summaryrefslogtreecommitdiffstats
path: root/WebCore/loader
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-06-28 16:42:48 +0100
committerKristian Monsen <kristianm@google.com>2010-07-02 10:29:56 +0100
commit06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch)
tree20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/loader
parent72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff)
downloadexternal_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')
-rw-r--r--WebCore/loader/CachedFont.cpp2
-rw-r--r--WebCore/loader/CrossOriginPreflightResultCache.h4
-rw-r--r--WebCore/loader/DocumentWriter.cpp51
-rw-r--r--WebCore/loader/DocumentWriter.h5
-rw-r--r--WebCore/loader/FTPDirectoryDocument.cpp55
-rw-r--r--WebCore/loader/FTPDirectoryDocument.h6
-rw-r--r--WebCore/loader/FormSubmission.cpp88
-rw-r--r--WebCore/loader/FormSubmission.h88
-rw-r--r--WebCore/loader/FrameLoader.cpp488
-rw-r--r--WebCore/loader/FrameLoader.h59
-rw-r--r--WebCore/loader/FrameLoaderStateMachine.cpp73
-rw-r--r--WebCore/loader/FrameLoaderStateMachine.h67
-rw-r--r--WebCore/loader/HistoryController.cpp80
-rw-r--r--WebCore/loader/HistoryController.h5
-rw-r--r--WebCore/loader/ImageDocument.cpp84
-rw-r--r--WebCore/loader/ImageDocument.h6
-rw-r--r--WebCore/loader/MainResourceLoader.cpp2
-rw-r--r--WebCore/loader/MediaDocument.cpp61
-rw-r--r--WebCore/loader/MediaDocument.h6
-rw-r--r--WebCore/loader/PlaceholderDocument.h6
-rw-r--r--WebCore/loader/PluginDocument.cpp70
-rw-r--r--WebCore/loader/PluginDocument.h6
-rw-r--r--WebCore/loader/ProgressTracker.cpp3
-rw-r--r--WebCore/loader/RedirectScheduler.cpp35
-rw-r--r--WebCore/loader/RedirectScheduler.h3
-rw-r--r--WebCore/loader/ResourceLoader.cpp9
-rw-r--r--WebCore/loader/SinkDocument.cpp33
-rw-r--r--WebCore/loader/SinkDocument.h6
-rw-r--r--WebCore/loader/SubframeLoader.cpp352
-rw-r--r--WebCore/loader/SubframeLoader.h92
-rw-r--r--WebCore/loader/SubresourceLoader.cpp2
-rw-r--r--WebCore/loader/TextDocument.cpp40
-rw-r--r--WebCore/loader/TextDocument.h6
-rw-r--r--WebCore/loader/appcache/ApplicationCache.cpp2
-rw-r--r--WebCore/loader/archive/cf/LegacyWebArchive.cpp2
-rw-r--r--WebCore/loader/archive/cf/LegacyWebArchiveMac.mm2
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.