📄 frameloader.cpp
字号:
if (m_encodingWasChosenByUser && !m_encoding.isEmpty()) return m_encoding; if (m_decoder && m_decoder->encoding().isValid()) return m_decoder->encoding().name(); Settings* settings = m_frame->settings(); return settings ? settings->defaultTextEncodingName() : String();}bool FrameLoader::gotoAnchor(const String& name){ ASSERT(m_frame->document()); if (!m_frame->document()->haveStylesheetsLoaded()) { m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); return false; } m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); Element* anchorNode = m_frame->document()->findAnchor(name);#if ENABLE(SVG) if (m_frame->document()->isSVGDocument()) { if (name.startsWith("xpointer(")) { // We need to parse the xpointer reference here } else if (name.startsWith("svgView(")) { RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement(); if (!svg->currentView()->parseViewSpec(name)) return false; svg->setUseCurrentView(true); } else { if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) { RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0; if (viewElement.get()) { RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get())); svg->inheritViewAttributes(viewElement.get()); } } } // FIXME: need to decide which <svg> to focus on, and zoom to that one // FIXME: need to actually "highlight" the viewTarget(s) }#endif m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target. // Implement the rule that "" and "top" both mean top of page as in other browsers. if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top"))) return false; // We need to update the layout before scrolling, otherwise we could // really mess things up if an anchor scroll comes at a bad moment. m_frame->document()->updateRendering(); // Only do a layout if changes have occurred that make it necessary. if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) m_frame->view()->layout(); // Scroll nested layers and frames to reveal the anchor. // Align to the top and to the closest side (this matches other browsers). RenderObject* renderer; IntRect rect; if (!anchorNode) renderer = m_frame->document()->renderer(); // top of document else { renderer = anchorNode->renderer(); rect = anchorNode->getRect(); } if (renderer) renderer->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); return true;}bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues){ if (url.isEmpty() && mimeType.isEmpty()) return false; KURL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); bool useFallback; if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) { Settings* settings = m_frame->settings(); if (!settings || !settings->arePluginsEnabled() || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) return false; return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback); } ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag)); HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node()); // FIXME: OK to always make a new frame? When does the old frame get removed? return loadSubframe(element, completedURL, frameName, m_outgoingReferrer);}bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback){ if (m_client->shouldUsePluginDocument(mimeType)) { useFallback = false; return true; } // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that // can handle TIFF (which QuickTime can also handle) they probably intended to override QT. if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) { const PluginData* pluginData = m_frame->page()->pluginData(); String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String(); if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) return true; } ObjectContentType objectType = m_client->objectContentType(url, mimeType); // If an object's content can't be handled and it has no fallback, let // it be handled as a plugin to show the broken plugin icon. useFallback = objectType == ObjectContentNone && hasFallback; return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;}static HTMLPlugInElement* toPlugInElement(Node* node){ if (!node) return 0;#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) || node->hasTagName(videoTag) || node->hasTagName(audioTag) || node->hasTagName(appletTag));#else ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) || node->hasTagName(appletTag));#endif return static_cast<HTMLPlugInElement*>(node);} bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback){ Widget* widget = 0; if (renderer && !useFallback) { HTMLPlugInElement* element = toPlugInElement(renderer->node()); if (!canLoad(url, String(), frame()->document())) { FrameLoader::reportLocalLoadFailed(m_frame, url.string()); return false; } widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), element, url, paramNames, paramValues, mimeType, m_frame->document()->isPluginDocument()); if (widget) { renderer->setWidget(widget); m_containsPlugIns = true; } } return widget != 0;}void FrameLoader::clearRecordedFormValues(){ m_formAboutToBeSubmitted = 0; m_formValuesAboutToBeSubmitted.clear();}void FrameLoader::setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element){ m_formAboutToBeSubmitted = element;}void FrameLoader::recordFormValue(const String& name, const String& value){ m_formValuesAboutToBeSubmitted.set(name, value);}void FrameLoader::parentCompleted(){ if (m_scheduledRedirection && !m_redirectionTimer.isActive()) startRedirectionTimer();}String FrameLoader::outgoingReferrer() const{ return m_outgoingReferrer;}String FrameLoader::outgoingOrigin() const{ return m_frame->document()->securityOrigin()->toString();}Frame* FrameLoader::opener(){ return m_opener;}void FrameLoader::setOpener(Frame* opener){ if (m_opener) m_opener->loader()->m_openedFrames.remove(m_frame); if (opener) opener->loader()->m_openedFrames.add(m_frame); m_opener = opener; if (m_frame->document()) { m_frame->document()->initSecurityContext(); m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin()); }}bool FrameLoader::openedByDOM() const{ return m_openedByDOM;}void FrameLoader::setOpenedByDOM(){ m_openedByDOM = true;}void FrameLoader::handleFallbackContent(){ HTMLFrameOwnerElement* owner = m_frame->ownerElement(); if (!owner || !owner->hasTagName(objectTag)) return; static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();}void FrameLoader::provisionalLoadStarted(){ Page* page = m_frame->page(); // this is used to update the current history item // in the event of a navigation aytime during loading m_navigationDuringLoad = false; if (page) { Document *document = page->mainFrame()->document(); m_navigationDuringLoad = !page->mainFrame()->loader()->isComplete() || (document && document->processingLoadEvent()); } m_firstLayoutDone = false; cancelRedirection(true); m_client->provisionalLoadStarted();}bool FrameLoader::userGestureHint(){ Frame* frame = m_frame->tree()->top(); if (!frame->script()->isEnabled()) return true; // If JavaScript is disabled, a user gesture must have initiated the navigation. return frame->script()->processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.}void FrameLoader::didNotOpenURL(const KURL& url){ if (m_submittedFormURL == url) m_submittedFormURL = KURL();}void FrameLoader::resetMultipleFormSubmissionProtection(){ m_submittedFormURL = KURL();}void FrameLoader::setEncoding(const String& name, bool userChosen){ if (!m_workingURL.isEmpty()) receivedFirstData(); m_encoding = name; m_encodingWasChosenByUser = userChosen;}void FrameLoader::addData(const char* bytes, int length){ ASSERT(m_workingURL.isEmpty()); ASSERT(m_frame->document()); ASSERT(m_frame->document()->parsing()); write(bytes, length);}bool FrameLoader::canCachePageContainingThisFrame(){ return m_documentLoader && m_documentLoader->mainDocumentError().isNull() && !m_frame->tree()->childCount() // FIXME: If we ever change this so that frames with plug-ins will be cached, // we need to make sure that we don't cache frames that have outstanding NPObjects // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in, // they would need to be destroyed and then recreated, and there is no way that we can recreate // the right NPObjects. See <rdar://problem/5197041> for more information. && !m_containsPlugIns && !m_URL.protocolIs("https") && !m_frame->document()->hasWindowEventListener(eventNames().unloadEvent)#if ENABLE(DATABASE) && !m_frame->document()->hasOpenDatabases()#endif && !m_frame->document()->usingGeolocation() && m_currentHistoryItem && !isQuickRedirectComing() && !m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping() && m_frame->document()->canSuspendActiveDOMObjects()#if ENABLE(OFFLINE_WEB_APPLICATIONS) // FIXME: We should investigating caching frames that have an associated // application cache. <rdar://problem/5917899> tracks that work. && !m_documentLoader->applicationCache() && !m_documentLoader->candidateApplicationCacheGroup()#endif && m_client->canCachePage() ;}bool FrameLoader::canCachePage(){#ifndef NDEBUG logCanCachePageDecision();#endif // Cache the page, if possible. // Don't write to the cache if in the middle of a redirect, since we will want to // store the final page we end up on. // No point writing to the cache on a reload or loadSame, since we will just write // over it again when we leave that page. // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they // are the most interesting pages on the web, and often those that would benefit the most from caching! FrameLoadType loadType = this->loadType(); return !m_frame->tree()->parent() && canCachePageContainingThisFrame() && m_frame->page() && m_frame->page()->backForwardList()->enabled() && m_frame->page()->backForwardList()->capacity() > 0 && m_frame->page()->settings()->usesPageCache() && loadType != FrameLoadTypeReload && loadType != FrameLoadTypeReloadFromOrigin && loadType != FrameLoadTypeSame ;}#ifndef NDEBUGstatic String& pageCacheLogPrefix(int indentLevel){ static int previousIndent = -1; DEFINE_STATIC_LOCAL(String, prefix, ()); if (indentLevel != previousIndent) { previousIndent = indentLevel; prefix.truncate(0); for (int i = 0; i < previousIndent; ++i) prefix += " "; } return prefix;}static void pageCacheLog(const String& prefix, const String& message){ LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());}#define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), String::format(__VA_ARGS__))void FrameLoader::logCanCachePageDecision(){ // Only bother logging for main frames that have actually loaded and have content. if (m_creatingInitialEmptyDocument) return; KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL(); if (currentURL.isEmpty()) return; int indentLevel = 0; PCLOG("--------\n Determining if page can be cached:"); bool cannotCache = !logCanCacheFrame
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -