📄 webview.mm
字号:
// 2) unload events need to be called if (applicationIsTerminating && !fullDocumentTeardown) { [self _closeWithFastTeardown]; return; } if (Frame* mainFrame = core([self mainFrame])) mainFrame->loader()->detachFromParent(); [self _removeFromAllWebViewsSet]; [self setHostWindow:nil]; [self setDownloadDelegate:nil]; [self setEditingDelegate:nil]; [self setFrameLoadDelegate:nil]; [self setPolicyDelegate:nil]; [self setResourceLoadDelegate:nil]; [self setScriptDebugDelegate:nil]; [self setUIDelegate:nil]; [_private->inspector webViewClosed]; // setHostWindow:nil must be called before this value is set (see 5408186) _private->closed = YES; // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint. [self removeDragCaret]; // Deleteing the WebCore::Page will clear the page cache so we call destroy on // all the plug-ins in the page cache to break any retain cycles. // See comment in HistoryItem::releaseAllPendingPageCaches() for more information. delete _private->page; _private->page = 0; if (_private->hasSpellCheckerDocumentTag) { [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag]; _private->hasSpellCheckerDocumentTag = NO; } [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]]; _private->preferences = nil; [preferences didRemoveFromWebView]; [preferences release]; [self _closePluginDatabases];#ifndef NDEBUG // Need this to make leak messages accurate. if (applicationIsTerminating) { gcController().garbageCollectNow(); [WebCache setDisabled:YES]; }#endif}+ (NSString *)_MIMETypeForFile:(NSString *)path{ NSString *extension = [path pathExtension]; NSString *MIMEType = nil; // Get the MIME type from the extension. if ([extension length] != 0) { MIMEType = WKGetMIMETypeForExtension(extension); } // If we can't get a known MIME type from the extension, sniff. if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) { NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path]; NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH]; [handle closeFile]; if ([data length] != 0) { MIMEType = [data _webkit_guessedMIMEType]; } if ([MIMEType length] == 0) { MIMEType = @"application/octet-stream"; } } return MIMEType;}- (WebDownload *)_downloadURL:(NSURL *)URL{ ASSERT(URL); NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL]; WebDownload *download = [WebDownload _downloadWithRequest:request delegate:_private->downloadDelegate directory:nil]; [request release]; return download;}- (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request{ NSDictionary *features = [[NSDictionary alloc] init]; WebView *newWindowWebView = [[self _UIDelegateForwarder] webView:self createWebViewWithRequest:nil windowFeatures:features]; [features release]; if (!newWindowWebView) return nil; CallUIDelegate(newWindowWebView, @selector(webViewShow:)); return newWindowWebView;}- (WebInspector *)inspector{ if (!_private->inspector) _private->inspector = [[WebInspector alloc] initWithWebView:self]; return _private->inspector;}- (WebCore::Page*)page{ return _private->page;}- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items{ NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items]; NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems); if (!menuItems) return nil; unsigned count = [menuItems count]; if (!count) return nil; NSMenu *menu = [[NSMenu alloc] init]; for (unsigned i = 0; i < count; i++) [menu addItem:[menuItems objectAtIndex:i]]; return [menu autorelease];}- (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags{ // We originally intended to call this delegate method sometimes with a nil dictionary, but due to // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients. if (!dictionary) return; CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);}- (void)_loadBackForwardListFromOtherView:(WebView *)otherView{ if (!_private->page) return; if (!otherView->_private->page) return; // It turns out the right combination of behavior is done with the back/forward load // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items // in the back forward list, and go to the current one. BackForwardList* backForwardList = _private->page->backForwardList(); ASSERT(!backForwardList->currentItem()); // destination list should be empty BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList(); if (!otherBackForwardList->currentItem()) return; // empty back forward list, bail HistoryItem* newItemToGoTo = 0; int lastItemIndex = otherBackForwardList->forwardListCount(); for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) { if (i == 0) { // If this item is showing , save away its current scroll and form state, // since that might have changed since loading and it is normally not saved // until we leave that page. otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState(); } RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy(); if (i == 0) newItemToGoTo = newItem.get(); backForwardList->addItem(newItem.release()); } ASSERT(newItemToGoTo); _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);}- (void)_setFormDelegate: (id<WebFormDelegate>)delegate{ _private->formDelegate = delegate;}- (id<WebFormDelegate>)_formDelegate{ return _private->formDelegate;}- (BOOL)_needsAdobeFrameReloadingQuirk{ static BOOL checked = NO; static BOOL needsQuirk = NO; if (checked) return needsQuirk; needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0) || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0) || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0) || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0) || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2) || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1) || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1) || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1) || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1) || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2); checked = YES; return needsQuirk;}- (BOOL)_needsKeyboardEventDisambiguationQuirks{ static BOOL checked = NO; static BOOL needsQuirks = NO; if (checked) return needsQuirks; needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && ![[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]; checked = YES; return needsQuirks;}- (void)_preferencesChangedNotification:(NSNotification *)notification{ WebPreferences *preferences = (WebPreferences *)[notification object]; ASSERT(preferences == [self preferences]); if (!_private->userAgentOverridden) _private->userAgent = String(); // Cache this value so we don't have to read NSUserDefaults on each page load _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing]; // Update corresponding WebCore Settings object. if (!_private->page) return; Settings* settings = _private->page->settings(); settings->setCursiveFontFamily([preferences cursiveFontFamily]); settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]); settings->setDefaultFontSize([preferences defaultFontSize]); settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]); settings->setFantasyFontFamily([preferences fantasyFontFamily]); settings->setFixedFontFamily([preferences fixedFontFamily]); settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]); settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]); settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]); settings->setJavaEnabled([preferences isJavaEnabled]); settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]); settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]); settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]); settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]); settings->setMinimumFontSize([preferences minimumFontSize]); settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]); settings->setPluginsEnabled([preferences arePlugInsEnabled]); settings->setDatabasesEnabled([preferences databasesEnabled]); settings->setLocalStorageEnabled([preferences localStorageEnabled]); settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]); settings->setSansSerifFontFamily([preferences sansSerifFontFamily]); settings->setSerifFontFamily([preferences serifFontFamily]); settings->setStandardFontFamily([preferences standardFontFamily]); settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]); settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]); settings->setTextAreasAreResizable([preferences textAreasAreResizable]); settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]); settings->setEditableLinkBehavior(core([preferences editableLinkBehavior])); settings->setTextDirectionSubmenuInclusionBehavior(core([preferences textDirectionSubmenuInclusionBehavior])); settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]); settings->setUsesPageCache([self usesPageCache]); settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]); settings->setDeveloperExtrasEnabled([preferences developerExtrasEnabled]); settings->setAuthorAndUserStylesEnabled([preferences authorAndUserStylesEnabled]); settings->setApplicationChromeMode([preferences applicationChromeModeEnabled]); if ([preferences userStyleSheetEnabled]) { NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString]; settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]); } else settings->setUserStyleSheetLocation([NSURL URLWithString:@""]); settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]); settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]); settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing); settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]); settings->disableRangeMutationForOldAppleMail(WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0)); settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]); settings->setZoomsTextOnly([preferences zoomsTextOnly]); settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1));}static inline IMP getMethod(id o, SEL s){ return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;}- (void)_cacheResourceLoadDelegateImplementations{ WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations; id delegate = _private->resourceProgressDelegate; if (!delegate) { bzero(cache, sizeof(WebResourceDelegateImplementationCache)); return; } cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:)); cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:)); cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:)); cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:)); cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:)); cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:)); cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:)); cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)); cache->shouldUseCredentialStorageFunc = getMethod(delegate, @selector(webView:resource:shouldUseCredentialStorageForDataSource:));}WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView){ static WebResourceDelegateImplementationCache empty; if (!webView) return ∅ return &webView->_private->resourceLoadDelegateImplementations;}- (void)_cacheFrameLoadDelegateImplementations{ WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations; id delegate = _private->frameLoadDelegate; if (!delegate) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -