diff options
author | Kristian Monsen <kristianm@google.com> | 2010-06-28 16:42:48 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-07-02 10:29:56 +0100 |
commit | 06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch) | |
tree | 20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/loader | |
parent | 72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff) | |
download | external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.zip external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.gz external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.bz2 |
Merge WebKit at r61871: Initial merge by git.
Change-Id: I6cff43abca9cc4782e088a469ad4f03f166a65d5
Diffstat (limited to 'WebCore/loader')
36 files changed, 1117 insertions, 782 deletions
diff --git a/WebCore/loader/CachedFont.cpp b/WebCore/loader/CachedFont.cpp index af0c235..71dd8f9 100644 --- a/WebCore/loader/CachedFont.cpp +++ b/WebCore/loader/CachedFont.cpp @@ -136,7 +136,7 @@ bool CachedFont::ensureSVGFontData() { ASSERT(m_isSVGFont); if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) { - m_externalSVGDocument = SVGDocument::create(0); + m_externalSVGDocument = SVGDocument::create(0, KURL()); m_externalSVGDocument->open(); RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml"); diff --git a/WebCore/loader/CrossOriginPreflightResultCache.h b/WebCore/loader/CrossOriginPreflightResultCache.h index f8a7c55..8e5b239 100644 --- a/WebCore/loader/CrossOriginPreflightResultCache.h +++ b/WebCore/loader/CrossOriginPreflightResultCache.h @@ -24,8 +24,8 @@ * */ -#ifndef CrossOriginPreflightResultCacheItem_h -#define CrossOriginPreflightResultCacheItem_h +#ifndef CrossOriginPreflightResultCache_h +#define CrossOriginPreflightResultCache_h #include "KURLHash.h" #include "StringHash.h" diff --git a/WebCore/loader/DocumentWriter.cpp b/WebCore/loader/DocumentWriter.cpp index cc2632b..2ea1afd 100644 --- a/WebCore/loader/DocumentWriter.cpp +++ b/WebCore/loader/DocumentWriter.cpp @@ -34,6 +34,7 @@ #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" +#include "FrameLoaderStateMachine.h" #include "FrameView.h" #include "PlaceholderDocument.h" #include "PluginDocument.h" @@ -58,11 +59,26 @@ DocumentWriter::DocumentWriter(Frame* frame) { } -void DocumentWriter::replaceDocument(const String& html) +// This is only called by ScriptController::executeIfJavaScriptURL +// and always contains the result of evaluating a javascript: url. +// This is the <iframe src="javascript:'html'"> case. +void DocumentWriter::replaceDocument(const String& source) { m_frame->loader()->stopAllLoaders(); begin(m_frame->loader()->url(), true, m_frame->document()->securityOrigin()); - addData(html); + + if (!source.isNull()) { + if (!m_receivedData) { + m_receivedData = true; + m_frame->document()->setParseMode(Document::Strict); + } + + // FIXME: If we wanted to support the <img src='javascript:'imagedata'> + // case then we would need to call addData(char*, int) instead. + if (DocumentParser* parser = m_frame->document()->parser()) + parser->write(source, true); + } + end(); } @@ -79,13 +95,13 @@ void DocumentWriter::begin() begin(KURL()); } -PassRefPtr<Document> DocumentWriter::createDocument() +PassRefPtr<Document> DocumentWriter::createDocument(const KURL& url) { - if (!m_frame->loader()->isDisplayingInitialEmptyDocument() && m_frame->loader()->client()->shouldUsePluginDocument(m_mimeType)) - return PluginDocument::create(m_frame); + if (!m_frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && m_frame->loader()->client()->shouldUsePluginDocument(m_mimeType)) + return PluginDocument::create(m_frame, url); if (!m_frame->loader()->client()->hasHTMLView()) - return PlaceholderDocument::create(m_frame); - return DOMImplementation::createDocument(m_mimeType, m_frame, m_frame->inViewSourceMode()); + return PlaceholderDocument::create(m_frame, url); + return DOMImplementation::createDocument(m_mimeType, m_frame, url, m_frame->inViewSourceMode()); } void DocumentWriter::begin(const KURL& url, bool dispatch, SecurityOrigin* origin) @@ -96,20 +112,19 @@ void DocumentWriter::begin(const KURL& url, bool dispatch, SecurityOrigin* origi // Create a new document before clearing the frame, because it may need to // inherit an aliased security context. - RefPtr<Document> document = createDocument(); + RefPtr<Document> document = createDocument(url); // If the new document is for a Plugin but we're supposed to be sandboxed from Plugins, // then replace the document with one whose parser will ignore the incoming data (bug 39323) if (document->isPluginDocument() && m_frame->loader()->isSandboxed(SandboxPlugins)) - document = SinkDocument::create(m_frame); + document = SinkDocument::create(m_frame, url); - bool resetScripting = !(m_frame->loader()->isDisplayingInitialEmptyDocument() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url)); + bool resetScripting = !(m_frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url)); m_frame->loader()->clear(resetScripting, resetScripting); if (resetScripting) m_frame->script()->updatePlatformScriptObjects(); m_frame->loader()->setURL(url); - document->setURL(url); m_frame->setDocument(document); if (m_decoder) @@ -192,20 +207,6 @@ void DocumentWriter::addData(const char* str, int len, bool flush) } } -void DocumentWriter::addData(const String& str) -{ - if (str.isNull()) - return; - - if (!m_receivedData) { - m_receivedData = true; - m_frame->document()->setParseMode(Document::Strict); - } - - if (DocumentParser* parser = m_frame->document()->parser()) - parser->write(str, true); -} - void DocumentWriter::end() { m_frame->loader()->didEndDocument(); diff --git a/WebCore/loader/DocumentWriter.h b/WebCore/loader/DocumentWriter.h index a06fb7f..6644093 100644 --- a/WebCore/loader/DocumentWriter.h +++ b/WebCore/loader/DocumentWriter.h @@ -43,12 +43,13 @@ class DocumentWriter : public Noncopyable { public: DocumentWriter(Frame*); + // This is only called by ScriptController::executeIfJavaScriptURL + // and always contains the result of evaluating a javascript: url. void replaceDocument(const String&); void begin(); void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0); void addData(const char* string, int length = -1, bool flush = false); - void addData(const String&); void end(); void endIfNotLoadingMainResource(); void clear(); @@ -67,7 +68,7 @@ public: void setDecoder(TextResourceDecoder*); private: - PassRefPtr<Document> createDocument(); + PassRefPtr<Document> createDocument(const KURL&); Frame* m_frame; diff --git a/WebCore/loader/FTPDirectoryDocument.cpp b/WebCore/loader/FTPDirectoryDocument.cpp index 5d1b2bf..2a19fa3 100644 --- a/WebCore/loader/FTPDirectoryDocument.cpp +++ b/WebCore/loader/FTPDirectoryDocument.cpp @@ -29,7 +29,7 @@ #include "CharacterNames.h" #include "HTMLNames.h" #include "HTMLTableElement.h" -#include "HTMLDocumentParser.h" +#include "LegacyHTMLDocumentParser.h" #include "LocalizedStrings.h" #include "Logging.h" #include "FTPDirectoryParser.h" @@ -48,7 +48,7 @@ namespace WebCore { using namespace HTMLNames; -class FTPDirectoryDocumentParser : public HTMLDocumentParser { +class FTPDirectoryDocumentParser : public LegacyHTMLDocumentParser { public: FTPDirectoryDocumentParser(HTMLDocument*); @@ -80,7 +80,6 @@ private: void appendEntry(const String& name, const String& size, const String& date, bool isDirectory); PassRefPtr<Element> createTDForFilename(const String&); - Document* m_doc; RefPtr<HTMLTableElement> m_tableElement; bool m_skipLF; @@ -94,9 +93,8 @@ private: ListState m_listState; }; -FTPDirectoryDocumentParser::FTPDirectoryDocumentParser(HTMLDocument* doc) - : HTMLDocumentParser(doc, false) - , m_doc(doc) +FTPDirectoryDocumentParser::FTPDirectoryDocumentParser(HTMLDocument* document) + : LegacyHTMLDocumentParser(document, false) , m_skipLF(false) , m_parsedTemplate(false) , m_size(254) @@ -112,8 +110,8 @@ void FTPDirectoryDocumentParser::appendEntry(const String& filename, const Strin RefPtr<Element> rowElement = m_tableElement->insertRow(-1, ec); rowElement->setAttribute("class", "ftpDirectoryEntryRow", ec); - RefPtr<Element> element = m_doc->createElement(tdTag, false); - element->appendChild(Text::create(m_doc, String(&noBreakSpace, 1)), ec); + RefPtr<Element> element = document()->createElement(tdTag, false); + element->appendChild(Text::create(document(), String(&noBreakSpace, 1)), ec); if (isDirectory) element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeDirectory", ec); else @@ -124,13 +122,13 @@ void FTPDirectoryDocumentParser::appendEntry(const String& filename, const Strin element->setAttribute("class", "ftpDirectoryFileName", ec); rowElement->appendChild(element, ec); - element = m_doc->createElement(tdTag, false); - element->appendChild(Text::create(m_doc, date), ec); + element = document()->createElement(tdTag, false); + element->appendChild(Text::create(document(), date), ec); element->setAttribute("class", "ftpDirectoryFileDate", ec); rowElement->appendChild(element, ec); - element = m_doc->createElement(tdTag, false); - element->appendChild(Text::create(m_doc, size), ec); + element = document()->createElement(tdTag, false); + element->appendChild(Text::create(document(), size), ec); element->setAttribute("class", "ftpDirectoryFileSize", ec); rowElement->appendChild(element, ec); } @@ -139,17 +137,17 @@ PassRefPtr<Element> FTPDirectoryDocumentParser::createTDForFilename(const String { ExceptionCode ec; - String fullURL = m_doc->baseURL().string(); + String fullURL = document()->baseURL().string(); if (fullURL[fullURL.length() - 1] == '/') fullURL.append(filename); else fullURL.append("/" + filename); - RefPtr<Element> anchorElement = m_doc->createElement(aTag, false); + RefPtr<Element> anchorElement = document()->createElement(aTag, false); anchorElement->setAttribute("href", fullURL, ec); - anchorElement->appendChild(Text::create(m_doc, filename), ec); + anchorElement->appendChild(Text::create(document(), filename), ec); - RefPtr<Element> tdElement = m_doc->createElement(tdTag, false); + RefPtr<Element> tdElement = document()->createElement(tdTag, false); tdElement->appendChild(anchorElement, ec); return tdElement.release(); @@ -294,7 +292,7 @@ static inline PassRefPtr<SharedBuffer> createTemplateDocumentData(Settings* sett bool FTPDirectoryDocumentParser::loadDocumentTemplate() { - DEFINE_STATIC_LOCAL(RefPtr<SharedBuffer>, templateDocumentData, (createTemplateDocumentData(m_doc->settings()))); + DEFINE_STATIC_LOCAL(RefPtr<SharedBuffer>, templateDocumentData, (createTemplateDocumentData(document()->settings()))); // FIXME: Instead of storing the data, we'd rather actually parse the template data into the template Document once, // store that document, then "copy" it whenever we get an FTP directory listing. There are complexities with this // approach that make it worth putting this off. @@ -306,10 +304,10 @@ bool FTPDirectoryDocumentParser::loadDocumentTemplate() // Tokenize the template as an HTML document synchronously setForceSynchronous(true); - HTMLDocumentParser::write(String(templateDocumentData->data(), templateDocumentData->size()), true); + LegacyHTMLDocumentParser::write(String(templateDocumentData->data(), templateDocumentData->size()), true); setForceSynchronous(false); - RefPtr<Element> tableElement = m_doc->getElementById("ftpDirectoryTable"); + RefPtr<Element> tableElement = document()->getElementById("ftpDirectoryTable"); if (!tableElement) LOG_ERROR("Unable to find element by id \"ftpDirectoryTable\" in the template document."); else if (!tableElement->hasTagName(tableTag)) @@ -322,7 +320,7 @@ bool FTPDirectoryDocumentParser::loadDocumentTemplate() return true; // Otherwise create one manually - tableElement = m_doc->createElement(tableTag, false); + tableElement = document()->createElement(tableTag, false); m_tableElement = static_cast<HTMLTableElement*>(tableElement.get()); ExceptionCode ec; m_tableElement->setAttribute("id", "ftpDirectoryTable", ec); @@ -330,10 +328,10 @@ bool FTPDirectoryDocumentParser::loadDocumentTemplate() // If we didn't find the table element, lets try to append our own to the body // If that fails for some reason, cram it on the end of the document as a last // ditch effort - if (Element* body = m_doc->body()) + if (Element* body = document()->body()) body->appendChild(m_tableElement, ec); else - m_doc->appendChild(m_tableElement, ec); + document()->appendChild(m_tableElement, ec); return true; } @@ -344,13 +342,12 @@ void FTPDirectoryDocumentParser::createBasicDocument() // FIXME: Make this "basic document" more acceptable - - RefPtr<Element> bodyElement = m_doc->createElement(bodyTag, false); + RefPtr<Element> bodyElement = document()->createElement(bodyTag, false); ExceptionCode ec; - m_doc->appendChild(bodyElement, ec); + document()->appendChild(bodyElement, ec); - RefPtr<Element> tableElement = m_doc->createElement(tableTag, false); + RefPtr<Element> tableElement = document()->createElement(tableTag, false); m_tableElement = static_cast<HTMLTableElement*>(tableElement.get()); m_tableElement->setAttribute("id", "ftpDirectoryTable", ec); @@ -431,11 +428,11 @@ void FTPDirectoryDocumentParser::finish() m_tableElement = 0; fastFree(m_buffer); - HTMLDocumentParser::finish(); + LegacyHTMLDocumentParser::finish(); } -FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame) - : HTMLDocument(frame) +FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) { #ifndef NDEBUG LogFTP.state = WTFLogChannelOn; diff --git a/WebCore/loader/FTPDirectoryDocument.h b/WebCore/loader/FTPDirectoryDocument.h index f74508c..920f870 100644 --- a/WebCore/loader/FTPDirectoryDocument.h +++ b/WebCore/loader/FTPDirectoryDocument.h @@ -33,13 +33,13 @@ class DOMImplementation; class FTPDirectoryDocument : public HTMLDocument { public: - static PassRefPtr<FTPDirectoryDocument> create(Frame* frame) + static PassRefPtr<FTPDirectoryDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new FTPDirectoryDocument(frame)); + return adoptRef(new FTPDirectoryDocument(frame, url)); } private: - FTPDirectoryDocument(Frame*); + FTPDirectoryDocument(Frame*, const KURL&); virtual DocumentParser* createParser(); }; diff --git a/WebCore/loader/FormSubmission.cpp b/WebCore/loader/FormSubmission.cpp new file mode 100644 index 0000000..4d44174 --- /dev/null +++ b/WebCore/loader/FormSubmission.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FormSubmission.h" + +#include "Event.h" +#include "FormData.h" +#include "FormState.h" +#include "Frame.h" +#include "FrameLoadRequest.h" +#include "FrameLoader.h" +#include "HTMLFormElement.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +FormSubmission::FormSubmission(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event) + : m_method(method) + , m_action(action) + , m_target(target) + , m_contentType(contentType) + , m_formState(state) + , m_formData(data) + , m_boundary(boundary) + , m_lockHistory(lockHistory) + , m_event(event) +{ +} + +PassRefPtr<FormSubmission> FormSubmission::create(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event) +{ + return adoptRef(new FormSubmission(method, action, target, contentType, state, data, boundary, lockHistory, event)); +} + +void FormSubmission::populateFrameLoadRequest(FrameLoadRequest& frameRequest) +{ + if (!m_target.isEmpty()) + frameRequest.setFrameName(m_target); + + if (!m_referrer.isEmpty()) + frameRequest.resourceRequest().setHTTPReferrer(m_referrer); + + if (m_method == FormSubmission::GetMethod) + m_action.setQuery(m_formData->flattenToString()); + else { + frameRequest.resourceRequest().setHTTPMethod("POST"); + frameRequest.resourceRequest().setHTTPBody(m_formData); + + // construct some user headers if necessary + if (m_contentType.isNull() || m_contentType == "application/x-www-form-urlencoded") + frameRequest.resourceRequest().setHTTPContentType(m_contentType); + else // contentType must be "multipart/form-data" + frameRequest.resourceRequest().setHTTPContentType(m_contentType + "; boundary=" + m_boundary); + } + + frameRequest.resourceRequest().setURL(m_action); + FrameLoader::addHTTPOriginIfNeeded(frameRequest.resourceRequest(), m_origin); +} + +} diff --git a/WebCore/loader/FormSubmission.h b/WebCore/loader/FormSubmission.h new file mode 100644 index 0000000..647c6c6 --- /dev/null +++ b/WebCore/loader/FormSubmission.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FormSubmission_h +#define FormSubmission_h + +#include "KURL.h" + +namespace WebCore { + +class Event; +class FormData; +class FormState; +struct FrameLoadRequest; + +class FormSubmission : public RefCounted<FormSubmission> { +public: + enum Method { + GetMethod, + PostMethod + }; + + static PassRefPtr<FormSubmission> create(Method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState>, PassRefPtr<FormData>, const String& boundary, bool lockHistory, PassRefPtr<Event>); + + void populateFrameLoadRequest(FrameLoadRequest&); + + Method method() const { return m_method; } + const KURL& action() const { return m_action; } + String target() const { return m_target; } + void clearTarget() { m_target = String(); } + String contentType() const { return m_contentType; } + FormState* state() const { return m_formState.get(); } + FormData* data() const { return m_formData.get(); } + String boundary() const { return m_boundary; } + bool lockHistory() const { return m_lockHistory; } + Event* event() const { return m_event.get(); } + + const String& referrer() const { return m_referrer; } + void setReferrer(const String& referrer) { m_referrer = referrer; } + const String& origin() const { return m_origin; } + void setOrigin(const String& origin) { m_origin = origin; } + +private: + FormSubmission(Method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState>, PassRefPtr<FormData>, const String& boundary, bool lockHistory, PassRefPtr<Event>); + + Method m_method; + KURL m_action; + String m_target; + String m_contentType; + RefPtr<FormState> m_formState; + RefPtr<FormData> m_formData; + String m_boundary; + bool m_lockHistory; + RefPtr<Event> m_event; + String m_referrer; + String m_origin; +}; + +} + +#endif // FormSubmission_h diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index 7920e2e..3c622ee 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -55,6 +55,7 @@ #include "EventNames.h" #include "FloatRect.h" #include "FormState.h" +#include "FormSubmission.h" #include "Frame.h" #include "FrameLoadRequest.h" #include "FrameLoaderClient.h" @@ -64,12 +65,7 @@ #include "Geolocation.h" #endif // PLATFORM(ANDROID) #include "HTMLAnchorElement.h" -#include "HTMLAppletElement.h" #include "HTMLFormElement.h" -#include "HTMLFrameElement.h" -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "HTMLMediaElement.h" -#endif #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "HTTPParsers.h" @@ -92,11 +88,6 @@ #include "PluginDatabase.h" #include "PluginDocument.h" #include "ProgressTracker.h" -#include "RenderEmbeddedObject.h" -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "RenderVideo.h" -#endif -#include "RenderView.h" #include "ResourceHandle.h" #include "ResourceRequest.h" #include "ScriptController.h" @@ -106,20 +97,21 @@ #include "SecurityOrigin.h" #include "SegmentedString.h" #include "Settings.h" - -#if ENABLE(SHARED_WORKERS) -#include "SharedWorkerRepository.h" -#endif - #include "TextResourceDecoder.h" #include "WindowFeatures.h" -#include "XMLHttpRequest.h" #include "XMLDocumentParser.h" -#include "XSSAuditor.h" -#include <wtf/text/CString.h> #include <wtf/CurrentTime.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "HTMLMediaElement.h" +#include "RenderVideo.h" +#endif +#if ENABLE(SHARED_WORKERS) +#include "SharedWorkerRepository.h" +#endif #if ENABLE(SVG) #include "SVGDocument.h" @@ -138,16 +130,18 @@ namespace WebCore { +using namespace HTMLNames; + #if ENABLE(SVG) using namespace SVGNames; #endif -using namespace HTMLNames; #if ENABLE(XHTMLMP) static const char defaultAcceptHeader[] = "application/xml,application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; #else static const char defaultAcceptHeader[] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; #endif + static double storedTimeOfLastCompletedLoad; bool isBackForwardLoadType(FrameLoadType type) @@ -202,10 +196,10 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) , m_history(frame) , m_notifer(frame) , m_writer(frame) + , m_subframeLoader(frame) , m_state(FrameStateCommittedPage) , m_loadType(FrameLoadTypeStandard) , m_delegateIsHandlingProvisionalLoadError(false) - , m_firstLayoutDone(false) , m_quickRedirectComing(false) , m_sentRedirectNotification(false) , m_inStopAllLoaders(false) @@ -216,15 +210,10 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) , m_isComplete(false) , m_isLoadingMainResource(false) , m_needsClear(false) - , m_receivedData(false) - , m_containsPlugIns(false) , m_checkTimer(this, &FrameLoader::checkTimerFired) , m_shouldCallCheckCompleted(false) , m_shouldCallCheckLoadComplete(false) , m_opener(0) - , m_creatingInitialEmptyDocument(false) - , m_isDisplayingInitialEmptyDocument(false) - , m_committedFirstRealDocumentLoad(false) , m_didPerformFirstNavigation(false) , m_loadingFromCachedPage(false) , m_suppressOpenerInNewFrame(false) @@ -254,8 +243,7 @@ void FrameLoader::init() updateSandboxFlags(); // this somewhat odd set of steps is needed to give the frame an initial empty document - m_isDisplayingInitialEmptyDocument = false; - m_creatingInitialEmptyDocument = true; + m_stateMachine.advanceTo(FrameLoaderStateMachine::CreatingInitialEmptyDocument); setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get()); setProvisionalDocumentLoader(m_policyDocumentLoader.get()); setState(FrameStateProvisional); @@ -264,7 +252,7 @@ void FrameLoader::init() writer()->begin(KURL(), false); writer()->end(); m_frame->document()->cancelParsing(); - m_creatingInitialEmptyDocument = false; + m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument); m_didCallImplicitClose = true; } @@ -400,114 +388,32 @@ void FrameLoader::urlSelected(const ResourceRequest& request, const String& pass m_suppressOpenerInNewFrame = false; } -bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) -{ - // Support for <frame src="javascript:string"> - KURL scriptURL; - KURL url; - if (protocolIsJavaScript(urlString)) { - scriptURL = completeURL(urlString); // completeURL() encodes the URL. - url = blankURL(); - } else - url = completeURL(urlString); - - Frame* frame = ownerElement->contentFrame(); - if (frame) - frame->redirectScheduler()->scheduleLocationChange(url.string(), m_outgoingReferrer, lockHistory, lockBackForwardList, isProcessingUserGesture()); - else - frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer); - - if (!frame) - return false; - - if (!scriptURL.isEmpty()) - frame->script()->executeIfJavaScriptURL(scriptURL); - - return true; -} - -Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer) +void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission) { - 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 (!SecurityOrigin::canLoad(url, referrer, 0)) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return 0; - } - - bool hideReferrer = SecurityOrigin::shouldHideReferrer(url, referrer); - RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight); + ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod); - if (!frame) { - checkCallImplicitClose(); - return 0; - } - - // All new frames will have m_isComplete set to true at this point due to synchronously loading - // an empty document in FrameLoader::init(). But many frames will now be starting an - // asynchronous load of url, so we set m_isComplete to false and then check if the load is - // actually completed below. (Note that we set m_isComplete to false even for synchronous - // loads, so that checkCompleted() below won't bail early.) - // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed. - frame->loader()->m_isComplete = false; - - RenderObject* renderer = ownerElement->renderer(); - FrameView* view = frame->view(); - if (renderer && renderer->isWidget() && view) - toRenderWidget(renderer)->setWidget(view); - - checkCallImplicitClose(); - - // Some loads are performed synchronously (e.g., about:blank and loads - // cancelled by returning a null ResourceRequest from requestFromDelegate). - // 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 and mark the load as being - // complete. - // 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 (frame->loader()->state() == FrameStateComplete) - frame->loader()->checkCompleted(); - - return frame.get(); -} - -void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData, - const String& target, const String& contentType, const String& boundary, - bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState) -{ - ASSERT(action); - ASSERT(strcmp(action, "GET") == 0 || strcmp(action, "POST") == 0); - ASSERT(formData); - ASSERT(formState); - ASSERT(formState->sourceFrame() == m_frame); + // FIXME: Find a good spot for these. + ASSERT(submission->data()); + ASSERT(submission->state()); + ASSERT(submission->state()->sourceFrame() == m_frame); if (!m_frame->page()) return; - KURL u = completeURL(url.isNull() ? "" : url); - if (u.isEmpty()) + if (submission->action().isEmpty()) return; if (isDocumentSandboxed(m_frame, SandboxForms)) return; - if (protocolIsJavaScript(u)) { + if (protocolIsJavaScript(submission->action())) { m_isExecutingJavaScriptFormAction = true; - m_frame->script()->executeIfJavaScriptURL(u, false, DoNotReplaceDocumentIfJavaScriptURL); + m_frame->script()->executeIfJavaScriptURL(submission->action(), false, DoNotReplaceDocumentIfJavaScriptURL); m_isExecutingJavaScriptFormAction = false; return; } +<<<<<<< HEAD FrameLoadRequest frameRequest; #ifdef ANDROID_USER_GESTURE frameRequest.resourceRequest().setUserGesture(isProcessingUserGesture()); @@ -515,6 +421,9 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F String targetOrBaseTarget = target.isEmpty() ? m_frame->document()->baseTarget() : target; Frame* targetFrame = m_frame->tree()->find(targetOrBaseTarget); +======= + Frame* targetFrame = m_frame->tree()->find(submission->target()); +>>>>>>> webkit.org at r61871 if (!shouldAllowNavigation(targetFrame)) return; if (!targetFrame) { @@ -522,8 +431,9 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F return; targetFrame = m_frame; - frameRequest.setFrameName(targetOrBaseTarget); - } + } else + submission->clearTarget(); + if (!targetFrame->page()) return; @@ -540,33 +450,16 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F // needed any more now that we reset m_submittedFormURL on each mouse or key down event. if (m_frame->tree()->isDescendantOf(targetFrame)) { - if (m_submittedFormURL == u) + if (m_submittedFormURL == submission->action()) return; - m_submittedFormURL = u; - } - - formData->generateFiles(m_frame->document()); - - if (!m_outgoingReferrer.isEmpty()) - frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); - - if (strcmp(action, "GET") == 0) - u.setQuery(formData->flattenToString()); - else { - frameRequest.resourceRequest().setHTTPMethod("POST"); - frameRequest.resourceRequest().setHTTPBody(formData); - - // 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); + m_submittedFormURL = submission->action(); } - frameRequest.resourceRequest().setURL(u); - addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); + submission->data()->generateFiles(m_frame->document()); + submission->setReferrer(m_outgoingReferrer); + submission->setOrigin(outgoingOrigin()); - targetFrame->redirectScheduler()->scheduleFormSubmission(frameRequest, lockHistory, event, formState); + targetFrame->redirectScheduler()->scheduleFormSubmission(submission); } void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolicy databasePolicy) @@ -597,7 +490,7 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic // Dispatching the unload event could have made m_frame->document() null. if (m_frame->document() && !m_frame->document()->inPageCache()) { // Don't remove event listeners from a transitional empty document (see bug 28716 for more information). - bool keepEventListeners = m_isDisplayingInitialEmptyDocument && m_provisionalDocumentLoader + bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url()); if (!keepEventListeners) @@ -628,6 +521,7 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic #endif } +<<<<<<< HEAD #if PLATFORM(ANDROID) // Stop the Geolocation object, if present. This call is made after the unload // event has fired, so no new Geolocation activity is possible. @@ -639,6 +533,9 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) child->loader()->stopLoading(unloadEventPolicy); +======= + // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache. +>>>>>>> webkit.org at r61871 m_frame->redirectScheduler()->cancel(); } @@ -710,9 +607,11 @@ bool FrameLoader::didOpenURL(const KURL& url) // If we are still in the process of initializing an empty document then // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText // since it may cause clients to attempt to render the frame. - if (!m_creatingInitialEmptyDocument) { - m_frame->setJSStatusBarText(String()); - m_frame->setJSDefaultStatusBarText(String()); + if (!m_stateMachine.creatingInitialEmptyDocument()) { + if (DOMWindow* window = m_frame->existingDOMWindow()) { + window->setStatus(String()); + window->setDefaultStatus(String()); + } } m_URL = url; if (m_URL.protocolInHTTPFamily() && !m_URL.host().isEmpty() && m_URL.path().isEmpty()) @@ -730,7 +629,8 @@ void FrameLoader::didExplicitOpen() m_didCallImplicitClose = false; // Calling document.open counts as committing the first real document load. - m_committedFirstRealDocumentLoad = true; + if (!m_stateMachine.committedFirstRealDocumentLoad()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results // from a subsequent window.document.open / window.document.write call. @@ -788,7 +688,7 @@ void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, boo m_frame->setDocument(0); writer()->clear(); - m_containsPlugIns = false; + m_subframeLoader.clear(); if (clearScriptObjects) m_frame->script()->clearScriptObjects(); @@ -799,7 +699,8 @@ void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, boo m_shouldCallCheckCompleted = false; m_shouldCallCheckLoadComplete = false; - m_isDisplayingInitialEmptyDocument = false; + if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); } void FrameLoader::receivedFirstData() @@ -851,7 +752,6 @@ void FrameLoader::didBeginDocument(bool dispatch) m_isComplete = false; m_didCallImplicitClose = false; m_isLoadingMainResource = true; - m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument; if (m_pendingStateObject) { m_frame->document()->statePopped(m_pendingStateObject.get()); @@ -965,7 +865,7 @@ void FrameLoader::commitIconURLToIconDatabase(const KURL& icon) void FrameLoader::finishedParsing() { - if (m_creatingInitialEmptyDocument) + if (m_stateMachine.creatingInitialEmptyDocument()) return; m_frame->injectUserScripts(InjectAtDocumentEnd); @@ -1166,68 +1066,6 @@ void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive) } #endif -bool FrameLoader::requestObject(RenderEmbeddedObject* 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; - - if (!m_frame->script()->xssAuditor()->canLoadObject(url)) { - // It is unsafe to honor the request for this object. - 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 ((!allowPlugins(AboutToInstantiatePlugin) - // Application plugins are plugins implemented by the user agent, for example Qt plugins, - // as opposed to third-party code such as flash. The user agent decides whether or not they are - // permitted, rather than WebKit. - && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)) - || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) - return false; - if (isDocumentSandboxed(m_frame, SandboxPlugins)) - 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()); - - // If the plug-in element already contains a subframe, requestFrame will re-use it. Otherwise, - // it will create a new frame and set it as the RenderPart's widget, causing what was previously - // in the widget to be torn down. - return requestFrame(element, completedURL, frameName); -} - -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; -} - ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn) { String mimeType = mimeTypeIn; @@ -1252,91 +1090,6 @@ ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const S return WebCore::ObjectContentNone; } -static HTMLPlugInElement* toPlugInElement(Node* node) -{ - if (!node) - return 0; - - ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) - || node->hasTagName(appletTag)); - - return static_cast<HTMLPlugInElement*>(node); -} - -bool FrameLoader::loadPlugin(RenderEmbeddedObject* renderer, const KURL& url, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) -{ - RefPtr<Widget> widget; - - if (renderer && !useFallback) { - HTMLPlugInElement* element = toPlugInElement(renderer->node()); - - if (!SecurityOrigin::canLoad(url, String(), frame()->document())) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return false; - } - - checkIfRunInsecureContent(m_frame->document()->securityOrigin(), url); - - widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), - element, url, paramNames, paramValues, mimeType, - m_frame->document()->isPluginDocument() && !m_containsPlugIns); - if (widget) { - renderer->setWidget(widget); - m_containsPlugIns = true; - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); -#endif - } else - renderer->setShowsMissingPluginIndicator(); - } - - return widget != 0; -} - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -PassRefPtr<Widget> FrameLoader::loadMediaPlayerProxyPlugin(Node* node, const KURL& url, - const Vector<String>& paramNames, const Vector<String>& paramValues) -{ - ASSERT(node->hasTagName(videoTag) || node->hasTagName(audioTag)); - - if (!m_frame->script()->xssAuditor()->canLoadObject(url.string())) - return 0; - - KURL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - - if (!SecurityOrigin::canLoad(completedURL, String(), frame()->document())) { - FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string()); - return 0; - } - - HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); - RenderPart* renderer = toRenderPart(node->renderer()); - IntSize size; - - if (renderer) - size = IntSize(renderer->contentWidth(), renderer->contentHeight()); - else if (mediaElement->isVideo()) - size = RenderVideo::defaultSize(); - - checkIfRunInsecureContent(m_frame->document()->securityOrigin(), completedURL); - - RefPtr<Widget> widget = m_client->createMediaPlayerProxyPlugin(size, mediaElement, completedURL, - paramNames, paramValues, "application/x-media-element-proxy-plugin"); - - if (widget && renderer) { - renderer->setWidget(widget); - m_containsPlugIns = true; - renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); - } - - return widget ? widget.release() : 0; -} -#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) - String FrameLoader::outgoingReferrer() const { return m_outgoingReferrer; @@ -1410,12 +1163,18 @@ void FrameLoader::handleFallbackContent() } void FrameLoader::provisionalLoadStarted() +<<<<<<< HEAD { #ifdef ANDROID_INSTRUMENT if (!m_frame->tree()->parent()) android::TimeCounter::reset(); #endif m_firstLayoutDone = false; +======= +{ + if (m_stateMachine.firstLayoutDone()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); +>>>>>>> webkit.org at r61871 m_frame->redirectScheduler()->cancel(true); m_client->provisionalLoadStarted(); } @@ -1569,20 +1328,6 @@ void FrameLoader::started() frame->loader()->m_isComplete = false; } -bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason) -{ - Settings* settings = m_frame->settings(); - bool allowed = m_client->allowPlugins(settings && settings->arePluginsEnabled()); - if (!allowed && reason == AboutToInstantiatePlugin) - m_frame->loader()->client()->didNotAllowPlugins(); - return allowed; -} - -bool FrameLoader::containsPlugins() const -{ - return m_containsPlugIns; -} - void FrameLoader::prepareForLoadStart() { if (Page* page = m_frame->page()) @@ -2141,7 +1886,7 @@ bool FrameLoader::isLoading() const bool FrameLoader::frameHasLoaded() const { - return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); + return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); } void FrameLoader::setDocumentLoader(DocumentLoader* loader) @@ -2230,15 +1975,13 @@ void FrameLoader::commitProvisionalLoad() // Check to see if we need to cache the page we are navigating away from into the back/forward cache. // We are doing this here because we know for sure that a new page is about to be loaded. HistoryItem* item = history()->currentItem(); - if (!m_frame->tree()->parent() && PageCache::canCache(m_frame->page()) && !item->isInPageCache()) { - pageHidden(); + if (!m_frame->tree()->parent() && PageCache::canCache(m_frame->page()) && !item->isInPageCache()) pageCache()->add(item, m_frame->page()); - } if (m_loadType != FrameLoadTypeReplace) closeOldDataSources(); - if (!cachedPage && !m_creatingInitialEmptyDocument) + if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument()) m_client->makeRepresentation(pdl.get()); transitionToCommitted(cachedPage); @@ -2342,18 +2085,24 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) case FrameLoadTypeIndexedBackForward: if (Page* page = m_frame->page()) { if (page->backForwardList()) { + // If the first load within a frame is a navigation within a back/forward list that was attached + // without any of the items being loaded then we need to update the history in a similar manner as + // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>). + if (!m_stateMachine.committedFirstRealDocumentLoad()) + history()->updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList); + history()->updateForBackForwardNavigation(); if (history()->currentItem()) m_pendingStateObject = history()->currentItem()->stateObject(); - + // Create a document view for this document, or used the cached view. if (cachedPage) { DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader(); ASSERT(cachedDocumentLoader); cachedDocumentLoader->setFrame(m_frame); m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame()); - + } else m_client->transitionToCommittedForNewPage(); } @@ -2395,10 +2144,11 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) // Tell the client we've committed this URL. ASSERT(m_frame->view()); - if (m_creatingInitialEmptyDocument) + if (m_stateMachine.creatingInitialEmptyDocument()) return; - - m_committedFirstRealDocumentLoad = true; + + if (!m_stateMachine.committedFirstRealDocumentLoad()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); if (!m_client->hasHTMLView()) receivedFirstData(); @@ -2483,8 +2233,10 @@ void FrameLoader::prepareForCachedPageRestore() // Delete old status bar messages (if it _was_ activated on last URL). if (m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) { - m_frame->setJSStatusBarText(String()); - m_frame->setJSDefaultStatusBarText(String()); + if (DOMWindow* window = m_frame->existingDOMWindow()) { + window->setStatus(String()); + window->setDefaultStatus(String()); + } } } @@ -2592,8 +2344,13 @@ void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame() void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) { // FIXME: Platforms shouldn't differ here! +<<<<<<< HEAD #if PLATFORM(WIN) || PLATFORM(CHROMIUM) || defined(ANDROID) if (m_creatingInitialEmptyDocument) +======= +#if PLATFORM(WIN) || PLATFORM(CHROMIUM) + if (m_stateMachine.creatingInitialEmptyDocument()) +>>>>>>> webkit.org at r61871 return; #endif @@ -2789,7 +2546,7 @@ void FrameLoader::checkLoadCompleteForThisFrame() if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList()) history()->restoreScrollPositionAndViewState(); - if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad) + if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad()) return; const ResourceError& error = dl->mainDocumentError(); @@ -2856,7 +2613,8 @@ void FrameLoader::didFirstLayout() if (isBackForwardLoadType(m_loadType) && page->backForwardList()) history()->restoreScrollPositionAndViewState(); - m_firstLayoutDone = true; + if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone); m_client->dispatchDidFirstLayout(); } @@ -2875,13 +2633,8 @@ void FrameLoader::frameLoadCompleted() // After a canceled provisional load, firstLayoutDone is false. // Reset it to true if we're displaying a page. - if (m_documentLoader) - m_firstLayoutDone = true; -} - -bool FrameLoader::firstLayoutDone() const -{ - return m_firstLayoutDone; + if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone()) + m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone); } void FrameLoader::detachChildren() @@ -3308,7 +3061,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass // is the user responding Cancel to the form repost nag sheet. // 2) User responded Cancel to an alert popped up by the before unload event handler. // The "before unload" event handler runs only for the main frame. - bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose()); + bool canContinue = shouldContinue && (!isLoadingMainFrame() || shouldClose()); if (!canContinue) { // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we @@ -3483,18 +3236,6 @@ void FrameLoader::loadProvisionalItemFromCachedPage() commitProvisionalLoad(); } -void FrameLoader::pageHidden() -{ - m_pageDismissalEventBeingDispatched = true; - if (m_frame->domWindow()) - m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, true), m_frame->document()); - m_pageDismissalEventBeingDispatched = false; - - // Send pagehide event for subframes as well - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->pageHidden(); -} - bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const { if (!history()->currentItem()) @@ -3631,14 +3372,11 @@ void FrameLoader::navigateToDifferentDocument(HistoryItem* item, FrameLoadType l void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) { // We do same-document navigation in the following cases: - // - The HistoryItem has a history state object - // - Navigating to an anchor within the page, with no form data stored on the target item or the current history entry, - // and the URLs in the frame tree match the history item for fragment scrolling. - // - The HistoryItem is not the same as the current item, because such cases are treated as a new load. + // - The HistoryItem corresponds to the same document. + // - The HistoryItem is not the same as the current item. HistoryItem* currentItem = history()->currentItem(); - bool sameDocumentNavigation = ((!item->formData() && !(currentItem && currentItem->formData()) && history()->urlsMatchItem(item)) - || (currentItem && item->documentSequenceNumber() == currentItem->documentSequenceNumber())) - && item != currentItem; + bool sameDocumentNavigation = currentItem && item != currentItem + && item->documentSequenceNumber() == currentItem->documentSequenceNumber(); #if ENABLE(WML) // All WML decks should go through the real load mechanism, not the scroll-to-anchor code @@ -3782,42 +3520,6 @@ void FrameLoader::updateSandboxFlags() child->loader()->updateSandboxFlags(); } -PassRefPtr<Widget> FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args) -{ - String baseURLString; - String codeBaseURLString; - Vector<String> paramNames; - Vector<String> paramValues; - HashMap<String, String>::const_iterator end = args.end(); - for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) { - if (equalIgnoringCase(it->first, "baseurl")) - baseURLString = it->second; - else if (equalIgnoringCase(it->first, "codebase")) - codeBaseURLString = it->second; - paramNames.append(it->first); - paramValues.append(it->second); - } - - if (!codeBaseURLString.isEmpty()) { - KURL codeBaseURL = completeURL(codeBaseURLString); - if (!SecurityOrigin::canLoad(codeBaseURL, String(), element->document())) { - FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string()); - return 0; - } - } - - if (baseURLString.isEmpty()) - baseURLString = m_frame->document()->baseURL().string(); - KURL baseURL = completeURL(baseURLString); - - RefPtr<Widget> widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); - if (!widget) - return 0; - - m_containsPlugIns = true; - return widget; -} - void FrameLoader::didChangeTitle(DocumentLoader* loader) { m_client->didChangeTitle(loader); @@ -3840,7 +3542,7 @@ void FrameLoader::didChangeIcons(DocumentLoader* loader) void FrameLoader::dispatchDidCommitLoad() { - if (m_creatingInitialEmptyDocument) + if (m_stateMachine.creatingInitialEmptyDocument()) return; #ifndef NDEBUG diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h index a04937d..b361b51 100644 --- a/WebCore/loader/FrameLoader.h +++ b/WebCore/loader/FrameLoader.h @@ -33,6 +33,7 @@ #include "CachePolicy.h" #include "DocumentWriter.h" +#include "FrameLoaderStateMachine.h" #include "FrameLoaderTypes.h" #include "HistoryController.h" #include "PolicyCallback.h" @@ -40,6 +41,7 @@ #include "RedirectScheduler.h" #include "ResourceLoadNotifier.h" #include "ResourceRequest.h" +#include "SubframeLoader.h" #include "ThreadableLoader.h" #include "Timer.h" #include <wtf/Forward.h> @@ -59,20 +61,14 @@ class DocumentLoader; class Event; class FormData; class FormState; +class FormSubmission; class Frame; class FrameLoaderClient; class HistoryItem; -class HTMLAppletElement; class HTMLFormElement; -class HTMLFrameOwnerElement; class IconLoader; -class IntSize; class NavigationAction; -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -class Node; -#endif class ProtectionSpace; -class RenderEmbeddedObject; class ResourceError; class ResourceLoader; class ResourceResponse; @@ -84,7 +80,6 @@ class SerializedScriptValue; class SharedBuffer; class SubstituteData; class TextResourceDecoder; -class Widget; struct FrameLoadRequest; struct WindowFeatures; @@ -104,6 +99,7 @@ public: HistoryController* history() const { return &m_history; } ResourceLoadNotifier* notifier() const { return &m_notifer; } DocumentWriter* writer() const { return &m_writer; } + SubframeLoader* subframeLoader() const { return &m_subframeLoader; } // FIXME: This is not cool, people. There are too many different functions that all start loads. // We should aim to consolidate these into a smaller set of functions, and try to reuse more of @@ -204,7 +200,6 @@ public: CachePolicy subresourceCachePolicy() const; void didFirstLayout(); - bool firstLayoutDone() const; void didFirstVisuallyNonEmptyLayout(); @@ -226,11 +221,8 @@ public: void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false, bool refresh = false); void urlSelected(const KURL&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy); - bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName, bool lockHistory = true, bool lockBackForwardList = true); - void submitForm(const char* action, const String& url, - PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary, - bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); + void submitForm(PassRefPtr<FormSubmission>); void stop(); void stopLoading(UnloadEventPolicy, DatabasePolicy = DatabasePolicyStop); @@ -251,8 +243,6 @@ public: void handledOnloadEvents(); String userAgent(const KURL&) const; - PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args); - void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*); void dispatchDidClearWindowObjectsInAllWorlds(); void dispatchDocumentElementAvailable(); @@ -288,9 +278,6 @@ public: // setURL is a low-level setter and does not trigger loading. void setURL(const KURL&); - bool allowPlugins(ReasonForCallingAllowPlugins); - bool containsPlugins() const; - void loadDone(); void finishedParsing(); void checkCompleted(); @@ -299,9 +286,6 @@ public: bool isComplete() const; - bool requestObject(RenderEmbeddedObject*, const String& url, const AtomicString& frameName, - const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); - KURL completeURL(const String& url); void cancelAndClear(); @@ -312,9 +296,7 @@ public: void commitProvisionalLoad(); bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } - bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; } - bool committedFirstRealDocumentLoad() const { return m_committedFirstRealDocumentLoad; } - bool creatingInitialEmptyDocument() const { return m_creatingInitialEmptyDocument; } + FrameLoaderStateMachine* stateMachine() const { return &m_stateMachine; } void iconLoadDecisionAvailable(); @@ -329,10 +311,6 @@ public: void open(CachedFrameBase&); -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - PassRefPtr<Widget> loadMediaPlayerProxyPlugin(Node*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues); -#endif - // FIXME: Should these really be public? void completed(); bool allAncestorsAreComplete() const; // including this @@ -350,13 +328,13 @@ public: static ObjectContentType defaultObjectContentType(const KURL& url, const String& mimeType); - bool isDisplayingInitialEmptyDocument() const { return m_isDisplayingInitialEmptyDocument; } - void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true); bool quickRedirectComing() const { return m_quickRedirectComing; } bool shouldClose(); + + void started(); private: bool canCachePageContainingThisFrame(); @@ -366,18 +344,11 @@ private: #endif void checkTimerFired(Timer<FrameLoader>*); - - void started(); - - bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); - bool loadPlugin(RenderEmbeddedObject*, const KURL&, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); void navigateWithinDocument(HistoryItem*); void navigateToDifferentDocument(HistoryItem*, FrameLoadType); void loadProvisionalItemFromCachedPage(); - void pageHidden(); void receivedFirstData(); @@ -454,8 +425,6 @@ private: void detachChildren(); void closeAndRemoveChild(Frame*); - Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); - void loadInSameDocument(const KURL&, SerializedScriptValue* stateObject, bool isNewNavigation); void provisionalLoadStarted(); @@ -481,6 +450,8 @@ private: mutable HistoryController m_history; mutable ResourceLoadNotifier m_notifer; mutable DocumentWriter m_writer; + mutable SubframeLoader m_subframeLoader; + mutable FrameLoaderStateMachine m_stateMachine; FrameState m_state; FrameLoadType m_loadType; @@ -495,7 +466,6 @@ private: bool m_delegateIsHandlingProvisionalLoadError; - bool m_firstLayoutDone; bool m_quickRedirectComing; bool m_sentRedirectNotification; bool m_inStopAllLoaders; @@ -518,12 +488,7 @@ private: OwnPtr<IconLoader> m_iconLoader; bool m_mayLoadIconLater; - bool m_cancellingWithLoadInProgress; - bool m_needsClear; - bool m_receivedData; - - bool m_containsPlugIns; KURL m_submittedFormURL; @@ -534,10 +499,6 @@ private: Frame* m_opener; HashSet<Frame*> m_openedFrames; - bool m_creatingInitialEmptyDocument; - bool m_isDisplayingInitialEmptyDocument; - bool m_committedFirstRealDocumentLoad; - bool m_didPerformFirstNavigation; bool m_loadingFromCachedPage; bool m_suppressOpenerInNewFrame; diff --git a/WebCore/loader/FrameLoaderStateMachine.cpp b/WebCore/loader/FrameLoaderStateMachine.cpp new file mode 100644 index 0000000..790b144 --- /dev/null +++ b/WebCore/loader/FrameLoaderStateMachine.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Google, Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FrameLoaderStateMachine.h" + +#include <wtf/Assertions.h> + +namespace WebCore { + + +FrameLoaderStateMachine::FrameLoaderStateMachine() + : m_state(Uninitialized) +{ +} + +bool FrameLoaderStateMachine::committingFirstRealLoad() const +{ + return m_state == DisplayingInitialEmptyDocument; +} + +bool FrameLoaderStateMachine::committedFirstRealDocumentLoad() const +{ + return m_state >= DisplayingInitialEmptyDocumentPostCommit; +} + +bool FrameLoaderStateMachine::creatingInitialEmptyDocument() const +{ + return m_state == CreatingInitialEmptyDocument; +} + +bool FrameLoaderStateMachine::isDisplayingInitialEmptyDocument() const +{ + return m_state == DisplayingInitialEmptyDocument || m_state == DisplayingInitialEmptyDocumentPostCommit; +} + +bool FrameLoaderStateMachine::firstLayoutDone() const +{ + return m_state == FirstLayoutDone; +} + +void FrameLoaderStateMachine::advanceTo(State state) +{ + ASSERT(State(m_state + 1) == state || (firstLayoutDone() && state == CommittedFirstRealLoad)); + m_state = state; +} + +} // namespace WebCore diff --git a/WebCore/loader/FrameLoaderStateMachine.h b/WebCore/loader/FrameLoaderStateMachine.h new file mode 100644 index 0000000..c3408c2 --- /dev/null +++ b/WebCore/loader/FrameLoaderStateMachine.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Google, Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FrameLoaderStateMachine_h +#define FrameLoaderStateMachine_h + +#include <wtf/Noncopyable.h> + +namespace WebCore { + +// Encapsulates a state machine for FrameLoader. Note that this is different from FrameState, +// which stores the state of the current load that FrameLoader is executing. +class FrameLoaderStateMachine : public Noncopyable { +public: + FrameLoaderStateMachine(); + + // Once a load has been committed, the state may + // alternate between CommittedFirstRealLoad and FirstLayoutDone. + // Otherwise, the states only go down the list. + enum State { + Uninitialized, + CreatingInitialEmptyDocument, + DisplayingInitialEmptyDocument, + DisplayingInitialEmptyDocumentPostCommit, + CommittedFirstRealLoad, + FirstLayoutDone + }; + + bool committingFirstRealLoad() const; + bool committedFirstRealDocumentLoad() const; + bool creatingInitialEmptyDocument() const; + bool isDisplayingInitialEmptyDocument() const; + bool firstLayoutDone() const; + void advanceTo(State); + +private: + State m_state; +}; + +} // namespace WebCore + +#endif // FrameLoaderStateMachine_h diff --git a/WebCore/loader/HistoryController.cpp b/WebCore/loader/HistoryController.cpp index c4e9e5a..5ccdf72 100644 --- a/WebCore/loader/HistoryController.cpp +++ b/WebCore/loader/HistoryController.cpp @@ -37,6 +37,7 @@ #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" +#include "FrameLoaderStateMachine.h" #include "FrameTree.h" #include "FrameView.h" #include "HistoryItem.h" @@ -81,7 +82,7 @@ void HistoryController::saveScrollPositionAndViewStateToItem(HistoryItem* item) */ void HistoryController::restoreScrollPositionAndViewState() { - if (!m_frame->loader()->committedFirstRealDocumentLoad()) + if (!m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad()) return; ASSERT(m_currentItem); @@ -106,21 +107,13 @@ void HistoryController::restoreScrollPositionAndViewState() void HistoryController::updateBackForwardListForFragmentScroll() { updateBackForwardListClippedAtTarget(false); - - // Since the document isn't changed as a result of a fragment scroll, we should - // preserve the DocumentSequenceNumber of the previous item. - if (!m_previousItem) - return; - - ASSERT(m_currentItem); - m_currentItem->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); } void HistoryController::saveDocumentState() { // FIXME: Reading this bit of FrameLoader state here is unfortunate. I need to study // this more to see if we can remove this dependency. - if (m_frame->loader()->creatingInitialEmptyDocument()) + if (m_frame->loader()->stateMachine()->creatingInitialEmptyDocument()) return; // For a standard page load, we will have a previous item set, which will be used to @@ -231,25 +224,6 @@ void HistoryController::goToItem(HistoryItem* targetItem, FrameLoadType type) recursiveGoToItem(targetItem, currentItem, type); } -// Walk the frame tree and ensure that the URLs match the URLs in the item. -bool HistoryController::urlsMatchItem(HistoryItem* item) const -{ - const KURL& currentURL = m_frame->loader()->documentLoader()->url(); - if (!equalIgnoringFragmentIdentifier(currentURL, item->url())) - return false; - - const HistoryItemVector& childItems = item->children(); - - unsigned size = childItems.size(); - for (unsigned i = 0; i < size; ++i) { - Frame* childFrame = m_frame->tree()->child(childItems[i]->target()); - if (childFrame && !childFrame->loader()->history()->urlsMatchItem(childItems[i].get())) - return false; - } - - return true; -} - void HistoryController::updateForBackForwardNavigation() { #if !LOG_DISABLED @@ -286,7 +260,7 @@ void HistoryController::updateForReload() // 2) Global history: Handled by the client. // 3) Visited links: Handled by the PageGroup. -void HistoryController::updateForStandardLoad() +void HistoryController::updateForStandardLoad(HistoryUpdateType updateType) { LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", m_frame->loader()->documentLoader()->url().string().ascii().data()); @@ -298,7 +272,8 @@ void HistoryController::updateForStandardLoad() if (!frameLoader->documentLoader()->isClientRedirect()) { if (!historyURL.isEmpty()) { - updateBackForwardListClippedAtTarget(true); + if (updateType != UpdateAllExceptBackForwardList) + updateBackForwardListClippedAtTarget(true); if (!needPrivacy) { frameLoader->client()->updateGlobalHistory(); frameLoader->documentLoader()->setDidCreateGlobalHistoryEntry(true); @@ -521,9 +496,21 @@ PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bo RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false); if (m_previousItem) saveScrollPositionAndViewStateToItem(m_previousItem.get()); - if (!(clipAtTarget && m_frame == targetFrame)) { + + if (!clipAtTarget || m_frame != targetFrame) { // save frame state for items that aren't loading (khtml doesn't save those) saveDocumentState(); + + // clipAtTarget is false for navigations within the same document, so + // we should copy the documentSequenceNumber over to the newly create + // item. Non-target items are just clones, and they should therefore + // preserve the same itemSequenceNumber. + if (m_previousItem) { + if (m_frame != targetFrame) + bfItem->setItemSequenceNumber(m_previousItem->itemSequenceNumber()); + bfItem->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); + } + for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { FrameLoader* childLoader = child->loader(); bool hasChildLoaded = childLoader->frameHasLoaded(); @@ -536,6 +523,7 @@ PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bo bfItem->addChildItem(childLoader->history()->createItemTree(targetFrame, clipAtTarget)); } } + // FIXME: Eliminate the isTargetItem flag in favor of itemSequenceNumber. if (m_frame == targetFrame) bfItem->setIsTargetItem(true); return bfItem; @@ -550,21 +538,15 @@ void HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromIt ASSERT(item); ASSERT(fromItem); - KURL itemURL = item->url(); - KURL currentURL; - if (m_frame->loader()->documentLoader()) - currentURL = m_frame->loader()->documentLoader()->url(); - - // Always reload the target frame of the item we're going to. This ensures that we will - // do -some- load for the transition, which means a proper notification will be posted - // to the app. - // The exact URL has to match, including fragment. We want to go through the _load - // method, even if to do a within-page navigation. - // The current frame tree and the frame tree snapshot in the item have to match. - if (!item->isTargetItem() && - itemURL == currentURL && - ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) && - childFramesMatchItem(item)) + // If the item we're going to is a clone of the item we're at, then do + // not load it again, and continue history traversal to its children. + // The current frame tree and the frame tree snapshot in the item have + // to match. + // Note: If item and fromItem are the same, then we need to create a new + // document. + if (item != fromItem && item->itemSequenceNumber() == fromItem->itemSequenceNumber() + && ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) + && childFramesMatchItem(item)) { // This content is good, so leave it alone and look for children that need reloading // Save form state (works from currentItem, since prevItem is nil) @@ -659,10 +641,6 @@ void HistoryController::pushState(PassRefPtr<SerializedScriptValue> stateObject, item->setStateObject(stateObject); item->setURLString(urlString); - // Since the document isn't changed as a result of a pushState call, we - // should preserve the DocumentSequenceNumber of the previous item. - item->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); - page->backForwardList()->pushStateItem(item.release()); } diff --git a/WebCore/loader/HistoryController.h b/WebCore/loader/HistoryController.h index 64f7854..19902f8 100644 --- a/WebCore/loader/HistoryController.h +++ b/WebCore/loader/HistoryController.h @@ -43,6 +43,8 @@ class SerializedScriptValue; class HistoryController : public Noncopyable { public: + enum HistoryUpdateType { UpdateAll, UpdateAllExceptBackForwardList }; + HistoryController(Frame*); ~HistoryController(); @@ -58,11 +60,10 @@ public: void invalidateCurrentItemCachedPage(); void goToItem(HistoryItem*, FrameLoadType); - bool urlsMatchItem(HistoryItem*) const; void updateForBackForwardNavigation(); void updateForReload(); - void updateForStandardLoad(); + void updateForStandardLoad(HistoryUpdateType updateType = UpdateAll); void updateForRedirectWithLockedBackForwardList(); void updateForClientRedirect(); void updateForCommit(); diff --git a/WebCore/loader/ImageDocument.cpp b/WebCore/loader/ImageDocument.cpp index 8ab412f..49f54e2 100644 --- a/WebCore/loader/ImageDocument.cpp +++ b/WebCore/loader/ImageDocument.cpp @@ -25,14 +25,11 @@ #include "config.h" #include "ImageDocument.h" -#include "CSSStyleDeclaration.h" #include "CachedImage.h" #include "DocumentLoader.h" -#include "Element.h" #include "EventListener.h" #include "EventNames.h" #include "Frame.h" -#include "FrameLoader.h" #include "FrameLoaderClient.h" #include "FrameView.h" #include "HTMLImageElement.h" @@ -41,10 +38,8 @@ #include "MouseEvent.h" #include "NotImplemented.h" #include "Page.h" -#include "SegmentedString.h" +#include "RawDataDocumentParser.h" #include "Settings.h" -#include "Text.h" -#include "XMLDocumentParser.h" using std::min; @@ -76,19 +71,21 @@ private: ImageDocument* m_doc; }; -class ImageTokenizer : public DocumentParser { +class ImageDocumentParser : public RawDataDocumentParser { public: - ImageTokenizer(ImageDocument* doc) : m_doc(doc) {} + ImageDocumentParser(ImageDocument* document) + : RawDataDocumentParser(document) + { + } - virtual void write(const SegmentedString&, bool appendData); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } - virtual bool writeRawData(const char* data, int len); + ImageDocument* document() const + { + return static_cast<ImageDocument*>(m_document); + } private: - ImageDocument* m_doc; + virtual bool writeRawData(const char* data, int len); + virtual void finish(); }; class ImageDocumentElement : public HTMLImageElement { @@ -110,7 +107,7 @@ private: inline PassRefPtr<ImageDocumentElement> ImageDocumentElement::create(ImageDocument* document) { - return new ImageDocumentElement(document); + return adoptRef(new ImageDocumentElement(document)); } // -------- @@ -121,69 +118,57 @@ static float pageZoomFactor(Document* document) return view ? view->pageZoomFactor() : 1; } -void ImageTokenizer::write(const SegmentedString&, bool) +bool ImageDocumentParser::writeRawData(const char*, int) { - // <https://bugs.webkit.org/show_bug.cgi?id=25397>: JS code can always call document.write, we need to handle it. - notImplemented(); -} - -bool ImageTokenizer::writeRawData(const char*, int) -{ - Frame* frame = m_doc->frame(); + Frame* frame = document()->frame(); Settings* settings = frame->settings(); if (!frame->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) return false; - - CachedImage* cachedImage = m_doc->cachedImage(); + + CachedImage* cachedImage = document()->cachedImage(); cachedImage->data(frame->loader()->documentLoader()->mainResourceData(), false); - m_doc->imageChanged(); + document()->imageChanged(); return false; } -void ImageTokenizer::finish() +void ImageDocumentParser::finish() { - if (!m_parserStopped && m_doc->imageElement()) { - CachedImage* cachedImage = m_doc->cachedImage(); - RefPtr<SharedBuffer> data = m_doc->frame()->loader()->documentLoader()->mainResourceData(); + if (!m_parserStopped && document()->imageElement()) { + CachedImage* cachedImage = document()->cachedImage(); + RefPtr<SharedBuffer> data = document()->frame()->loader()->documentLoader()->mainResourceData(); // If this is a multipart image, make a copy of the current part, since the resource data // will be overwritten by the next part. - if (m_doc->frame()->loader()->documentLoader()->isLoadingMultipartContent()) + if (document()->frame()->loader()->documentLoader()->isLoadingMultipartContent()) data = data->copy(); cachedImage->data(data.release(), true); cachedImage->finish(); - cachedImage->setResponse(m_doc->frame()->loader()->documentLoader()->response()); + cachedImage->setResponse(document()->frame()->loader()->documentLoader()->response()); - IntSize size = cachedImage->imageSize(pageZoomFactor(m_doc)); + IntSize size = cachedImage->imageSize(pageZoomFactor(document())); if (size.width()) { // Compute the title, we use the decoded filename of the resource, falling // back on the (decoded) hostname if there is no path. - String fileName = decodeURLEscapeSequences(m_doc->url().lastPathComponent()); + String fileName = decodeURLEscapeSequences(document()->url().lastPathComponent()); if (fileName.isEmpty()) - fileName = m_doc->url().host(); - m_doc->setTitle(imageTitle(fileName, size)); + fileName = document()->url().host(); + document()->setTitle(imageTitle(fileName, size)); } - m_doc->imageChanged(); + document()->imageChanged(); } - m_doc->finishedParsing(); -} - -bool ImageTokenizer::isWaitingForScripts() const -{ - // An image document is never waiting for scripts - return false; + document()->finishedParsing(); } // -------- -ImageDocument::ImageDocument(Frame* frame) - : HTMLDocument(frame) +ImageDocument::ImageDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) , m_imageElement(0) , m_imageSizeIsKnown(false) , m_didShrinkImage(false) @@ -194,7 +179,7 @@ ImageDocument::ImageDocument(Frame* frame) DocumentParser* ImageDocument::createParser() { - return new ImageTokenizer(this); + return new ImageDocumentParser(this); } void ImageDocument::createDocumentStructure() @@ -203,6 +188,9 @@ void ImageDocument::createDocumentStructure() RefPtr<Element> rootElement = Document::createElement(htmlTag, false); appendChild(rootElement, ec); + + if (frame() && frame()->loader()) + frame()->loader()->dispatchDocumentElementAvailable(); RefPtr<Element> body = Document::createElement(bodyTag, false); body->setAttribute(styleAttr, "margin: 0px;"); diff --git a/WebCore/loader/ImageDocument.h b/WebCore/loader/ImageDocument.h index bd627b4..e85b3ab 100644 --- a/WebCore/loader/ImageDocument.h +++ b/WebCore/loader/ImageDocument.h @@ -33,9 +33,9 @@ class ImageDocumentElement; class ImageDocument : public HTMLDocument { public: - static PassRefPtr<ImageDocument> create(Frame* frame) + static PassRefPtr<ImageDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new ImageDocument(frame)); + return adoptRef(new ImageDocument(frame, url)); } CachedImage* cachedImage(); @@ -47,7 +47,7 @@ public: void imageClicked(int x, int y); private: - ImageDocument(Frame*); + ImageDocument(Frame*, const KURL&); virtual DocumentParser* createParser(); virtual bool isImageDocument() const { return true; } diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp index 28587e2..0a5bf40 100644 --- a/WebCore/loader/MainResourceLoader.cpp +++ b/WebCore/loader/MainResourceLoader.cpp @@ -285,7 +285,7 @@ void MainResourceLoader::continueAfterContentPolicy(PolicyAction policy) #if PLATFORM(QT) void MainResourceLoader::substituteMIMETypeFromPluginDatabase(const ResourceResponse& r) { - if (!m_frame->loader()->allowPlugins(NotAboutToInstantiatePlugin)) + if (!m_frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin)) return; String filename = r.url().lastPathComponent(); diff --git a/WebCore/loader/MediaDocument.cpp b/WebCore/loader/MediaDocument.cpp index e505c2f..97ca783 100644 --- a/WebCore/loader/MediaDocument.cpp +++ b/WebCore/loader/MediaDocument.cpp @@ -29,11 +29,8 @@ #include "MediaDocument.h" #include "DocumentLoader.h" -#include "Element.h" -#include "Event.h" #include "EventNames.h" #include "Frame.h" -#include "FrameLoader.h" #include "FrameLoaderClient.h" #include "HTMLEmbedElement.h" #include "HTMLNames.h" @@ -41,51 +38,41 @@ #include "KeyboardEvent.h" #include "MainResourceLoader.h" #include "NodeList.h" -#include "Page.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "Text.h" -#include "XMLDocumentParser.h" +#include "RawDataDocumentParser.h" namespace WebCore { using namespace HTMLNames; -class MediaDocumentParser : public DocumentParser { +// FIXME: Share more code with PluginDocumentParser. +class MediaDocumentParser : public RawDataDocumentParser { public: - MediaDocumentParser(Document* doc) : m_doc(doc), m_mediaElement(0) {} - + MediaDocumentParser(Document* document) + : RawDataDocumentParser(document) + , m_mediaElement(0) + { + } + private: - virtual void write(const SegmentedString&, bool appendData); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } virtual bool writeRawData(const char* data, int len); - + void createDocumentStructure(); - Document* m_doc; HTMLMediaElement* m_mediaElement; }; - -void MediaDocumentParser::write(const SegmentedString&, bool) -{ - ASSERT_NOT_REACHED(); -} void MediaDocumentParser::createDocumentStructure() { ExceptionCode ec; - RefPtr<Element> rootElement = m_doc->createElement(htmlTag, false); - m_doc->appendChild(rootElement, ec); + RefPtr<Element> rootElement = document()->createElement(htmlTag, false); + document()->appendChild(rootElement, ec); - RefPtr<Element> body = m_doc->createElement(bodyTag, false); + RefPtr<Element> body = document()->createElement(bodyTag, false); body->setAttribute(styleAttr, "background-color: rgb(38,38,38);"); rootElement->appendChild(body, ec); - RefPtr<Element> mediaElement = m_doc->createElement(videoTag, false); + RefPtr<Element> mediaElement = document()->createElement(videoTag, false); m_mediaElement = static_cast<HTMLVideoElement*>(mediaElement.get()); m_mediaElement->setAttribute(controlsAttr, ""); @@ -93,11 +80,11 @@ void MediaDocumentParser::createDocumentStructure() m_mediaElement->setAttribute(styleAttr, "margin: auto; position: absolute; top: 0; right: 0; bottom: 0; left: 0;"); m_mediaElement->setAttribute(nameAttr, "media"); - m_mediaElement->setSrc(m_doc->url()); + m_mediaElement->setSrc(document()->url()); body->appendChild(mediaElement, ec); - Frame* frame = m_doc->frame(); + Frame* frame = document()->frame(); if (!frame) return; @@ -114,21 +101,9 @@ bool MediaDocumentParser::writeRawData(const char*, int) finish(); return false; } - -void MediaDocumentParser::finish() -{ - if (!m_parserStopped) - m_doc->finishedParsing(); -} - -bool MediaDocumentParser::isWaitingForScripts() const -{ - // A media document is never waiting for scripts - return false; -} -MediaDocument::MediaDocument(Frame* frame) - : HTMLDocument(frame) +MediaDocument::MediaDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) , m_replaceMediaElementTimer(this, &MediaDocument::replaceMediaElementTimerFired) { setParseMode(Compat); diff --git a/WebCore/loader/MediaDocument.h b/WebCore/loader/MediaDocument.h index 98eb02f..5a8ec52 100644 --- a/WebCore/loader/MediaDocument.h +++ b/WebCore/loader/MediaDocument.h @@ -34,16 +34,16 @@ namespace WebCore { class MediaDocument : public HTMLDocument { public: - static PassRefPtr<MediaDocument> create(Frame* frame) + static PassRefPtr<MediaDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new MediaDocument(frame)); + return adoptRef(new MediaDocument(frame, url)); } virtual ~MediaDocument(); void mediaElementSawUnsupportedTracks(); private: - MediaDocument(Frame*); + MediaDocument(Frame*, const KURL&); virtual bool isMediaDocument() const { return true; } virtual DocumentParser* createParser(); diff --git a/WebCore/loader/PlaceholderDocument.h b/WebCore/loader/PlaceholderDocument.h index 5b76a9c..3d40a6e 100644 --- a/WebCore/loader/PlaceholderDocument.h +++ b/WebCore/loader/PlaceholderDocument.h @@ -32,15 +32,15 @@ namespace WebCore { class PlaceholderDocument : public Document { public: - static PassRefPtr<PlaceholderDocument> create(Frame* frame) + static PassRefPtr<PlaceholderDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new PlaceholderDocument(frame)); + return adoptRef(new PlaceholderDocument(frame, url)); } virtual void attach(); private: - PlaceholderDocument(Frame* frame) : Document(frame, false, false) { } + PlaceholderDocument(Frame* frame, const KURL& url) : Document(frame, url, false, false) { } }; } // namespace WebCore diff --git a/WebCore/loader/PluginDocument.cpp b/WebCore/loader/PluginDocument.cpp index 7833d41..12ab746 100644 --- a/WebCore/loader/PluginDocument.cpp +++ b/WebCore/loader/PluginDocument.cpp @@ -26,41 +26,36 @@ #include "PluginDocument.h" #include "DocumentLoader.h" -#include "Element.h" #include "Frame.h" -#include "FrameLoader.h" #include "FrameLoaderClient.h" #include "HTMLEmbedElement.h" #include "HTMLNames.h" #include "MainResourceLoader.h" #include "Page.h" +#include "RawDataDocumentParser.h" #include "RenderEmbeddedObject.h" -#include "RenderWidget.h" -#include "SegmentedString.h" #include "Settings.h" -#include "Text.h" -#include "XMLDocumentParser.h" namespace WebCore { using namespace HTMLNames; - -class PluginDocumentParser : public DocumentParser { + +// FIXME: Share more code with MediaDocumentParser. +class PluginDocumentParser : public RawDataDocumentParser { public: - PluginDocumentParser(Document* doc) : m_doc(doc), m_embedElement(0) {} - static Widget* pluginWidgetFromDocument(Document* doc); - + PluginDocumentParser(Document* document) + : RawDataDocumentParser(document) + , m_embedElement(0) + { + } + + static Widget* pluginWidgetFromDocument(Document*); + private: - virtual void write(const SegmentedString&, bool appendData); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } virtual bool writeRawData(const char* data, int len); - + void createDocumentStructure(); - Document* m_doc; HTMLEmbedElement* m_embedElement; }; @@ -78,33 +73,28 @@ Widget* PluginDocumentParser::pluginWidgetFromDocument(Document* doc) return 0; } -void PluginDocumentParser::write(const SegmentedString&, bool) -{ - ASSERT_NOT_REACHED(); -} - void PluginDocumentParser::createDocumentStructure() { ExceptionCode ec; - RefPtr<Element> rootElement = m_doc->createElement(htmlTag, false); - m_doc->appendChild(rootElement, ec); + RefPtr<Element> rootElement = document()->createElement(htmlTag, false); + document()->appendChild(rootElement, ec); - RefPtr<Element> body = m_doc->createElement(bodyTag, false); + RefPtr<Element> body = document()->createElement(bodyTag, false); body->setAttribute(marginwidthAttr, "0"); body->setAttribute(marginheightAttr, "0"); body->setAttribute(bgcolorAttr, "rgb(38,38,38)"); rootElement->appendChild(body, ec); - RefPtr<Element> embedElement = m_doc->createElement(embedTag, false); + RefPtr<Element> embedElement = document()->createElement(embedTag, false); m_embedElement = static_cast<HTMLEmbedElement*>(embedElement.get()); m_embedElement->setAttribute(widthAttr, "100%"); m_embedElement->setAttribute(heightAttr, "100%"); m_embedElement->setAttribute(nameAttr, "plugin"); - m_embedElement->setAttribute(srcAttr, m_doc->url().string()); - m_embedElement->setAttribute(typeAttr, m_doc->frame()->loader()->writer()->mimeType()); + m_embedElement->setAttribute(srcAttr, document()->url().string()); + m_embedElement->setAttribute(typeAttr, document()->frame()->loader()->writer()->mimeType()); body->appendChild(embedElement, ec); } @@ -117,10 +107,10 @@ bool PluginDocumentParser::writeRawData(const char*, int) createDocumentStructure(); - if (Frame* frame = m_doc->frame()) { + if (Frame* frame = document()->frame()) { Settings* settings = frame->settings(); - if (settings && frame->loader()->allowPlugins(NotAboutToInstantiatePlugin)) { - m_doc->updateLayout(); + if (settings && frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin)) { + document()->updateLayout(); if (RenderWidget* renderer = toRenderWidget(m_embedElement->renderer())) { frame->loader()->client()->redirectDataToPlugin(renderer->widget()); @@ -134,20 +124,8 @@ bool PluginDocumentParser::writeRawData(const char*, int) return false; } -void PluginDocumentParser::finish() -{ - if (!m_parserStopped) - m_doc->finishedParsing(); -} - -bool PluginDocumentParser::isWaitingForScripts() const -{ - // A plugin document is never waiting for scripts - return false; -} - -PluginDocument::PluginDocument(Frame* frame) - : HTMLDocument(frame) +PluginDocument::PluginDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) { setParseMode(Compat); } diff --git a/WebCore/loader/PluginDocument.h b/WebCore/loader/PluginDocument.h index e3f98a7..53dde65 100644 --- a/WebCore/loader/PluginDocument.h +++ b/WebCore/loader/PluginDocument.h @@ -33,9 +33,9 @@ class Node; class Widget; class PluginDocument : public HTMLDocument { public: - static PassRefPtr<PluginDocument> create(Frame* frame) + static PassRefPtr<PluginDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new PluginDocument(frame)); + return adoptRef(new PluginDocument(frame, url)); } Widget* pluginWidget(); @@ -44,7 +44,7 @@ public: virtual bool isPluginDocument() const { return true; } private: - PluginDocument(Frame*); + PluginDocument(Frame*, const KURL&); virtual DocumentParser* createParser(); }; diff --git a/WebCore/loader/ProgressTracker.cpp b/WebCore/loader/ProgressTracker.cpp index 2e12204..88231c8 100644 --- a/WebCore/loader/ProgressTracker.cpp +++ b/WebCore/loader/ProgressTracker.cpp @@ -29,6 +29,7 @@ #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderStateMachine.h" #include "FrameLoaderClient.h" #include "Logging.h" #include "ResourceResponse.h" @@ -204,7 +205,7 @@ void ProgressTracker::incrementProgress(unsigned long identifier, const char*, i // For documents that use WebCore's layout system, treat first layout as the half-way point. // FIXME: The hasHTMLView function is a sort of roundabout way of asking "do you use WebCore's layout system". bool useClampedMaxProgress = frame->loader()->client()->hasHTMLView() - && !frame->loader()->firstLayoutDone(); + && !frame->loader()->stateMachine()->firstLayoutDone(); double maxProgressValue = useClampedMaxProgress ? 0.5 : finalProgressValue; increment = (maxProgressValue - m_progressValue) * percentOfRemainingBytes; m_progressValue += increment; diff --git a/WebCore/loader/RedirectScheduler.cpp b/WebCore/loader/RedirectScheduler.cpp index b4c86d4..3cfe61a 100644 --- a/WebCore/loader/RedirectScheduler.cpp +++ b/WebCore/loader/RedirectScheduler.cpp @@ -36,9 +36,11 @@ #include "DocumentLoader.h" #include "Event.h" #include "FormState.h" +#include "FormSubmission.h" #include "Frame.h" #include "FrameLoadRequest.h" #include "FrameLoader.h" +#include "FrameLoaderStateMachine.h" #include "HistoryItem.h" #include "HTMLFormElement.h" #include "HTMLFrameOwnerElement.h" @@ -170,15 +172,12 @@ private: class ScheduledFormSubmission : public ScheduledNavigation { public: - ScheduledFormSubmission(const FrameLoadRequest& frameRequest, bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState, bool duringLoad) - : ScheduledNavigation(0, lockHistory, lockBackForwardList, duringLoad, true) - , m_frameRequest(frameRequest) - , m_event(event) - , m_formState(formState) + ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBackForwardList, bool duringLoad) + : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList, duringLoad, true) + , m_submission(submission) , m_wasProcessingUserGesture(UserGestureIndicator::processingUserGesture()) { - ASSERT(!frameRequest.isEmpty()); - ASSERT(m_formState); + ASSERT(m_submission->state()); } virtual void fire(Frame* frame) @@ -189,9 +188,11 @@ public: // Now that the timer has fired, we need to repeat the security check which normally is done when // selecting a target, in case conditions have changed. Other code paths avoid this by targeting // without leaving a time window. If we fail the check just silently drop the form submission. - if (!m_formState->sourceFrame()->loader()->shouldAllowNavigation(frame)) + if (!m_submission->state()->sourceFrame()->loader()->shouldAllowNavigation(frame)) return; - frame->loader()->loadFrameRequest(m_frameRequest, lockHistory(), lockBackForwardList(), m_event, m_formState, SendReferrer); + FrameLoadRequest frameRequest; + m_submission->populateFrameLoadRequest(frameRequest); + frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackForwardList(), m_submission->event(), m_submission->state(), SendReferrer); } // FIXME: Implement didStartTimer? It would make sense to report form @@ -200,9 +201,7 @@ public: // be a behavior change. private: - const FrameLoadRequest m_frameRequest; - const RefPtr<Event> m_event; - const RefPtr<FormState> m_formState; + RefPtr<FormSubmission> m_submission; bool m_wasProcessingUserGesture; }; @@ -281,31 +280,29 @@ void RedirectScheduler::scheduleLocationChange(const String& url, const String& // Handle a location change of a page with no document as a special case. // This may happen when a frame changes the location of another frame. - bool duringLoad = !loader->committedFirstRealDocumentLoad(); + bool duringLoad = !loader->stateMachine()->committedFirstRealDocumentLoad(); schedule(new ScheduledLocationChange(url, referrer, lockHistory, lockBackForwardList, wasUserGesture, duringLoad)); } -void RedirectScheduler::scheduleFormSubmission(const FrameLoadRequest& frameRequest, - bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState) +void RedirectScheduler::scheduleFormSubmission(PassRefPtr<FormSubmission> submission) { ASSERT(m_frame->page()); - ASSERT(!frameRequest.isEmpty()); // FIXME: Do we need special handling for form submissions where the URL is the same // as the current one except for the fragment part? See scheduleLocationChange above. // Handle a location change of a page with no document as a special case. // This may happen when a frame changes the location of another frame. - bool duringLoad = !m_frame->loader()->committedFirstRealDocumentLoad(); + bool duringLoad = !m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad(); // If this is a child frame and the form submission was triggered by a script, lock the back/forward list // to match IE and Opera. // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this. - bool lockBackForwardList = mustLockBackForwardList(m_frame) || (formState->formSubmissionTrigger() == SubmittedByJavaScript && m_frame->tree()->parent()); + bool lockBackForwardList = mustLockBackForwardList(m_frame) || (submission->state()->formSubmissionTrigger() == SubmittedByJavaScript && m_frame->tree()->parent()); - schedule(new ScheduledFormSubmission(frameRequest, lockHistory, lockBackForwardList, event, formState, duringLoad)); + schedule(new ScheduledFormSubmission(submission, lockBackForwardList, duringLoad)); } void RedirectScheduler::scheduleRefresh(bool wasUserGesture) diff --git a/WebCore/loader/RedirectScheduler.h b/WebCore/loader/RedirectScheduler.h index ac3731c..e9d04dc 100644 --- a/WebCore/loader/RedirectScheduler.h +++ b/WebCore/loader/RedirectScheduler.h @@ -40,6 +40,7 @@ namespace WebCore { class FormState; +class FormSubmission; class Frame; class String; @@ -56,7 +57,7 @@ public: void scheduleRedirect(double delay, const String& url); void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false); - void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); + void scheduleFormSubmission(PassRefPtr<FormSubmission>); void scheduleRefresh(bool userGesture = false); void scheduleHistoryNavigation(int steps); diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp index 7a95383..b700fcf 100644 --- a/WebCore/loader/ResourceLoader.cpp +++ b/WebCore/loader/ResourceLoader.cpp @@ -510,8 +510,15 @@ void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy) { + // <rdar://problem/7249553> - There are reports of crashes with this method being called + // with a null m_frame->settings(), which can only happen if the frame doesn't have a page. + // Sadly we have no reproducible cases of this. + // We think that any frame without a page shouldn't have any loads happening in it, yet + // there is at least one code path where that is not true. + ASSERT(m_frame->settings()); + // When in private browsing mode, prevent caching to disk - if (policy == StorageAllowed && m_frame->settings()->privateBrowsingEnabled()) + if (policy == StorageAllowed && m_frame->settings() && m_frame->settings()->privateBrowsingEnabled()) policy = StorageAllowedInMemoryOnly; } diff --git a/WebCore/loader/SinkDocument.cpp b/WebCore/loader/SinkDocument.cpp index d40e567..e149981 100644 --- a/WebCore/loader/SinkDocument.cpp +++ b/WebCore/loader/SinkDocument.cpp @@ -26,40 +26,21 @@ #include "config.h" #include "SinkDocument.h" -#include "DocumentParser.h" +#include "RawDataDocumentParser.h" namespace WebCore { -class SinkDocumentParser : public DocumentParser { -public: - SinkDocumentParser(Document* document) : m_document(document) { } - -private: - virtual void write(const SegmentedString&, bool) { ASSERT_NOT_REACHED(); } - virtual void finish(); - virtual bool isWaitingForScripts() const { return false; } - - virtual bool wantsRawData() const { return true; } - virtual bool writeRawData(const char*, int) { return false; } - - Document* m_document; -}; - -void SinkDocumentParser::finish() -{ - if (!m_parserStopped) - m_document->finishedParsing(); -} - -SinkDocument::SinkDocument(Frame* frame) - : HTMLDocument(frame) +SinkDocument::SinkDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) { setParseMode(Compat); } - + DocumentParser* SinkDocument::createParser() { - return new SinkDocumentParser(this); + // The basic RawDataDocumentParser does nothing with the data + // which is sufficient for our purposes here. + return new RawDataDocumentParser(this); } } // namespace WebCore diff --git a/WebCore/loader/SinkDocument.h b/WebCore/loader/SinkDocument.h index 386660c..61930d4 100644 --- a/WebCore/loader/SinkDocument.h +++ b/WebCore/loader/SinkDocument.h @@ -32,13 +32,13 @@ namespace WebCore { class SinkDocument : public HTMLDocument { public: - static PassRefPtr<SinkDocument> create(Frame* frame) + static PassRefPtr<SinkDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new SinkDocument(frame)); + return adoptRef(new SinkDocument(frame, url)); } private: - SinkDocument(Frame*); + SinkDocument(Frame*, const KURL&); virtual DocumentParser* createParser(); }; diff --git a/WebCore/loader/SubframeLoader.cpp b/WebCore/loader/SubframeLoader.cpp new file mode 100644 index 0000000..f5a4c18 --- /dev/null +++ b/WebCore/loader/SubframeLoader.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SubframeLoader.h" + +#include "Frame.h" +#include "FrameLoaderClient.h" +#include "HTMLAppletElement.h" +#include "HTMLFrameElementBase.h" +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "HTMLMediaElement.h" +#endif +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "MIMETypeRegistry.h" +#include "Node.h" +#include "Page.h" +#include "PluginData.h" +#include "RenderEmbeddedObject.h" +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "RenderVideo.h" +#endif +#include "RenderView.h" +#include "Settings.h" +#include "XSSAuditor.h" + +namespace WebCore { + +using namespace HTMLNames; + +SubframeLoader::SubframeLoader(Frame* frame) + : m_containsPlugins(false) + , m_frame(frame) +{ +} + +static HTMLPlugInElement* toPlugInElement(Node* node) +{ + if (!node) + return 0; + + ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag) || node->hasTagName(appletTag)); + + return static_cast<HTMLPlugInElement*>(node); +} + +void SubframeLoader::clear() +{ + m_containsPlugins = false; +} + +bool SubframeLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) +{ + // Support for <frame src="javascript:string"> + KURL scriptURL; + KURL url; + if (protocolIsJavaScript(urlString)) { + scriptURL = completeURL(urlString); // completeURL() encodes the URL. + url = blankURL(); + } else + url = completeURL(urlString); + + Frame* frame = ownerElement->contentFrame(); + if (frame) + frame->redirectScheduler()->scheduleLocationChange(url.string(), m_frame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, m_frame->loader()->isProcessingUserGesture()); + else + frame = loadSubframe(ownerElement, url, frameName, m_frame->loader()->outgoingReferrer()); + + if (!frame) + return false; + + if (!scriptURL.isEmpty()) + frame->script()->executeIfJavaScriptURL(scriptURL); + + return true; +} + +bool SubframeLoader::requestObject(RenderEmbeddedObject* 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; + + if (!m_frame->script()->xssAuditor()->canLoadObject(url)) { + // It is unsafe to honor the request for this object. + 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 ((!allowPlugins(AboutToInstantiatePlugin) + // Application plugins are plugins implemented by the user agent, for example Qt plugins, + // as opposed to third-party code such as flash. The user agent decides whether or not they are + // permitted, rather than WebKit. + && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)) + || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) + return false; + if (m_frame->document() && m_frame->document()->securityOrigin()->isSandboxed(SandboxPlugins)) + 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()); + + // If the plug-in element already contains a subframe, requestFrame will re-use it. Otherwise, + // it will create a new frame and set it as the RenderPart's widget, causing what was previously + // in the widget to be torn down. + return requestFrame(element, completedURL, frameName); +} + + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +PassRefPtr<Widget> FrameLoader::loadMediaPlayerProxyPlugin(Node* node, const KURL& url, + const Vector<String>& paramNames, const Vector<String>& paramValues) +{ + ASSERT(node->hasTagName(videoTag) || node->hasTagName(audioTag)); + + if (!m_frame->script()->xssAuditor()->canLoadObject(url.string())) + return 0; + + KURL completedURL; + if (!url.isEmpty()) + completedURL = completeURL(url); + + if (!SecurityOrigin::canLoad(completedURL, String(), frame()->document())) { + FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string()); + return 0; + } + + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); + RenderPart* renderer = toRenderPart(node->renderer()); + IntSize size; + + if (renderer) + size = IntSize(renderer->contentWidth(), renderer->contentHeight()); + else if (mediaElement->isVideo()) + size = RenderVideo::defaultSize(); + + m_frame->loader()->checkIfRunInsecureContent(m_frame->document()->securityOrigin(), completedURL); + + RefPtr<Widget> widget = m_frame->loader()->client()->createMediaPlayerProxyPlugin(size, mediaElement, completedURL, + paramNames, paramValues, "application/x-media-element-proxy-plugin"); + + if (widget && renderer) { + renderer->setWidget(widget); + m_containsPlugIns = true; + renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); + } + + return widget ? widget.release() : 0; +} +#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) + +PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args) +{ + String baseURLString; + String codeBaseURLString; + Vector<String> paramNames; + Vector<String> paramValues; + HashMap<String, String>::const_iterator end = args.end(); + for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) { + if (equalIgnoringCase(it->first, "baseurl")) + baseURLString = it->second; + else if (equalIgnoringCase(it->first, "codebase")) + codeBaseURLString = it->second; + paramNames.append(it->first); + paramValues.append(it->second); + } + + if (!codeBaseURLString.isEmpty()) { + KURL codeBaseURL = completeURL(codeBaseURLString); + if (!SecurityOrigin::canLoad(codeBaseURL, String(), element->document())) { + FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string()); + return 0; + } + } + + if (baseURLString.isEmpty()) + baseURLString = m_frame->document()->baseURL().string(); + KURL baseURL = completeURL(baseURLString); + + RefPtr<Widget> widget = m_frame->loader()->client()->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); + if (!widget) + return 0; + + m_containsPlugins = true; + return widget; +} + +Frame* SubframeLoader::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 (!SecurityOrigin::canLoad(url, referrer, 0)) { + FrameLoader::reportLocalLoadFailed(m_frame, url.string()); + return 0; + } + + bool hideReferrer = SecurityOrigin::shouldHideReferrer(url, referrer); + RefPtr<Frame> frame = m_frame->loader()->client()->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight); + + if (!frame) { + m_frame->loader()->checkCallImplicitClose(); + return 0; + } + + // All new frames will have m_isComplete set to true at this point due to synchronously loading + // an empty document in FrameLoader::init(). But many frames will now be starting an + // asynchronous load of url, so we set m_isComplete to false and then check if the load is + // actually completed below. (Note that we set m_isComplete to false even for synchronous + // loads, so that checkCompleted() below won't bail early.) + // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed. + frame->loader()->started(); + + RenderObject* renderer = ownerElement->renderer(); + FrameView* view = frame->view(); + if (renderer && renderer->isWidget() && view) + toRenderWidget(renderer)->setWidget(view); + + m_frame->loader()->checkCallImplicitClose(); + + // Some loads are performed synchronously (e.g., about:blank and loads + // cancelled by returning a null ResourceRequest from requestFromDelegate). + // 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 and mark the load as being + // complete. + // 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 (frame->loader()->state() == FrameStateComplete) + frame->loader()->checkCompleted(); + + return frame.get(); +} + +bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins reason) +{ + Settings* settings = m_frame->settings(); + bool allowed = m_frame->loader()->client()->allowPlugins(settings && settings->arePluginsEnabled()); + if (!allowed && reason == AboutToInstantiatePlugin) + m_frame->loader()->client()->didNotAllowPlugins(); + return allowed; +} + + +bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) +{ + if (m_frame->loader()->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_frame->loader()->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; +} + +bool SubframeLoader::loadPlugin(RenderEmbeddedObject* renderer, const KURL& url, const String& mimeType, + const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) +{ + RefPtr<Widget> widget; + + if (renderer && !useFallback) { + HTMLPlugInElement* element = toPlugInElement(renderer->node()); + + if (!SecurityOrigin::canLoad(url, String(), m_frame->document())) { + FrameLoader::reportLocalLoadFailed(m_frame, url.string()); + return false; + } + + m_frame->loader()->checkIfRunInsecureContent(m_frame->document()->securityOrigin(), url); + + widget = m_frame->loader()->client()->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), + element, url, paramNames, paramValues, mimeType, + m_frame->document()->isPluginDocument() && !m_containsPlugins); + if (widget) { + renderer->setWidget(widget); + m_containsPlugins = true; + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); +#endif + } else + renderer->setShowsMissingPluginIndicator(); + } + + return widget; +} + +KURL SubframeLoader::completeURL(const String& url) const +{ + ASSERT(m_frame->document()); + return m_frame->document()->completeURL(url); +} + +} // namespace WebCore diff --git a/WebCore/loader/SubframeLoader.h b/WebCore/loader/SubframeLoader.h new file mode 100644 index 0000000..4bdb787 --- /dev/null +++ b/WebCore/loader/SubframeLoader.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SubframeLoader_h +#define SubframeLoader_h + +#include "FrameLoaderTypes.h" +#include "PlatformString.h" +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class AtomicString; +class Frame; +class FrameLoaderClient; +class HTMLAppletElement; +class HTMLFrameOwnerElement; +class IntSize; +class KURL; +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +class Node; +#endif +class RenderEmbeddedObject; +class Widget; + +// This is a slight misnomer. It handles the higher level logic of loading both subframes and plugins. +class SubframeLoader : public Noncopyable { +public: + SubframeLoader(Frame*); + + void clear(); + + bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName, bool lockHistory = true, bool lockBackForwardList = true); + bool requestObject(RenderEmbeddedObject*, const String& url, const AtomicString& frameName, + const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + PassRefPtr<Widget> loadMediaPlayerProxyPlugin(Node*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues); +#endif + + PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args); + + bool allowPlugins(ReasonForCallingAllowPlugins); + + bool containsPlugins() const { return m_containsPlugins; } + +private: + Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); + bool loadPlugin(RenderEmbeddedObject*, const KURL&, const String& mimeType, + const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); + + bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); + + bool m_containsPlugins; + Frame* m_frame; + + KURL completeURL(const String&) const; +}; + +} // namespace WebCore + +#endif // SubframeLoader_h diff --git a/WebCore/loader/SubresourceLoader.cpp b/WebCore/loader/SubresourceLoader.cpp index 4bd3c8d..d37bb1c 100644 --- a/WebCore/loader/SubresourceLoader.cpp +++ b/WebCore/loader/SubresourceLoader.cpp @@ -51,7 +51,6 @@ SubresourceLoader::SubresourceLoader(Frame* frame, SubresourceLoaderClient* clie #ifndef NDEBUG subresourceLoaderCounter.increment(); #endif - m_documentLoader->addSubresourceLoader(this); } SubresourceLoader::~SubresourceLoader() @@ -99,6 +98,7 @@ PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, Subresourc fl->addExtraFieldsToSubresourceRequest(newRequest); RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff))); + subloader->documentLoader()->addSubresourceLoader(subloader.get()); if (!subloader->load(newRequest)) return 0; diff --git a/WebCore/loader/TextDocument.cpp b/WebCore/loader/TextDocument.cpp index 68335a7..3360aca 100644 --- a/WebCore/loader/TextDocument.cpp +++ b/WebCore/loader/TextDocument.cpp @@ -44,8 +44,10 @@ public: virtual ~TextDocumentParser(); TextDocumentParser(HTMLViewSourceDocument*); +private: virtual void write(const SegmentedString&, bool appendData); virtual void finish(); + virtual bool finishWasCalled(); virtual bool isWaitingForScripts() const; inline void checkBuffer(int len = 10) @@ -59,9 +61,7 @@ public: m_size = newSize; } } - -private: - Document* m_doc; + Element* m_preElement; bool m_skipLF; @@ -71,8 +71,8 @@ private: UChar* m_dest; }; -TextDocumentParser::TextDocumentParser(Document* doc) - : m_doc(doc) +TextDocumentParser::TextDocumentParser(Document* document) + : DocumentParser(document) , m_preElement(0) , m_skipLF(false) { @@ -82,9 +82,8 @@ TextDocumentParser::TextDocumentParser(Document* doc) m_dest = m_buffer; } -TextDocumentParser::TextDocumentParser(HTMLViewSourceDocument* doc) - : DocumentParser(true) - , m_doc(doc) +TextDocumentParser::TextDocumentParser(HTMLViewSourceDocument* document) + : DocumentParser(document, true) , m_preElement(0) , m_skipLF(false) { @@ -132,13 +131,13 @@ void TextDocumentParser::write(const SegmentedString& s, bool) } if (!m_preElement && !inViewSourceMode()) { - RefPtr<Element> rootElement = m_doc->createElement(htmlTag, false); - m_doc->appendChild(rootElement, ec); + RefPtr<Element> rootElement = document()->createElement(htmlTag, false); + document()->appendChild(rootElement, ec); - RefPtr<Element> body = m_doc->createElement(bodyTag, false); + RefPtr<Element> body = document()->createElement(bodyTag, false); rootElement->appendChild(body, ec); - RefPtr<Element> preElement = m_doc->createElement(preTag, false); + RefPtr<Element> preElement = document()->createElement(preTag, false); preElement->setAttribute("style", "word-wrap: break-word; white-space: pre-wrap;", ec); body->appendChild(preElement, ec); @@ -148,14 +147,14 @@ void TextDocumentParser::write(const SegmentedString& s, bool) String string = String(m_buffer, m_dest - m_buffer); if (inViewSourceMode()) { - static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceText(string); + static_cast<HTMLViewSourceDocument*>(document())->addViewSourceText(string); return; } unsigned charsLeft = string.length(); while (charsLeft) { // split large text to nodes of manageable size - RefPtr<Text> text = Text::createWithLengthLimit(m_doc, string, charsLeft); + RefPtr<Text> text = Text::createWithLengthLimit(document(), string, charsLeft); m_preElement->appendChild(text, ec); } } @@ -169,7 +168,14 @@ void TextDocumentParser::finish() m_buffer = 0; m_dest = 0; - m_doc->finishedParsing(); + document()->finishedParsing(); +} + +bool TextDocumentParser::finishWasCalled() +{ + // finish() always calls document()->finishedParsing() so we'll be deleted + // after finish(). + return false; } bool TextDocumentParser::isWaitingForScripts() const @@ -178,8 +184,8 @@ bool TextDocumentParser::isWaitingForScripts() const return false; } -TextDocument::TextDocument(Frame* frame) - : HTMLDocument(frame) +TextDocument::TextDocument(Frame* frame, const KURL& url) + : HTMLDocument(frame, url) { } diff --git a/WebCore/loader/TextDocument.h b/WebCore/loader/TextDocument.h index 02c7af5..8f58b69 100644 --- a/WebCore/loader/TextDocument.h +++ b/WebCore/loader/TextDocument.h @@ -33,13 +33,13 @@ class HTMLViewSourceDocument; class TextDocument : public HTMLDocument { public: - static PassRefPtr<TextDocument> create(Frame* frame) + static PassRefPtr<TextDocument> create(Frame* frame, const KURL& url) { - return adoptRef(new TextDocument(frame)); + return adoptRef(new TextDocument(frame, url)); } private: - TextDocument(Frame*); + TextDocument(Frame*, const KURL&); virtual DocumentParser* createParser(); }; diff --git a/WebCore/loader/appcache/ApplicationCache.cpp b/WebCore/loader/appcache/ApplicationCache.cpp index c0cd3ea..2ad4a4b 100644 --- a/WebCore/loader/appcache/ApplicationCache.cpp +++ b/WebCore/loader/appcache/ApplicationCache.cpp @@ -130,7 +130,7 @@ ApplicationCacheResource* ApplicationCache::resourceForRequest(const ResourceReq { // We only care about HTTP/HTTPS GET requests. if (!requestIsHTTPOrHTTPSGet(request)) - return false; + return 0; KURL url(request.url()); if (url.hasFragmentIdentifier()) diff --git a/WebCore/loader/archive/cf/LegacyWebArchive.cpp b/WebCore/loader/archive/cf/LegacyWebArchive.cpp index 931b159..3a144c2 100644 --- a/WebCore/loader/archive/cf/LegacyWebArchive.cpp +++ b/WebCore/loader/archive/cf/LegacyWebArchive.cpp @@ -198,7 +198,7 @@ PassRefPtr<ArchiveResource> LegacyWebArchive::createResource(CFDictionaryRef dic } CFStringRef mimeType = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceMIMETypeKey)); - if (mimeType && CFGetTypeID(mimeType) != CFStringGetTypeID()) { + if (!mimeType || CFGetTypeID(mimeType) != CFStringGetTypeID()) { LOG(Archives, "LegacyWebArchive - MIME type is not of type CFString, cannot create invalid resource"); return 0; } diff --git a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm b/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm index c474bba..6a35753 100644 --- a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm +++ b/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm @@ -31,7 +31,7 @@ namespace WebCore { -static const NSString *LegacyWebArchiveResourceResponseKey = @"WebResourceResponse"; +static NSString * const LegacyWebArchiveResourceResponseKey = @"WebResourceResponse"; // FIXME: If is is possible to parse in a serialized NSURLResponse manually, without using // NSKeyedUnarchiver, manipulating plists directly, we would prefer to do that instead. |