📄 frameloader.cpp
字号:
ResourceRequest request(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy); if (executeIfJavaScriptURL(request.url(), userGesture)) return; urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture);}void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList){ FrameLoadRequest copy = request; if (copy.resourceRequest().httpReferrer().isEmpty()) copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer); addHTTPOriginIfNeeded(copy.resourceRequest(), outgoingOrigin()); loadFrameRequestWithFormAndValues(copy, lockHistory, lockBackForwardList, event, 0, HashMap<String, String>());} void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture){ if (executeIfJavaScriptURL(request.url(), userGesture, false)) return; String target = _target; if (target.isEmpty()) target = m_frame->document()->baseTarget(); FrameLoadRequest frameRequest(request, target); urlSelected(frameRequest, triggeringEvent, lockHistory, lockBackForwardList);}bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName){ // Support for <frame src="javascript:string"> KURL scriptURL; KURL url; if (protocolIs(urlString, "javascript")) { scriptURL = completeURL(urlString); // completeURL() encodes the URL. url = blankURL(); } else url = completeURL(urlString); Frame* frame = ownerElement->contentFrame(); if (frame) frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, userGestureHint()); else frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer); if (!frame) return false; if (!scriptURL.isEmpty()) frame->loader()->executeIfJavaScriptURL(scriptURL); return true;}Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer){ bool allowsScrolling = true; int marginWidth = -1; int marginHeight = -1; if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) { HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement); allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff; marginWidth = o->getMarginWidth(); marginHeight = o->getMarginHeight(); } if (!canLoad(url, referrer)) { FrameLoader::reportLocalLoadFailed(m_frame, url.string()); return 0; } bool hideReferrer = shouldHideReferrer(url, referrer); RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight); if (!frame) { checkCallImplicitClose(); return 0; } frame->loader()->m_isComplete = false; RenderObject* renderer = ownerElement->renderer(); FrameView* view = frame->view(); if (renderer && renderer->isWidget() && view) static_cast<RenderWidget*>(renderer)->setWidget(view); checkCallImplicitClose(); // In these cases, the synchronous load would have finished // before we could connect the signals, so make sure to send the // completed() signal for the child by hand // FIXME: In this case the Frame will have finished loading before // it's being added to the child list. It would be a good idea to // create the child first, then invoke the loader separately. if (url.isEmpty() || url == blankURL()) { frame->loader()->completed(); frame->loader()->checkCompleted(); } return frame.get();}void FrameLoader::submitFormAgain(){ if (m_isRunningScript) return; OwnPtr<FormSubmission> form(m_deferredFormSubmission.release()); if (!form) return; submitForm(form->action, form->url, form->formData, form->target, form->contentType, form->boundary, form->event.get(), form->lockHistory, form->lockBackForwardList);}void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData, const String& target, const String& contentType, const String& boundary, Event* event, bool lockHistory, bool lockBackForwardList){ ASSERT(formData); if (!m_frame->page()) return; KURL u = completeURL(url.isNull() ? "" : url); // FIXME: Do we really need to special-case an empty URL? // Would it be better to just go on with the form submisson and let the I/O fail? if (u.isEmpty()) return; if (u.protocolIs("javascript")) { m_isExecutingJavaScriptFormAction = true; executeIfJavaScriptURL(u, false, false); m_isExecutingJavaScriptFormAction = false; return; } if (m_isRunningScript) { if (m_deferredFormSubmission) return; m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target, contentType, boundary, event, lockHistory, lockBackForwardList)); return; } formData->generateFiles(m_frame->page()->chrome()->client()); FrameLoadRequest frameRequest; if (!m_outgoingReferrer.isEmpty()) frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); frameRequest.setFrameName(target.isEmpty() ? m_frame->document()->baseTarget() : target); // Handle mailto: forms bool isMailtoForm = equalIgnoringCase(u.protocol(), "mailto"); if (isMailtoForm && strcmp(action, "GET") != 0) { // Append body= for POST mailto, replace the whole query string for GET one. String body = formData->flattenToString(); String query = u.query(); if (!query.isEmpty()) query.append('&'); u.setQuery(query + body); } if (strcmp(action, "GET") == 0) { u.setQuery(formData->flattenToString()); } else { if (!isMailtoForm) frameRequest.resourceRequest().setHTTPBody(formData.get()); frameRequest.resourceRequest().setHTTPMethod("POST"); // construct some user headers if necessary if (contentType.isNull() || contentType == "application/x-www-form-urlencoded") frameRequest.resourceRequest().setHTTPContentType(contentType); else // contentType must be "multipart/form-data" frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary); } frameRequest.resourceRequest().setURL(u); addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); submitForm(frameRequest, event, lockHistory, lockBackForwardList);}void FrameLoader::stopLoading(bool sendUnload){ if (m_frame->document() && m_frame->document()->tokenizer()) m_frame->document()->tokenizer()->stopParsing(); if (sendUnload) { if (m_frame->document()) { if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) { Node* currentFocusedNode = m_frame->document()->focusedNode(); if (currentFocusedNode) currentFocusedNode->aboutToUnload(); m_frame->document()->dispatchWindowEvent(eventNames().unloadEvent, false, false); if (m_frame->document()) m_frame->document()->updateRendering(); m_wasUnloadEventEmitted = true; if (m_frame->eventHandler()->pendingFrameUnloadEventCount()) m_frame->eventHandler()->clearPendingFrameUnloadEventCount(); if (m_frame->eventHandler()->pendingFrameBeforeUnloadEventCount()) m_frame->eventHandler()->clearPendingFrameBeforeUnloadEventCount(); } } if (m_frame->document() && !m_frame->document()->inPageCache()) m_frame->document()->removeAllEventListenersFromAllNodes(); } m_isComplete = true; // to avoid calling completed() in finishedParsing() (David) m_isLoadingMainResource = false; m_didCallImplicitClose = true; // don't want that one either if (m_frame->document() && m_frame->document()->parsing()) { finishedParsing(); m_frame->document()->setParsing(false); } m_workingURL = KURL(); if (Document* doc = m_frame->document()) { if (DocLoader* docLoader = doc->docLoader()) cache()->loader()->cancelRequests(docLoader);#if ENABLE(DATABASE) doc->stopDatabases();#endif } // tell all subframes to stop as well for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) child->loader()->stopLoading(sendUnload); cancelRedirection();}void FrameLoader::stop(){ // http://bugs.webkit.org/show_bug.cgi?id=10854 // The frame's last ref may be removed and it will be deleted by checkCompleted(). RefPtr<Frame> protector(m_frame); if (m_frame->document()->tokenizer()) m_frame->document()->tokenizer()->stopParsing(); m_frame->document()->finishParsing(); if (m_iconLoader) m_iconLoader->stopLoading();}bool FrameLoader::closeURL(){ saveDocumentState(); stopLoading(true); m_frame->editor()->clearUndoRedoOperations(); return true;}void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress){ m_cancellingWithLoadInProgress = cancelWithLoadInProgress; stopRedirectionTimer(); m_scheduledRedirection.clear();}KURL FrameLoader::iconURL(){ // If this isn't a top level frame, return nothing if (m_frame->tree() && m_frame->tree()->parent()) return KURL(); // If we have an iconURL from a Link element, return that if (!m_frame->document()->iconURL().isEmpty()) return KURL(m_frame->document()->iconURL()); // Don't return a favicon iconURL unless we're http or https if (!m_URL.protocolIs("http") && !m_URL.protocolIs("https")) return KURL(); KURL url; url.setProtocol(m_URL.protocol()); url.setHost(m_URL.host()); if (int port = m_URL.port()) url.setPort(port); url.setPath("/favicon.ico"); return url;}bool FrameLoader::didOpenURL(const KURL& url){ if (m_scheduledRedirection && m_scheduledRedirection->type == ScheduledRedirection::locationChangeDuringLoad) // A redirect was scheduled before the document was created. // This can happen when one frame changes another frame's location. return false; cancelRedirection(); m_frame->editor()->clearLastEditCommand(); closeURL(); m_isComplete = false; m_isLoadingMainResource = true; m_didCallImplicitClose = false; m_frame->setJSStatusBarText(String()); m_frame->setJSDefaultStatusBarText(String()); m_URL = url; if ((m_URL.protocolIs("http") || m_URL.protocolIs("https")) && !m_URL.host().isEmpty() && m_URL.path().isEmpty()) m_URL.setPath("/"); m_workingURL = m_URL; started(); return true;}void FrameLoader::didExplicitOpen(){ m_isComplete = false; m_didCallImplicitClose = false; // Calling document.open counts as committing the first real document load. m_committedFirstRealDocumentLoad = true; // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results // from a subsequent window.document.open / window.document.write call. // Cancelling redirection here works for all cases because document.open // implicitly precedes document.write. cancelRedirection(); if (m_frame->document()->url() != blankURL()) m_URL = m_frame->document()->url();}bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument){ if (!url.protocolIs("javascript")) return false; if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) return true; String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); ScriptValue result = executeScript(script, userGesture); String scriptResult; if (!result.getString(scriptResult)) return true; SecurityOrigin* currentSecurityOrigin = 0; currentSecurityOrigin = m_frame->document()->securityOrigin(); // FIXME: We should always replace the document, but doing so // synchronously can cause crashes: // http://bugs.webkit.org/show_bug.cgi?id=16782 if (replaceDocument) { begin(m_URL, true, currentSecurityOrigin); write(scriptResult); end(); } return true;}ScriptValue FrameLoader::executeScript(const String& script, bool forceUserGesture){ return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_URL));}ScriptValue FrameLoader::executeScript(const ScriptSourceCode& sourceCode){ if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused()) return ScriptValue(); bool wasRunningScript = m_isRunningScript; m_isRunningScript = true; ScriptValue result = m_frame->script()->evaluate(sourceCode); if (!wasRunningScript) { m_isRunningScript = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -