📄 webview.mm
字号:
[standardPreferences willAddToWebView]; _private->preferences = [standardPreferences retain]; _private->catchesDelegateExceptions = YES; _private->mainFrameDocumentReady = NO; _private->drawsBackground = YES; _private->smartInsertDeleteEnabled = YES; _private->backgroundColor = [[NSColor whiteColor] retain]; _private->useDocumentViews = usesDocumentViews; WebFrameView *frameView = nil; if (_private->useDocumentViews) { NSRect f = [self frame]; frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)]; [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [self addSubview:frameView]; [frameView release]; } static bool didOneTimeInitialization = false; if (!didOneTimeInitialization) { WebKitInitializeLoggingChannelsIfNecessary(); WebCore::InitializeLoggingChannelsIfNecessary(); [WebHistoryItem initWindowWatcherIfNecessary]; WebKitInitializeDatabasesIfNecessary(); WebKitInitializeApplicationCachePathIfNecessary(); patchMailRemoveAttributesMethod(); didOneTimeInitialization = true; } _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self)); _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]); [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView];#ifndef BUILDING_ON_TIGER if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES)) [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; else [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];#endif [self _addToAllWebViewsSet]; [self setGroupName:groupName]; // If there's already a next key view (e.g., from a nib), wire it up to our // contained frame view. In any case, wire our next key view up to the our // contained frame view. This works together with our becomeFirstResponder // and setNextKeyView overrides. NSView *nextKeyView = [self nextKeyView]; if (nextKeyView && nextKeyView != frameView) [frameView setNextKeyView:nextKeyView]; [super setNextKeyView:frameView]; ++WebViewCount; [self _registerDraggedTypes]; WebPreferences *prefs = [self preferences]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:prefs]; // Post a notification so the WebCore settings update. [[self preferences] _postPreferencesChangesNotification]; if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { // Originally, we allowed all local loads. FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForAll); } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { // Later, we allowed local loads for local URLs and documents loaded // with substitute data. FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForLocalAndSubstituteData); }}- (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews{ self = [super initWithFrame:f]; if (!self) return nil;#ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the // need for Safari to unset it to prevent it from being passed to applications it launches. // Unsetting it when a WebView is first created is as good a place as any. // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details. if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) { unsetenv("DYLD_FRAMEWORK_PATH"); unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"); }#endif _private = [[WebViewPrivate alloc] init]; [self _commonInitializationWithFrameName:frameName groupName:groupName usesDocumentViews:usesDocumentViews]; [self setMaintainsBackForwardList: YES]; return self;}- (void)_boundsChanged{ Frame* frame = core([self mainFrame]); IntSize oldSize = frame->view()->frameRect().size(); frame->view()->resize([self bounds].size.width, [self bounds].size.height); if (oldSize != frame->view()->frameRect().size()) [self setNeedsDisplay: YES];}- (BOOL)_mustDrawUnionedRect:(NSRect)rect singleRects:(const NSRect *)rects count:(NSInteger)count{ // If count == 0 here, use the rect passed in for drawing. This is a workaround for: // <rdar://problem/3908282> REGRESSION (Mail): No drag image dragging selected text in Blot and Mail // The reason for the workaround is that this method is called explicitly from the code // to generate a drag image, and at that time, getRectsBeingDrawn:count: will return a zero count. const int cRectThreshold = 10; const float cWastedSpaceThreshold = 0.75f; BOOL useUnionedRect = (count <= 1) || (count > cRectThreshold); if (!useUnionedRect) { // Attempt to guess whether or not we should use the unioned rect or the individual rects. // We do this by computing the percentage of "wasted space" in the union. If that wasted space // is too large, then we will do individual rect painting instead. float unionPixels = (rect.size.width * rect.size.height); float singlePixels = 0; for (int i = 0; i < count; ++i) singlePixels += rects[i].size.width * rects[i].size.height; float wastedSpace = 1 - (singlePixels / unionPixels); if (wastedSpace <= cWastedSpaceThreshold) useUnionedRect = YES; } return useUnionedRect;}- (void)drawSingleRect:(NSRect)rect{ ASSERT(!_private->useDocumentViews); [NSGraphicsContext saveGraphicsState]; NSRectClip(rect); @try { [[self mainFrame] _drawRect:rect contentsOnly:NO]; WebView *webView = [self _webView]; [[webView _UIDelegateForwarder] webView:webView didDrawRect:rect]; if (WebNodeHighlight *currentHighlight = [webView currentNodeHighlight]) [currentHighlight setNeedsUpdateInTargetViewRect:rect]; [NSGraphicsContext restoreGraphicsState]; } @catch (NSException *localException) { [NSGraphicsContext restoreGraphicsState]; LOG_ERROR("Exception caught while drawing: %@", localException); [localException raise]; }}- (BOOL)isFlipped { return _private && !_private->useDocumentViews;}#ifndef BUILDING_ON_TIGER- (void)viewWillDraw{ if (!_private->useDocumentViews) { Frame* frame = core([self mainFrame]); if (frame && frame->view()) frame->view()->layoutIfNeededRecursive(); } [super viewWillDraw];}#endif- (void)drawRect:(NSRect)rect{ if (_private->useDocumentViews) return [super drawRect:rect]; ASSERT_MAIN_THREAD(); const NSRect *rects; NSInteger count; [self getRectsBeingDrawn:&rects count:&count]; if ([self _mustDrawUnionedRect:rect singleRects:rects count:count]) [self drawSingleRect:rect]; else for (int i = 0; i < count; ++i) [self drawSingleRect:rects[i]];}+ (NSArray *)_supportedMIMETypes{ // Load the plug-in DB allowing plug-ins to install types. [WebPluginDatabase sharedDatabase]; return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];}+ (NSArray *)_supportedFileExtensions{ NSMutableSet *extensions = [[NSMutableSet alloc] init]; NSArray *MIMETypes = [self _supportedMIMETypes]; NSEnumerator *enumerator = [MIMETypes objectEnumerator]; NSString *MIMEType; while ((MIMEType = [enumerator nextObject]) != nil) { NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType); if (extensionsForType) { [extensions addObjectsFromArray:extensionsForType]; } } NSArray *uniqueExtensions = [extensions allObjects]; [extensions release]; return uniqueExtensions;}+ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType{ MIMEType = [MIMEType lowercaseString]; Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) { // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed. // Load the plug-in DB allowing plug-ins to install types. [WebPluginDatabase sharedDatabase]; // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types. viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; } if (viewClass && repClass) { // Special-case WebHTMLView for text types that shouldn't be shown. if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class] && [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) { return NO; } if (vClass) *vClass = viewClass; if (rClass) *rClass = repClass; return YES; } return NO;}- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType{ if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType]) return YES; if (_private->pluginDatabase) { WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType]; if (pluginPackage) { if (vClass) *vClass = [WebHTMLView class]; if (rClass) *rClass = [WebHTMLRepresentation class]; return YES; } } return NO;}+ (void)_setAlwaysUseATSU:(BOOL)f{ [self _setAlwaysUsesComplexTextCodePath:f];}+ (void)_setAlwaysUsesComplexTextCodePath:(BOOL)f{ WebCoreSetAlwaysUsesComplexTextCodePath(f);}+ (BOOL)canShowFile:(NSString *)path{ return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];}+ (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type{ return WKGetPreferredExtensionForMIMEType(type);}- (BOOL)_isClosed{ return !_private || _private->closed;}- (void)_closePluginDatabases{ pluginDatabaseClientCount--; // Close both sets of plug-in databases because plug-ins need an opportunity to clean up files, etc. // Unload the WebView local plug-in database. if (_private->pluginDatabase) { [_private->pluginDatabase destroyAllPluginInstanceViews]; [_private->pluginDatabase close]; [_private->pluginDatabase release]; _private->pluginDatabase = nil; } // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles. if (!pluginDatabaseClientCount && applicationIsTerminating) [WebPluginDatabase closeSharedDatabase];}- (void)_closeWithFastTeardown {#ifndef NDEBUG WTF::RefCountedLeakCounter::suppressMessages("At least one WebView was closed with fast teardown.");#endif // Dispatch unload events. // FIXME: Shouldn't have to use a RefPtr here -- keeping the frame alive while stopping it // should be WebCore's responsibility -- but we do as of the time this comment was written. RefPtr<Frame> mainFrame = core([self mainFrame]); if (mainFrame && mainFrame->page() && mainFrame->page()->pendingUnloadEventCount()) mainFrame->loader()->stopLoading(true); _private->closed = YES; [self _closePluginDatabases];}// _close is here only for backward compatibility; clients and subclasses should use// public method -close instead.- (void)_close{ if (!_private || _private->closed) return;#ifndef NDEBUG WTF::RefCountedLeakCounter::cancelMessageSuppression(webViewIsOpen);#endif WebPreferences *preferences = _private->preferences; BOOL fullDocumentTeardown = [preferences fullDocumentTeardownEnabled]; // To quit the apps fast we skip document teardown. Two exceptions: // 1) plugins need to be destroyed and unloaded
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -