summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/FrameLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/loader/FrameLoader.cpp')
-rw-r--r--WebCore/loader/FrameLoader.cpp921
1 files changed, 587 insertions, 334 deletions
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index 0285a8c..adaea61 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -1,6 +1,7 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,9 +54,9 @@
#include "Frame.h"
#include "FrameLoadRequest.h"
#include "FrameLoaderClient.h"
-#include "FramePrivate.h"
#include "FrameTree.h"
#include "FrameView.h"
+#include "HTMLAnchorElement.h"
#include "HTMLFormElement.h"
#include "HTMLFrameElement.h"
#include "HTMLNames.h"
@@ -72,24 +73,25 @@
#include "PageCache.h"
#include "PageGroup.h"
#include "PluginData.h"
+#include "PluginDocument.h"
#include "ProgressTracker.h"
#include "RenderPart.h"
-#include "RenderWidget.h"
#include "RenderView.h"
+#include "RenderWidget.h"
#include "ResourceHandle.h"
#include "ResourceRequest.h"
+#include "ScriptController.h"
+#include "ScriptSourceCode.h"
+#include "ScriptValue.h"
#include "SecurityOrigin.h"
#include "SegmentedString.h"
#include "Settings.h"
-#include "SystemTime.h"
#include "TextResourceDecoder.h"
#include "WindowFeatures.h"
#include "XMLHttpRequest.h"
#include "XMLTokenizer.h"
-#include "JSDOMBinding.h"
-#include "ScriptController.h"
-#include <runtime/JSLock.h>
-#include <runtime/JSObject.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/StdLibExtras.h>
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCache.h"
@@ -108,10 +110,9 @@
#ifdef ANDROID_INSTRUMENT
#include "TimeCounter.h"
+#include "RenderArena.h"
#endif
-using namespace JSC;
-
namespace WebCore {
#if ENABLE(SVG)
@@ -123,26 +124,33 @@ using namespace HTMLNames;
const unsigned int cMaxPendingSourceLengthInLowBandwidthDisplay = 128 * 1024;
#endif
+typedef HashSet<String, CaseFoldingHash> LocalSchemesMap;
+
struct FormSubmission {
+ FormSubmission(const char* action, const String& url, PassRefPtr<FormData> formData,
+ const String& target, const String& contentType, const String& boundary,
+ PassRefPtr<Event> event, bool lockHistory, bool lockBackForwardList)
+ : action(action)
+ , url(url)
+ , formData(formData)
+ , target(target)
+ , contentType(contentType)
+ , boundary(boundary)
+ , event(event)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ {
+ }
+
const char* action;
String url;
- RefPtr<FormData> data;
+ RefPtr<FormData> formData;
String target;
String contentType;
String boundary;
RefPtr<Event> event;
-
- FormSubmission(const char* a, const String& u, PassRefPtr<FormData> d, const String& t,
- const String& ct, const String& b, PassRefPtr<Event> e)
- : action(a)
- , url(u)
- , data(d)
- , target(t)
- , contentType(ct)
- , boundary(b)
- , event(e)
- {
- }
+ bool lockHistory;
+ bool lockBackForwardList;
};
struct ScheduledRedirection {
@@ -153,28 +161,32 @@ struct ScheduledRedirection {
String referrer;
int historySteps;
bool lockHistory;
+ bool lockBackForwardList;
bool wasUserGesture;
+ bool wasRefresh;
- ScheduledRedirection(double redirectDelay, const String& redirectURL, bool redirectLockHistory, bool userGesture)
+ ScheduledRedirection(double delay, const String& url, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
: type(redirection)
- , delay(redirectDelay)
- , url(redirectURL)
+ , delay(delay)
+ , url(url)
, historySteps(0)
- , lockHistory(redirectLockHistory)
- , wasUserGesture(userGesture)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ , wasUserGesture(wasUserGesture)
+ , wasRefresh(refresh)
{
}
- ScheduledRedirection(Type locationChangeType,
- const String& locationChangeURL, const String& locationChangeReferrer,
- bool locationChangeLockHistory, bool locationChangeWasUserGesture)
+ ScheduledRedirection(Type locationChangeType, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
: type(locationChangeType)
, delay(0)
- , url(locationChangeURL)
- , referrer(locationChangeReferrer)
+ , url(url)
+ , referrer(referrer)
, historySteps(0)
- , lockHistory(locationChangeLockHistory)
- , wasUserGesture(locationChangeWasUserGesture)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ , wasUserGesture(wasUserGesture)
+ , wasRefresh(refresh)
{
}
@@ -184,6 +196,7 @@ struct ScheduledRedirection {
, historySteps(historyNavigationSteps)
, lockHistory(false)
, wasUserGesture(false)
+ , wasRefresh(false)
{
}
};
@@ -191,26 +204,14 @@ struct ScheduledRedirection {
static double storedTimeOfLastCompletedLoad;
static FrameLoader::LocalLoadPolicy localLoadPolicy = FrameLoader::AllowLocalLoadsForLocalOnly;
-static bool getString(JSValue* result, String& string)
-{
- if (!result)
- return false;
- JSLock lock(false);
- UString ustring;
- if (!result->getString(ustring))
- return false;
- string = ustring;
- return true;
-}
-
bool isBackForwardLoadType(FrameLoadType type)
{
switch (type) {
case FrameLoadTypeStandard:
case FrameLoadTypeReload:
- case FrameLoadTypeReloadAllowingStaleData:
+ case FrameLoadTypeReloadFromOrigin:
case FrameLoadTypeSame:
- case FrameLoadTypeRedirectWithLockedHistory:
+ case FrameLoadTypeRedirectWithLockedBackForwardList:
case FrameLoadTypeReplace:
return false;
case FrameLoadTypeBack:
@@ -244,7 +245,6 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
, m_sentRedirectNotification(false)
, m_inStopAllLoaders(false)
, m_navigationDuringLoad(false)
- , m_cachePolicy(CachePolicyVerify)
, m_isExecutingJavaScriptFormAction(false)
, m_isRunningScript(false)
, m_didCallImplicitClose(false)
@@ -273,6 +273,9 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
, m_finishedParsingDuringLowBandwidthDisplay(false)
, m_needToSwitchOutLowBandwidthDisplay(false)
#endif
+#if ENABLE(WML)
+ , m_forceReloadWmlDeck(false)
+#endif
{
}
@@ -292,7 +295,7 @@ void FrameLoader::init()
// this somewhat odd set of steps is needed to give the frame an initial empty document
m_isDisplayingInitialEmptyDocument = false;
m_creatingInitialEmptyDocument = true;
- setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(String("")), SubstituteData()).get());
+ setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL("")), SubstituteData()).get());
setProvisionalDocumentLoader(m_policyDocumentLoader.get());
setState(FrameStateProvisional);
m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
@@ -322,7 +325,7 @@ Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const F
Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName());
if (frame && shouldAllowNavigation(frame)) {
if (!request.resourceRequest().url().isEmpty())
- frame->loader()->loadFrameRequestWithFormAndValues(request, false, 0, 0, HashMap<String, String>());
+ frame->loader()->loadFrameRequestWithFormAndValues(request, false, false, 0, 0, HashMap<String, String>());
if (Page* page = frame->page())
page->chrome()->focus();
created = false;
@@ -380,19 +383,17 @@ bool FrameLoader::canHandleRequest(const ResourceRequest& request)
return m_client->canHandleRequest(request);
}
-void FrameLoader::changeLocation(const String& url, const String& referrer, bool lockHistory, bool userGesture)
+void FrameLoader::changeLocation(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool userGesture, bool refresh)
{
- changeLocation(completeURL(url), referrer, lockHistory, userGesture);
+ changeLocation(completeURL(url), referrer, lockHistory, lockBackForwardList, userGesture, refresh);
}
-void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool lockHistory, bool userGesture)
+void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool userGesture, bool refresh)
{
RefPtr<Frame> protect(m_frame);
- ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)
- ? ReloadIgnoringCacheData : UseProtocolCachePolicy;
- ResourceRequest request(url, referrer, policy);
+ ResourceRequest request(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy);
#ifdef ANDROID_USER_GESTURE
request.setUserGesture(userGesture);
#endif
@@ -400,20 +401,20 @@ void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool l
if (executeIfJavaScriptURL(request.url(), userGesture))
return;
- urlSelected(request, "_self", 0, lockHistory, userGesture);
+ urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture);
}
-void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory)
+void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList)
{
FrameLoadRequest copy = request;
if (copy.resourceRequest().httpReferrer().isEmpty())
copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
addHTTPOriginIfNeeded(copy.resourceRequest(), outgoingOrigin());
- loadFrameRequestWithFormAndValues(copy, lockHistory, event, 0, HashMap<String, String>());
+ loadFrameRequestWithFormAndValues(copy, lockHistory, lockBackForwardList, event, 0, HashMap<String, String>());
}
-void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool userGesture)
+void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture)
{
if (executeIfJavaScriptURL(request.url(), userGesture, false))
return;
@@ -427,7 +428,7 @@ void FrameLoader::urlSelected(const ResourceRequest& request, const String& _tar
frameRequest.setWasUserGesture(userGesture);
#endif
- urlSelected(frameRequest, triggeringEvent, lockHistory);
+ urlSelected(frameRequest, triggeringEvent, lockHistory, lockBackForwardList);
}
bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName)
@@ -444,14 +445,14 @@ bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String
KURL scriptURL;
KURL url;
if (protocolIs(urlString, "javascript")) {
- scriptURL = KURL(urlString);
+ scriptURL = completeURL(urlString); // completeURL() encodes the URL.
url = blankURL();
} else
url = completeURL(urlString);
Frame* frame = ownerElement->contentFrame();
if (frame)
- frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, userGestureHint());
+ frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, userGestureHint());
else
frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
@@ -518,13 +519,13 @@ void FrameLoader::submitFormAgain()
if (m_isRunningScript)
return;
OwnPtr<FormSubmission> form(m_deferredFormSubmission.release());
- if (form)
- submitForm(form->action, form->url, form->data, form->target,
- form->contentType, form->boundary, form->event.get());
+ if (!form)
+ return;
+ submitForm(form->action, form->url, form->formData, form->target, form->contentType, form->boundary, form->event.get(), form->lockHistory, form->lockBackForwardList);
}
void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData,
- const String& target, const String& contentType, const String& boundary, Event* event)
+ const String& target, const String& contentType, const String& boundary, Event* event, bool lockHistory, bool lockBackForwardList)
{
ASSERT(formData);
@@ -547,8 +548,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
if (m_isRunningScript) {
if (m_deferredFormSubmission)
return;
- m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target,
- contentType, boundary, event));
+ m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target, contentType, boundary, event, lockHistory, lockBackForwardList));
return;
}
@@ -592,7 +592,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
frameRequest.resourceRequest().setURL(u);
addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
- submitForm(frameRequest, event);
+ submitForm(frameRequest, event, lockHistory, lockBackForwardList);
}
void FrameLoader::stopLoading(bool sendUnload)
@@ -623,7 +623,6 @@ void FrameLoader::stopLoading(bool sendUnload)
m_isComplete = true; // to avoid calling completed() in finishedParsing() (David)
m_isLoadingMainResource = false;
m_didCallImplicitClose = true; // don't want that one either
- m_cachePolicy = CachePolicyVerify; // Why here?
if (m_frame->document() && m_frame->document()->parsing()) {
finishedParsing();
@@ -636,8 +635,6 @@ void FrameLoader::stopLoading(bool sendUnload)
if (DocLoader* docLoader = doc->docLoader())
cache()->loader()->cancelRequests(docLoader);
- doc->stopActiveDOMObjects();
-
#if ENABLE(DATABASE)
doc->stopDatabases();
#endif
@@ -769,10 +766,10 @@ bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool
return false;
String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
- JSValue* result = executeScript(script, userGesture);
+ ScriptValue result = executeScript(script, userGesture);
String scriptResult;
- if (!getString(result, scriptResult))
+ if (!result.getString(scriptResult))
return true;
SecurityOrigin* currentSecurityOrigin = 0;
@@ -791,20 +788,20 @@ bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool
return true;
}
-JSValue* FrameLoader::executeScript(const String& script, bool forceUserGesture)
+ScriptValue FrameLoader::executeScript(const String& script, bool forceUserGesture)
{
- return executeScript(forceUserGesture ? String() : m_URL.string(), 1, script);
+ return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_URL));
}
-JSValue* FrameLoader::executeScript(const String& url, int baseLine, const String& script)
+ScriptValue FrameLoader::executeScript(const ScriptSourceCode& sourceCode)
{
if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused())
- return noValue();
+ return ScriptValue();
bool wasRunningScript = m_isRunningScript;
m_isRunningScript = true;
- JSValue* result = m_frame->script()->evaluate(url, baseLine, script);
+ ScriptValue result = m_frame->script()->evaluate(sourceCode);
if (!wasRunningScript) {
m_isRunningScript = false;
@@ -823,14 +820,11 @@ void FrameLoader::cancelAndClear()
closeURL();
clear(false);
+ m_frame->script()->updatePlatformScriptObjects();
}
void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
{
- // FIXME: Commenting out the below line causes <http://bugs.webkit.org/show_bug.cgi?id=11212>, but putting it
- // back causes a measurable performance regression which we will need to fix to restore the correct behavior
- // urlsBridgeKnowsAbout.clear();
-
m_frame->editor()->clear();
if (!m_needsClear)
@@ -839,6 +833,7 @@ void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
if (m_frame->document() && !m_frame->document()->inPageCache()) {
m_frame->document()->cancelParsing();
+ m_frame->document()->stopActiveDOMObjects();
if (m_frame->document()->attached()) {
m_frame->document()->willRemove();
m_frame->document()->detach();
@@ -895,7 +890,6 @@ void FrameLoader::receivedFirstData()
if (!ptitle.isNull())
m_client->dispatchDidReceiveTitle(ptitle);
- m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy);
m_workingURL = KURL();
double delay;
@@ -936,6 +930,8 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
bool resetScripting = !(m_isDisplayingInitialEmptyDocument && m_frame->document() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url));
clear(resetScripting, resetScripting);
+ if (resetScripting)
+ m_frame->script()->updatePlatformScriptObjects();
if (dispatch)
dispatchWindowObjectAvailable();
@@ -952,7 +948,12 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
m_outgoingReferrer = ref.string();
m_URL = url;
- RefPtr<Document> document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
+ RefPtr<Document> document;
+
+ if (!m_isDisplayingInitialEmptyDocument && m_client->shouldUsePluginDocument(m_responseMIMEType))
+ document = PluginDocument::create(m_frame);
+ else
+ document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
m_frame->setDocument(document);
document->setURL(m_URL);
@@ -1041,9 +1042,7 @@ void FrameLoader::write(const char* str, int len, bool flush)
#if USE(LOW_BANDWIDTH_DISPLAY)
if (m_frame->document()->inLowBandwidthDisplay())
- m_pendingSourceInLowBandwidthDisplay.append(decoded);
- else // reset policy which is changed in switchOutLowBandwidthDisplayIfReady()
- m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy);
+ m_pendingSourceInLowBandwidthDisplay.append(decoded);
#endif
if (!m_receivedData) {
@@ -1132,7 +1131,7 @@ void FrameLoader::startIconLoader()
return;
// If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load
- if (loadType() != FrameLoadTypeReload) {
+ if (loadType() != FrameLoadTypeReload && loadType() != FrameLoadTypeReloadFromOrigin) {
IconLoadDecision decision = iconDatabase()->loadDecisionForIconURL(urlString, m_documentLoader.get());
if (decision == IconLoadNo) {
LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
@@ -1188,9 +1187,9 @@ bool FrameLoader::allowSubstituteDataAccessToLocal()
return localLoadPolicy != FrameLoader::AllowLocalLoadsForLocalOnly;
}
-static HashSet<String, CaseFoldingHash>& localSchemes()
+static LocalSchemesMap& localSchemes()
{
- static HashSet<String, CaseFoldingHash> localSchemes;
+ DEFINE_STATIC_LOCAL(LocalSchemesMap, localSchemes, ());
if (localSchemes.isEmpty()) {
localSchemes.add("file");
@@ -1223,26 +1222,22 @@ void FrameLoader::restoreDocumentState()
switch (loadType()) {
case FrameLoadTypeReload:
-#ifndef ANDROID_HISTORY_CLIENT
- case FrameLoadTypeReloadAllowingStaleData:
-#endif
+ case FrameLoadTypeReloadFromOrigin:
case FrameLoadTypeSame:
case FrameLoadTypeReplace:
break;
case FrameLoadTypeBack:
case FrameLoadTypeForward:
case FrameLoadTypeIndexedBackForward:
- case FrameLoadTypeRedirectWithLockedHistory:
+ case FrameLoadTypeRedirectWithLockedBackForwardList:
case FrameLoadTypeStandard:
-#ifdef ANDROID_HISTORY_CLIENT
- case FrameLoadTypeReloadAllowingStaleData:
-#endif
itemToRestore = m_currentHistoryItem.get();
}
if (!itemToRestore)
return;
-
+
+ LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->name().string().utf8().data(), itemToRestore);
doc->setStateForNewFormElements(itemToRestore->documentState());
}
@@ -1274,6 +1269,8 @@ void FrameLoader::finishedParsing()
// Null-checking the FrameView indicates whether or not we're in the destructor.
RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
+ m_client->dispatchDidFinishDocumentLoad();
+
checkCompleted();
if (!m_frame->view())
@@ -1283,8 +1280,6 @@ void FrameLoader::finishedParsing()
// If not, remove them, relayout, and repaint.
m_frame->view()->restoreScrollbar();
- m_client->dispatchDidFinishDocumentLoad();
-
gotoAnchor();
}
@@ -1409,14 +1404,14 @@ void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
DocumentLoader* docLoader = activeDocumentLoader();
if (docLoader)
wasUserGesture = docLoader->request().userGesture();
- scheduleRedirection(new ScheduledRedirection(delay, url, delay <= 1, wasUserGesture));
+ scheduleRedirection(new ScheduledRedirection(delay, url, true, delay <= 1, wasUserGesture, false));
}
#else
- scheduleRedirection(new ScheduledRedirection(delay, url, delay <= 1, false));
+ scheduleRedirection(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
#endif
}
-void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool wasUserGesture)
+void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
{
if (!m_frame->page())
return;
@@ -1425,7 +1420,7 @@ void FrameLoader::scheduleLocationChange(const String& url, const String& referr
// fragment part, we don't need to schedule the location change.
KURL parsedURL(url);
if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) {
- changeLocation(url, referrer, lockHistory, wasUserGesture);
+ changeLocation(url, referrer, lockHistory, lockBackForwardList, wasUserGesture);
return;
}
@@ -1444,7 +1439,7 @@ void FrameLoader::scheduleLocationChange(const String& url, const String& referr
ScheduledRedirection::Type type = duringLoad
? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
- scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, wasUserGesture));
+ scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false));
}
void FrameLoader::scheduleRefresh(bool wasUserGesture)
@@ -1464,8 +1459,7 @@ void FrameLoader::scheduleRefresh(bool wasUserGesture)
ScheduledRedirection::Type type = duringLoad
? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
- scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, wasUserGesture));
- m_cachePolicy = CachePolicyRefresh;
+ scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, true, wasUserGesture, true));
}
bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection)
@@ -1549,12 +1543,12 @@ void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
case ScheduledRedirection::locationChange:
case ScheduledRedirection::locationChangeDuringLoad:
changeLocation(redirection->url, redirection->referrer,
- redirection->lockHistory, redirection->wasUserGesture);
+ redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
return;
case ScheduledRedirection::historyNavigation:
if (redirection->historySteps == 0) {
// Special case for go(0) from a frame -> reload only the frame
- urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->wasUserGesture);
+ urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
return;
}
// go(i!=0) from a frame navigates into the history of the frame only,
@@ -1577,32 +1571,21 @@ void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer,
ASSERT(childFrame);
HistoryItem* parentItem = currentHistoryItem();
FrameLoadType loadType = this->loadType();
- FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
+ FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
KURL workingURL = url;
// If we're moving in the backforward list, we might want to replace the content
// of this child frame with whatever was there at that point.
- // Reload will maintain the frame contents, LoadSame will not.
- if (parentItem && parentItem->children().size() &&
- (isBackForwardLoadType(loadType) || loadType == FrameLoadTypeReloadAllowingStaleData))
- {
+ if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType)) {
HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name());
if (childItem) {
// Use the original URL to ensure we get all the side-effects, such as
// onLoad handlers, of any redirects that happened. An example of where
// this is needed is Radar 3213556.
workingURL = KURL(childItem->originalURLString());
- // These behaviors implied by these loadTypes should apply to the child frames
childLoadType = loadType;
-
- if (isBackForwardLoadType(loadType)) {
- // For back/forward, remember this item so we can traverse any child items as child frames load
- childFrame->loader()->setProvisionalHistoryItem(childItem);
- } else {
- // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
- childFrame->loader()->setCurrentHistoryItem(childItem);
- }
+ childFrame->loader()->setProvisionalHistoryItem(childItem);
}
}
@@ -1614,9 +1597,9 @@ void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer,
else
#endif
#ifdef ANDROID_USER_GESTURE
- childFrame->loader()->loadURL(workingURL, referer, String(), childLoadType, 0, 0, false);
+ childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0, false);
#else
- childFrame->loader()->loadURL(workingURL, referer, String(), childLoadType, 0, 0);
+ childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0);
#endif
}
@@ -1664,9 +1647,7 @@ bool FrameLoader::gotoAnchor(const String& name)
m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
- Node* anchorNode = m_frame->document()->getElementById(AtomicString(name));
- if (!anchorNode && !name.isEmpty())
- anchorNode = m_frame->document()->anchors()->namedItem(name, !m_frame->document()->inCompatMode());
+ Element* anchorNode = m_frame->document()->findAnchor(name);
#if ENABLE(SVG)
if (m_frame->document()->isSVGDocument()) {
@@ -1758,10 +1739,16 @@ bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const A
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")) {
- String pluginName = m_frame->page()->pluginData()->pluginNameForMimeType(mimeType);
+ const PluginData* pluginData = m_frame->page()->pluginData();
+ String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false))
return true;
}
@@ -1896,14 +1883,10 @@ void FrameLoader::provisionalLoadStarted()
bool FrameLoader::userGestureHint()
{
- Frame* rootFrame = m_frame;
- while (rootFrame->tree()->parent())
- rootFrame = rootFrame->tree()->parent();
-
- if (rootFrame->script()->isEnabled())
- return rootFrame->script()->processingUserGesture();
-
- return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
+ Frame* frame = m_frame->tree()->top();
+ if (!frame->script()->isEnabled())
+ return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
+ return frame->script()->processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.
}
void FrameLoader::didNotOpenURL(const KURL& url)
@@ -1933,23 +1916,13 @@ void FrameLoader::addData(const char* bytes, int length)
write(bytes, length);
}
-bool FrameLoader::canCachePage()
-{
- // Cache the page, if possible.
- // Don't write to the cache if in the middle of a redirect, since we will want to
- // store the final page we end up on.
- // No point writing to the cache on a reload or loadSame, since we will just write
- // over it again when we leave that page.
- // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
- // are the most interesting pages on the web, and often those that would benefit the most from caching!
- FrameLoadType loadType = this->loadType();
-
+bool FrameLoader::canCachePageContainingThisFrame()
+{
return m_documentLoader
&& m_documentLoader->mainDocumentError().isNull()
&& !m_frame->tree()->childCount()
- && !m_frame->tree()->parent()
- // FIXME: If we ever change this so that pages with plug-ins will be cached,
- // we need to make sure that we don't cache pages that have outstanding NPObjects
+ // FIXME: If we ever change this so that frames with plug-ins will be cached,
+ // we need to make sure that we don't cache frames that have outstanding NPObjects
// (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
// they would need to be destroyed and then recreated, and there is no way that we can recreate
// the right NPObjects. See <rdar://problem/5197041> for more information.
@@ -1961,26 +1934,187 @@ bool FrameLoader::canCachePage()
&& !m_frame->document()->hasOpenDatabases()
#endif
&& !m_frame->document()->usingGeolocation()
- && m_frame->page()
- && m_frame->page()->backForwardList()->enabled()
- && m_frame->page()->backForwardList()->capacity() > 0
- && m_frame->page()->settings()->usesPageCache()
&& m_currentHistoryItem
&& !isQuickRedirectComing()
- && loadType != FrameLoadTypeReload
- && loadType != FrameLoadTypeReloadAllowingStaleData
- && loadType != FrameLoadTypeSame
&& !m_documentLoader->isLoadingInAPISense()
&& !m_documentLoader->isStopping()
+ && m_frame->document()->canSuspendActiveDOMObjects()
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // FIXME: We should investigating caching pages that have an associated
+ // FIXME: We should investigating caching frames that have an associated
// application cache. <rdar://problem/5917899> tracks that work.
&& !m_documentLoader->applicationCache()
&& !m_documentLoader->candidateApplicationCacheGroup()
#endif
+ && m_client->canCachePage()
;
}
+bool FrameLoader::canCachePage()
+{
+#ifndef NDEBUG
+ logCanCachePageDecision();
+#endif
+
+ // Cache the page, if possible.
+ // Don't write to the cache if in the middle of a redirect, since we will want to
+ // store the final page we end up on.
+ // No point writing to the cache on a reload or loadSame, since we will just write
+ // over it again when we leave that page.
+ // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
+ // are the most interesting pages on the web, and often those that would benefit the most from caching!
+ FrameLoadType loadType = this->loadType();
+
+ return !m_frame->tree()->parent()
+ && canCachePageContainingThisFrame()
+ && m_frame->page()
+ && m_frame->page()->backForwardList()->enabled()
+ && m_frame->page()->backForwardList()->capacity() > 0
+ && m_frame->page()->settings()->usesPageCache()
+ && loadType != FrameLoadTypeReload
+ && loadType != FrameLoadTypeReloadFromOrigin
+ && loadType != FrameLoadTypeSame
+ ;
+}
+
+#ifndef NDEBUG
+static String& pageCacheLogPrefix(int indentLevel)
+{
+ static int previousIndent = -1;
+ DEFINE_STATIC_LOCAL(String, prefix, ());
+
+ if (indentLevel != previousIndent) {
+ previousIndent = indentLevel;
+ prefix.truncate(0);
+ for (int i = 0; i < previousIndent; ++i)
+ prefix += " ";
+ }
+
+ return prefix;
+}
+
+static void pageCacheLog(const String& prefix, const String& message)
+{
+ LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
+}
+
+#define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), String::format(__VA_ARGS__))
+
+void FrameLoader::logCanCachePageDecision()
+{
+ // Only bother logging for main frames that have actually loaded and have content.
+ if (m_creatingInitialEmptyDocument)
+ return;
+ KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
+ if (currentURL.isEmpty())
+ return;
+
+ int indentLevel = 0;
+ PCLOG("--------\n Determining if page can be cached:");
+
+ bool cannotCache = !logCanCacheFrameDecision(1);
+
+ FrameLoadType loadType = this->loadType();
+ do {
+ if (m_frame->tree()->parent())
+ { PCLOG(" -Frame has a parent frame"); cannotCache = true; }
+ if (!m_frame->page()) {
+ PCLOG(" -There is no Page object");
+ cannotCache = true;
+ break;
+ }
+ if (!m_frame->page()->backForwardList()->enabled())
+ { PCLOG(" -The back/forward list is disabled"); cannotCache = true; }
+ if (!(m_frame->page()->backForwardList()->capacity() > 0))
+ { PCLOG(" -The back/forward list has a 0 capacity"); cannotCache = true; }
+ if (!m_frame->page()->settings()->usesPageCache())
+ { PCLOG(" -Page settings says b/f cache disabled"); cannotCache = true; }
+ if (loadType == FrameLoadTypeReload)
+ { PCLOG(" -Load type is: Reload"); cannotCache = true; }
+ if (loadType == FrameLoadTypeReloadFromOrigin)
+ { PCLOG(" -Load type is: Reload from origin"); cannotCache = true; }
+ if (loadType == FrameLoadTypeSame)
+ { PCLOG(" -Load type is: Same"); cannotCache = true; }
+ } while (false);
+
+ PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
+}
+
+bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
+{
+ // Only bother logging for frames that have actually loaded and have content.
+ if (m_creatingInitialEmptyDocument)
+ return false;
+ KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
+ if (currentURL.isEmpty())
+ return false;
+
+ PCLOG("+---");
+ KURL newURL = m_provisionalDocumentLoader ? m_provisionalDocumentLoader->url() : KURL();
+ if (!newURL.isEmpty())
+ PCLOG(" Determining if frame can be cached navigating from (%s) to (%s):", currentURL.string().utf8().data(), newURL.string().utf8().data());
+ else
+ PCLOG(" Determining if subframe with URL (%s) can be cached:", currentURL.string().utf8().data());
+
+ bool cannotCache = false;
+
+ do {
+ if (!m_documentLoader) {
+ PCLOG(" -There is no DocumentLoader object");
+ cannotCache = true;
+ break;
+ }
+ if (!m_documentLoader->mainDocumentError().isNull())
+ { PCLOG(" -Main document has an error"); cannotCache = true; }
+ if (m_frame->tree()->childCount())
+ { PCLOG(" -Frame has child frames"); cannotCache = true; }
+ if (m_containsPlugIns)
+ { PCLOG(" -Frame contains plugins"); cannotCache = true; }
+ if (m_URL.protocolIs("https"))
+ { PCLOG(" -Frame is HTTPS"); cannotCache = true; }
+ if (!m_frame->document()) {
+ PCLOG(" -There is no Document object");
+ cannotCache = true;
+ break;
+ }
+ if (m_frame->document()->hasWindowEventListener(eventNames().unloadEvent))
+ { PCLOG(" -Frame has an unload event listener"); cannotCache = true; }
+#if ENABLE(DATABASE)
+ if (m_frame->document()->hasOpenDatabases())
+ { PCLOG(" -Frame has open database handles"); cannotCache = true; }
+#endif
+ if (m_frame->document()->usingGeolocation())
+ { PCLOG(" -Frame uses Geolocation"); cannotCache = true; }
+ if (!m_currentHistoryItem)
+ { PCLOG(" -No current history item"); cannotCache = true; }
+ if (isQuickRedirectComing())
+ { PCLOG(" -Quick redirect is coming"); cannotCache = true; }
+ if (m_documentLoader->isLoadingInAPISense())
+ { PCLOG(" -DocumentLoader is still loading in API sense"); cannotCache = true; }
+ if (m_documentLoader->isStopping())
+ { PCLOG(" -DocumentLoader is in the middle of stopping"); cannotCache = true; }
+ if (!m_frame->document()->canSuspendActiveDOMObjects())
+ { PCLOG(" -The document cannot suspect its active DOM Objects"); cannotCache = true; }
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ if (m_documentLoader->applicationCache())
+ { PCLOG(" -The DocumentLoader has an active application cache"); cannotCache = true; }
+ if (m_documentLoader->candidateApplicationCacheGroup())
+ { PCLOG(" -The DocumentLoader has a candidateApplicationCacheGroup"); cannotCache = true; }
+#endif
+ if (!m_client->canCachePage())
+ { PCLOG(" -The client says this frame cannot be cached"); cannotCache = true; }
+ } while (false);
+
+ for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
+ if (!child->loader()->logCanCacheFrameDecision(indentLevel + 1))
+ cannotCache = true;
+
+ PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
+ PCLOG("+---");
+
+ return !cannotCache;
+}
+#endif
+
void FrameLoader::updatePolicyBaseURL()
{
if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
@@ -2047,7 +2181,7 @@ void FrameLoader::startRedirectionTimer()
clientRedirected(KURL(m_scheduledRedirection->url),
m_scheduledRedirection->delay,
currentTime() + m_redirectionTimer.nextFireInterval(),
- m_scheduledRedirection->lockHistory,
+ m_scheduledRedirection->lockBackForwardList,
m_isExecutingJavaScriptFormAction);
return;
case ScheduledRedirection::historyNavigation:
@@ -2120,18 +2254,22 @@ void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
}
-void FrameLoader::loadFrameRequestWithFormState(const FrameLoadRequest& request, bool lockHistory, Event* event, PassRefPtr<FormState> prpFormState)
+void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList, Event* event,
+ HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
{
- RefPtr<FormState> formState = prpFormState;
+ RefPtr<FormState> formState;
+ if (submitForm)
+ formState = FormState::create(submitForm, formValues, m_frame);
+
KURL url = request.resourceRequest().url();
-
+
String referrer;
String argsReferrer = request.resourceRequest().httpReferrer();
if (!argsReferrer.isEmpty())
referrer = argsReferrer;
else
referrer = m_outgoingReferrer;
-
+
ASSERT(frame()->document());
if (url.protocolIs("file")) {
if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
@@ -2143,51 +2281,38 @@ void FrameLoader::loadFrameRequestWithFormState(const FrameLoadRequest& request,
if (shouldHideReferrer(url, referrer))
referrer = String();
- Frame* targetFrame = findFrameForNavigation(request.frameName());
+ FrameLoadType loadType;
+ if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
+ loadType = FrameLoadTypeReload;
+ else if (lockBackForwardList)
+ loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
+ else
+ loadType = FrameLoadTypeStandard;
- if (request.resourceRequest().httpMethod() != "POST") {
- FrameLoadType loadType;
- if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
- loadType = FrameLoadTypeReload;
- else if (lockHistory)
- loadType = FrameLoadTypeRedirectWithLockedHistory;
- else
- loadType = FrameLoadTypeStandard;
-
+ if (request.resourceRequest().httpMethod() == "POST")
#ifdef ANDROID_USER_GESTURE
- loadURL(request.resourceRequest().url(), referrer, request.frameName(), loadType,
- event, formState.release(), request.wasUserGesture());
+ loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.release(), request.wasUserGesture());
#else
- loadURL(request.resourceRequest().url(), referrer, request.frameName(), loadType,
- event, formState.release());
+ loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
#endif
- } else
+ else
#ifdef ANDROID_USER_GESTURE
- loadPostRequest(request.resourceRequest(), referrer, request.frameName(), event, formState.release(), request.wasUserGesture());
+ loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.release(), request.wasUserGesture());
#else
- loadPostRequest(request.resourceRequest(), referrer, request.frameName(), event, formState.release());
+ loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.release());
#endif
+ Frame* targetFrame = findFrameForNavigation(request.frameName());
if (targetFrame && targetFrame != m_frame)
if (Page* page = targetFrame->page())
page->chrome()->focus();
}
-void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, Event* event,
- HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
-{
- RefPtr<FormState> formState;
- if (submitForm)
- formState = FormState::create(submitForm, formValues, m_frame);
-
- loadFrameRequestWithFormState(request, lockHistory, event, formState.release());
-}
-
#ifdef ANDROID_USER_GESTURE
-void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, FrameLoadType newLoadType,
+void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
Event* event, PassRefPtr<FormState> prpFormState, bool userGesture)
#else
-void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, FrameLoadType newLoadType,
+void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
Event* event, PassRefPtr<FormState> prpFormState)
#endif
{
@@ -2203,8 +2328,8 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
addHTTPOriginIfNeeded(request, referrerOrigin->toString());
}
- addExtraFieldsToRequest(request, true, event || isFormSubmission);
- if (newLoadType == FrameLoadTypeReload)
+ addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
+ if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
request.setCachePolicy(ReloadIgnoringCacheData);
ASSERT(newLoadType != FrameLoadTypeSame);
@@ -2214,9 +2339,9 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
if (!frameName.isEmpty()) {
if (Frame* targetFrame = findFrameForNavigation(frameName))
#ifdef ANDROID_USER_GESTURE
- targetFrame->loader()->loadURL(newURL, referrer, String(), newLoadType, event, formState, userGesture);
+ targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState, userGesture);
#else
- targetFrame->loader()->loadURL(newURL, referrer, String(), newLoadType, event, formState);
+ targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState);
#endif
else
checkNewWindowPolicy(action, request, formState, frameName);
@@ -2238,16 +2363,12 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
} else {
// must grab this now, since this load may stop the previous load and clear this flag
bool isRedirect = m_quickRedirectComing;
- loadWithNavigationAction(request, action, newLoadType, formState);
+ loadWithNavigationAction(request, action, lockHistory, newLoadType, formState);
if (isRedirect) {
m_quickRedirectComing = false;
if (m_provisionalDocumentLoader)
m_provisionalDocumentLoader->setIsClientRedirect(true);
-#ifdef ANDROID_HISTORY_CLIENT
- } else if (sameURL && (newLoadType != FrameLoadTypeReloadAllowingStaleData))
-#else
} else if (sameURL)
-#endif
// Example of this case are sites that reload the same URL with a different cookie
// driving the generated content, or a master frame with links that drive a target
// frame, where the user has clicked on the same link repeatedly.
@@ -2255,40 +2376,43 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
}
}
-void FrameLoader::load(const ResourceRequest& request)
+void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
{
- load(request, SubstituteData());
+ load(request, SubstituteData(), lockHistory);
}
-void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)
+void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
{
if (m_inStopAllLoaders)
return;
// FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
m_loadType = FrameLoadTypeStandard;
- load(m_client->createDocumentLoader(request, substituteData).get());
+ RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
+ loader->setURLForHistoryReflectsClientRedirect(lockHistory);
+ load(loader.get());
}
-void FrameLoader::load(const ResourceRequest& request, const String& frameName)
+void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
{
if (frameName.isEmpty()) {
- load(request);
+ load(request, lockHistory);
return;
}
Frame* frame = findFrameForNavigation(frameName);
if (frame) {
- frame->loader()->load(request);
+ frame->loader()->load(request, lockHistory);
return;
}
checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
}
-void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
+void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
{
RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
+ loader->setURLForHistoryReflectsClientRedirect(lockHistory);
loader->setTriggeringAction(action);
if (m_documentLoader)
@@ -2300,7 +2424,7 @@ void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const
void FrameLoader::load(DocumentLoader* newDocumentLoader)
{
ResourceRequest& r = newDocumentLoader->request();
- addExtraFieldsToRequest(r, true, false);
+ addExtraFieldsToMainResourceRequest(r);
FrameLoadType type;
if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
@@ -2483,7 +2607,7 @@ bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
}
-void FrameLoader::reloadAllowingStaleData(const String& encoding)
+void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
{
if (!m_documentLoader)
return;
@@ -2500,25 +2624,25 @@ void FrameLoader::reloadAllowingStaleData(const String& encoding)
loader->setOverrideEncoding(encoding);
- loadWithDocumentLoader(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
+ loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
}
-void FrameLoader::reload()
+void FrameLoader::reload(bool endToEndReload)
{
if (!m_documentLoader)
return;
- ResourceRequest& initialRequest = m_documentLoader->request();
-
// If a window is created by javascript, its main frame can have an empty but non-nil URL.
// Reloading in this case will lose the current contents (see 4151001).
- if (initialRequest.url().isEmpty())
+ if (m_documentLoader->request().url().isEmpty())
return;
+ ResourceRequest initialRequest = m_documentLoader->request();
+
// Replace error-page URL with the URL we were trying to reach.
KURL unreachableURL = m_documentLoader->unreachableURL();
if (!unreachableURL.isEmpty())
- initialRequest = ResourceRequest(unreachableURL);
+ initialRequest.setURL(unreachableURL);
// Create a new document loader for the reload, this will become m_documentLoader eventually,
// but first it has to be the "policy" document loader, and then the "provisional" document loader.
@@ -2526,8 +2650,8 @@ void FrameLoader::reload()
ResourceRequest& request = loader->request();
+ // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
request.setCachePolicy(ReloadIgnoringCacheData);
- request.setHTTPHeaderField("Cache-Control", "max-age=0");
// If we're about to re-post, set up action so the application can warn the user.
if (request.httpMethod() == "POST")
@@ -2535,7 +2659,7 @@ void FrameLoader::reload()
loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
- loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
+ loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
}
static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
@@ -2768,19 +2892,15 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
{
RefPtr<CachedPage> cachedPage = prpCachedPage;
RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
-
+
+ LOG(Loading, "WebCoreLoading %s: About to commit provisional load from previous URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
+
// 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.
- if (canCachePage() && m_client->canCachePage() && !m_currentHistoryItem->isInPageCache())
+ if (canCachePage() && !m_currentHistoryItem->isInPageCache()) {
+ if (Document* document = m_frame->document())
+ document->suspendActiveDOMObjects();
cachePageForHistoryItem(m_currentHistoryItem.get());
- else if (m_frame->page() && m_frame == m_frame->page()->mainFrame()) {
- // If the main frame installs a timeout late enough (for example in its onunload handler)
- // it could sometimes fire when transitioning to a non-HTML document representation (such as the Mac bookmarks view).
- // To avoid this, we clear all timeouts if the page is not to be cached in the back forward list.
- // Cached pages have their timers paused so they are fine.
- ScriptController* proxy = m_frame->script();
- if (proxy->haveWindowShell())
- proxy->windowShell()->window()->clearAllTimeouts();
}
if (m_loadType != FrameLoadTypeReplace)
@@ -2812,6 +2932,9 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
didOpenURL(url);
}
+
+ LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
+
opened();
}
@@ -2862,7 +2985,7 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
ASSERT(cachedDocumentLoader);
cachedDocumentLoader->setFrame(m_frame);
- m_client->transitionToCommittedFromCachedPage(cachedPage.get());
+ m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
} else
m_client->transitionToCommittedForNewPage();
@@ -2870,17 +2993,13 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
break;
case FrameLoadTypeReload:
+ case FrameLoadTypeReloadFromOrigin:
case FrameLoadTypeSame:
case FrameLoadTypeReplace:
updateHistoryForReload();
m_client->transitionToCommittedForNewPage();
break;
- // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
- case FrameLoadTypeReloadAllowingStaleData:
- m_client->transitionToCommittedForNewPage();
- break;
-
case FrameLoadTypeStandard:
updateHistoryForStandardLoad();
#ifndef BUILDING_ON_TIGER
@@ -2892,8 +3011,8 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
m_client->transitionToCommittedForNewPage();
break;
- case FrameLoadTypeRedirectWithLockedHistory:
- updateHistoryForRedirectWithLockedHistory();
+ case FrameLoadTypeRedirectWithLockedBackForwardList:
+ updateHistoryForRedirectWithLockedBackForwardList();
m_client->transitionToCommittedForNewPage();
break;
@@ -2910,9 +3029,9 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
if (m_creatingInitialEmptyDocument)
return;
-
- m_committedFirstRealDocumentLoad = true;
+ m_committedFirstRealDocumentLoad = true;
+
// For non-cached HTML pages, these methods are called in FrameLoader::begin.
if (cachedPage || !m_client->hasHTMLView()) {
dispatchDidCommitLoad();
@@ -2936,7 +3055,7 @@ void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgres
m_sentRedirectNotification = false;
}
-void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
+void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList, bool isJavaScriptFormAction)
{
m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
@@ -2947,11 +3066,24 @@ void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireD
// If a "quick" redirect comes in an, we set a special mode so we treat the next
// load as part of the same navigation. If we don't have a document loader, we have
// no "original" load on which to base a redirect, so we treat the redirect as a normal load.
- m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
+ m_quickRedirectComing = lockBackForwardList && m_documentLoader && !isJavaScriptFormAction;
}
+#if ENABLE(WML)
+void FrameLoader::setForceReloadWmlDeck(bool reload)
+{
+ m_forceReloadWmlDeck = reload;
+}
+#endif
+
bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
{
+#if ENABLE(WML)
+ // As for WML deck, sometimes it's supposed to be reloaded even if the same URL with fragment
+ if (m_forceReloadWmlDeck)
+ return true;
+#endif
+
// This function implements the rule: "Don't reload if navigating by fragment within
// the same URL, but do reload if going to a new URL or to the same URL with no
// fragment identifier at all."
@@ -3022,6 +3154,7 @@ void FrameLoader::open(CachedPage& cachedPage)
m_frame->setView(view);
m_frame->setDocument(document);
+ m_frame->setDOMWindow(cachedPage.domWindow());
m_frame->domWindow()->setURL(document->url());
m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
@@ -3030,6 +3163,11 @@ void FrameLoader::open(CachedPage& cachedPage)
updatePolicyBaseURL();
cachedPage.restore(m_frame->page());
+ document->resumeActiveDOMObjects();
+
+ // It is necessary to update any platform script objects after restoring the
+ // cached page.
+ m_frame->script()->updatePlatformScriptObjects();
checkCompleted();
}
@@ -3170,6 +3308,26 @@ FrameLoadType FrameLoader::loadType() const
{
return m_loadType;
}
+
+CachePolicy FrameLoader::cachePolicy() const
+{
+ if (m_isComplete)
+ return CachePolicyVerify;
+
+ if (m_loadType == FrameLoadTypeReloadFromOrigin)
+ return CachePolicyReload;
+
+ if (Frame* parentFrame = m_frame->tree()->parent()) {
+ CachePolicy parentCachePolicy = parentFrame->loader()->cachePolicy();
+ if (parentCachePolicy != CachePolicyVerify)
+ return parentCachePolicy;
+ }
+
+ if (m_loadType == FrameLoadTypeReload)
+ return CachePolicyRevalidate;
+
+ return CachePolicyVerify;
+}
void FrameLoader::stopPolicyCheck()
{
@@ -3226,8 +3384,11 @@ void FrameLoader::checkLoadCompleteForThisFrame()
}
}
if (shouldReset && item)
- if (Page* page = m_frame->page())
+ if (Page* page = m_frame->page()) {
page->backForwardList()->goToItem(item.get());
+ Settings* settings = m_frame->settings();
+ page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : item.get());
+ }
return;
}
@@ -3246,7 +3407,7 @@ void FrameLoader::checkLoadCompleteForThisFrame()
// If the user had a scroll point, scroll to it, overriding the anchor point if any.
if (Page* page = m_frame->page())
- if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList())
+ if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList())
restoreScrollPositionAndViewState();
if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
@@ -3265,8 +3426,9 @@ void FrameLoader::checkLoadCompleteForThisFrame()
page->progress()->progressCompleted(m_frame);
#ifdef ANDROID_INSTRUMENT
- if (!m_frame->tree()->parent())
- android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize());
+ if (!m_frame->tree()->parent() && m_frame->document()->renderArena())
+ android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(),
+ m_frame->document()->renderArena()->reportPoolSize());
#endif
return;
}
@@ -3334,6 +3496,11 @@ void FrameLoader::didFirstLayout()
m_client->dispatchDidFirstLayout();
}
+void FrameLoader::didFirstVisuallyNonEmptyLayout()
+{
+ m_client->dispatchDidFirstVisuallyNonEmptyLayout();
+}
+
void FrameLoader::frameLoadCompleted()
{
m_client->frameLoadCompleted();
@@ -3400,12 +3567,7 @@ int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
return count;
}
-FrameLoaderClient* FrameLoader::client() const
-{
- return m_client;
-}
-
-void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
+void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event, bool lockHistory, bool lockBackForwardList)
{
// FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
// We do not want to submit more than one form from the same page,
@@ -3424,8 +3586,7 @@ void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
m_submittedFormURL = request.resourceRequest().url();
}
- // FIXME: We should probably call userGestureHint() to tell whether this form submission was the result of a user gesture.
- loadFrameRequestWithFormAndValues(request, false, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
+ loadFrameRequestWithFormAndValues(request, lockHistory, lockBackForwardList, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
clearRecordedFormValues();
}
@@ -3443,16 +3604,6 @@ void FrameLoader::tokenizerProcessedData()
checkCompleted();
}
-void FrameLoader::didTellClientAboutLoad(const String& url)
-{
- m_urlsClientKnowsAbout.add(url);
-}
-
-bool FrameLoader::haveToldClientAboutLoad(const String& url)
-{
- return m_urlsClientKnowsAbout.contains(url);
-}
-
void FrameLoader::handledOnloadEvents()
{
m_client->dispatchDidHandleOnloadEvents();
@@ -3461,6 +3612,8 @@ void FrameLoader::handledOnloadEvents()
void FrameLoader::frameDetached()
{
stopAllLoaders();
+ if (Document* document = m_frame->document())
+ document->stopActiveDOMObjects();
detachFromParent();
}
@@ -3487,19 +3640,33 @@ void FrameLoader::detachFromParent()
m_frame->pageDestroyed();
}
}
+
+void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
+{
+ addExtraFieldsToRequest(request, m_loadType, false, false);
+}
-void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
+void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
+{
+ addExtraFieldsToRequest(request, m_loadType, true, false);
+}
+
+void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
{
applyUserAgent(request);
- if (m_loadType == FrameLoadTypeReload) {
+ if (loadType == FrameLoadTypeReload) {
request.setCachePolicy(ReloadIgnoringCacheData);
request.setHTTPHeaderField("Cache-Control", "max-age=0");
+ } else if (loadType == FrameLoadTypeReloadFromOrigin) {
+ request.setCachePolicy(ReloadIgnoringCacheData);
+ request.setHTTPHeaderField("Cache-Control", "no-cache");
+ request.setHTTPHeaderField("Pragma", "no-cache");
}
// Don't set the cookie policy URL if it's already been set.
if (request.mainDocumentURL().isEmpty()) {
- if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
+ if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
request.setMainDocumentURL(request.url());
else if (Page* page = m_frame->page())
request.setMainDocumentURL(page->mainFrame()->loader()->url());
@@ -3510,6 +3677,11 @@ void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainRes
// Make sure we send the Origin header.
addHTTPOriginIfNeeded(request, String());
+
+ // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
+ // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
+ Settings* settings = m_frame->settings();
+ request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_URL.isEmpty() ? m_encoding : encoding(), settings ? settings->defaultTextEncodingName() : String());
}
void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
@@ -3548,11 +3720,9 @@ void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int le
}
#ifdef ANDROID_USER_GESTURE
-void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName,
- Event* event, PassRefPtr<FormState> prpFormState, bool userGesture)
+void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState, bool userGesture)
#else
-void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName,
- Event* event, PassRefPtr<FormState> prpFormState)
+void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState)
#endif
{
RefPtr<FormState> formState = prpFormState;
@@ -3583,28 +3753,23 @@ void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String
workingResourceRequest.setHTTPMethod("POST");
workingResourceRequest.setHTTPBody(formData);
workingResourceRequest.setHTTPContentType(contentType);
- addExtraFieldsToRequest(workingResourceRequest, true, true);
+ addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
- NavigationAction action(url, FrameLoadTypeStandard, true, event);
+ NavigationAction action(url, loadType, true, event);
if (!frameName.isEmpty()) {
if (Frame* targetFrame = findFrameForNavigation(frameName))
- targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release());
+ targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
else
checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName);
} else
- loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release());
-}
-
-bool FrameLoader::isReloading() const
-{
- return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
+ loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
}
void FrameLoader::loadEmptyDocumentSynchronously()
{
ResourceRequest request(KURL(""));
- load(request);
+ load(request, false);
}
unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
@@ -3637,19 +3802,34 @@ unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& requ
if (error.isNull()) {
ASSERT(!newRequest.isNull());
- didTellClientAboutLoad(newRequest.url().string());
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
ApplicationCacheResource* resource;
if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) {
if (resource) {
response = resource->response();
- data.append(resource->data()->data(), resource->data()->size());
+ data.append(resource->data()->data(), resource->data()->size());
} else
error = cannotShowURLError(newRequest);
- } else
+ } else {
#endif
ResourceHandle::loadResourceSynchronously(newRequest, error, response, data, m_frame);
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent,
+ // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry
+ // corresponding to the matched namespace.
+ if ((!error.isNull() && !error.isCancellation())
+ || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
+ || !protocolHostAndPortAreEqual(newRequest.url(), response.url())) {
+ if (documentLoader()->getApplicationCacheFallbackResource(newRequest, resource)) {
+ response = resource->response();
+ data.clear();
+ data.append(resource->data()->data(), resource->data()->size());
+ }
+ }
+ }
+#endif
}
sendRemainingDelegateMessages(identifier, response, data.size(), error);
@@ -3742,10 +3922,7 @@ void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument
void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
{
- // FIXME:
- // some functions check m_quickRedirectComing, and others check for
- // FrameLoadTypeRedirectWithLockedHistory.
- bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedHistory;
+ bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedBackForwardList;
m_quickRedirectComing = false;
if (!shouldContinue)
@@ -3793,6 +3970,7 @@ bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType load
return !isFormSubmission
&& loadType != FrameLoadTypeReload
+ && loadType != FrameLoadTypeReloadFromOrigin
&& loadType != FrameLoadTypeSame
&& !shouldReload(this->url(), url)
// We don't want to just scroll if a link from within a
@@ -3937,7 +4115,7 @@ void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
}
-void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
+void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
{
// If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
// nil policyDataSource because loading the alternate page will have passed
@@ -3967,8 +4145,11 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& reque
if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
if (Page* page = m_frame->page()) {
Frame* mainFrame = page->mainFrame();
- if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
+ if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) {
page->backForwardList()->goToItem(resetItem);
+ Settings* settings = m_frame->settings();
+ page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem);
+ }
}
return;
}
@@ -4021,7 +4202,7 @@ void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& reques
mainFrame->loader()->setOpenedByDOM();
mainFrame->loader()->m_client->dispatchShow();
mainFrame->loader()->setOpener(frame.get());
- mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), FrameLoadTypeStandard, formState);
+ mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
}
void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
@@ -4061,29 +4242,31 @@ void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& i
void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
{
- ResourceRequest request(resource->url());
- const ResourceResponse& response = resource->response();
- SharedBuffer* data = resource->data();
- int length = data ? data->size() : 0;
+ Page* page = m_frame->page();
+ if (!page)
+ return;
- if (Page* page = m_frame->page())
- page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length);
+ page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource);
+
+ if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
+ return;
- if (!resource->sendResourceLoadCallbacks() || haveToldClientAboutLoad(resource->url()))
+ if (!page->areMemoryCacheClientCallsEnabled()) {
+ m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
+ m_documentLoader->didTellClientAboutLoad(resource->url());
return;
+ }
- if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length)) {
- didTellClientAboutLoad(resource->url());
+ ResourceRequest request(resource->url());
+ if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
+ m_documentLoader->didTellClientAboutLoad(resource->url());
return;
}
unsigned long identifier;
ResourceError error;
- ResourceRequest r(request);
- requestFromDelegate(r, identifier, error);
- sendRemainingDelegateMessages(identifier, response, length, error);
-
- didTellClientAboutLoad(resource->url());
+ requestFromDelegate(request, identifier, error);
+ sendRemainingDelegateMessages(identifier, resource->response(), resource->encodedSize(), error);
}
void FrameLoader::applyUserAgent(ResourceRequest& request)
@@ -4153,9 +4336,7 @@ void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
{
if (Page* page = m_frame->page()) {
RefPtr<CachedPage> cachedPage = CachedPage::create(page);
- cachedPage->setTimeStampToNow();
- cachedPage->setDocumentLoader(documentLoader());
- m_client->savePlatformDataToCachedPage(cachedPage.get());
+ m_client->savePlatformDataToCachedFrame(cachedPage->cachedMainFrame());
pageCache()->add(item, cachedPage.release());
}
@@ -4185,7 +4366,7 @@ PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
if (useOriginal)
url = originalURL;
else if (docLoader)
- url = docLoader->requestURL();
+ url = docLoader->requestURL();
}
LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data());
@@ -4206,7 +4387,10 @@ PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title);
item->setOriginalURLString(originalURL.string());
-
+
+ if (!unreachableURL.isEmpty() || !docLoader || docLoader->response().httpStatusCode() >= 400)
+ item->setLastVisitWasFailure(true);
+
// Save form state if this is a POST
if (docLoader) {
if (useOriginal)
@@ -4390,7 +4574,11 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
// check for all that as an additional optimization.
// We also do not do anchor-style navigation if we're posting a form.
+#if ENABLE(WML)
+ if (!formData && urlsMatchItem(item) && !m_frame->document()->isWMLDocument()) {
+#else
if (!formData && urlsMatchItem(item)) {
+#endif
// Must do this maintenance here, since we don't go through a real page reload
saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
@@ -4441,8 +4629,12 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
}
if (!inPageCache) {
+ bool addedExtraFields = false;
ResourceRequest request(itemURL);
+ if (!item->referrer().isNull())
+ request.setHTTPReferrer(item->referrer());
+
// If this was a repost that failed the page cache, we might try to repost the form.
NavigationAction action;
if (formData) {
@@ -4450,12 +4642,16 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
formData->generateFiles(m_frame->page()->chrome()->client());
request.setHTTPMethod("POST");
- request.setHTTPReferrer(item->formReferrer());
request.setHTTPBody(formData);
request.setHTTPContentType(item->formContentType());
- RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->formReferrer());
+ RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
addHTTPOriginIfNeeded(request, securityOrigin->toString());
+ // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
+ // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
+ addExtraFieldsToRequest(request, m_loadType, true, formData);
+ addedExtraFields = true;
+
// FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
// We want to know this before talking to the policy delegate, since it affects whether
// we show the DoYouReallyWantToRepost nag.
@@ -4473,6 +4669,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
} else {
switch (loadType) {
case FrameLoadTypeReload:
+ case FrameLoadTypeReloadFromOrigin:
request.setCachePolicy(ReloadIgnoringCacheData);
break;
case FrameLoadTypeBack:
@@ -4482,21 +4679,20 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
request.setCachePolicy(ReturnCacheDataElseLoad);
break;
case FrameLoadTypeStandard:
- case FrameLoadTypeRedirectWithLockedHistory:
- // no-op: leave as protocol default
- // FIXME: I wonder if we ever hit this case
+ case FrameLoadTypeRedirectWithLockedBackForwardList:
break;
case FrameLoadTypeSame:
- case FrameLoadTypeReloadAllowingStaleData:
default:
ASSERT_NOT_REACHED();
}
action = NavigationAction(itemOriginalURL, loadType, false);
}
+
+ if (!addedExtraFields)
+ addExtraFieldsToRequest(request, m_loadType, true, formData);
- addExtraFieldsToRequest(request, true, formData);
- loadWithNavigationAction(request, action, loadType, 0);
+ loadWithNavigationAction(request, action, false, loadType, 0);
}
}
}
@@ -4542,6 +4738,8 @@ void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type)
BackForwardList* bfList = page->backForwardList();
HistoryItem* currentItem = bfList->currentItem();
bfList->goToItem(targetItem);
+ Settings* settings = m_frame->settings();
+ page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : targetItem);
recursiveGoToItem(targetItem, currentItem, type);
}
@@ -4644,11 +4842,16 @@ void FrameLoader::updateHistoryForStandardLoad()
m_navigationDuringLoad = false;
}
+ bool didUpdateGlobalHistory = false;
if (!frameNavigationDuringLoad && !documentLoader()->isClientRedirect()) {
if (!historyURL.isEmpty()) {
addBackForwardItemClippedAtTarget(true);
- if (!needPrivacy)
- m_client->updateGlobalHistory(historyURL);
+ if (!needPrivacy) {
+ m_client->updateGlobalHistory();
+ didUpdateGlobalHistory = true;
+ }
+ if (Page* page = m_frame->page())
+ page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem());
}
} else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) {
m_currentHistoryItem->setURL(documentLoader()->url());
@@ -4658,6 +4861,9 @@ void FrameLoader::updateHistoryForStandardLoad()
if (!historyURL.isEmpty() && !needPrivacy) {
if (Page* page = m_frame->page())
page->group().addVisitedLink(historyURL);
+
+ if (!didUpdateGlobalHistory && !url().isEmpty())
+ m_client->updateGlobalHistoryForRedirectWithoutHistoryItem();
}
}
@@ -4706,7 +4912,7 @@ void FrameLoader::updateHistoryForReload()
if (m_currentHistoryItem) {
pageCache()->remove(m_currentHistoryItem.get());
- if (loadType() == FrameLoadTypeReload)
+ if (loadType() == FrameLoadTypeReload || loadType() == FrameLoadTypeReloadFromOrigin)
saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
// Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
@@ -4715,22 +4921,29 @@ void FrameLoader::updateHistoryForReload()
}
}
-void FrameLoader::updateHistoryForRedirectWithLockedHistory()
+void FrameLoader::updateHistoryForRedirectWithLockedBackForwardList()
{
#if !LOG_DISABLED
if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for internal load in frame %s", documentLoader()->title().utf8().data());
+ LOG(History, "WebCoreHistory: Updating History for redirect load in frame %s", documentLoader()->title().utf8().data());
#endif
Settings* settings = m_frame->settings();
bool needPrivacy = !settings || settings->privateBrowsingEnabled();
const KURL& historyURL = documentLoader()->urlForHistory();
+ bool didUpdateGlobalHistory = false;
if (documentLoader()->isClientRedirect()) {
if (!m_currentHistoryItem && !m_frame->tree()->parent()) {
- addBackForwardItemClippedAtTarget(true);
- if (!needPrivacy && !historyURL.isEmpty())
- m_client->updateGlobalHistory(historyURL);
+ if (!historyURL.isEmpty()) {
+ addBackForwardItemClippedAtTarget(true);
+ if (!needPrivacy) {
+ m_client->updateGlobalHistory();
+ didUpdateGlobalHistory = true;
+ }
+ if (Page* page = m_frame->page())
+ page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem());
+ }
}
if (m_currentHistoryItem) {
m_currentHistoryItem->setURL(documentLoader()->url());
@@ -4745,6 +4958,9 @@ void FrameLoader::updateHistoryForRedirectWithLockedHistory()
if (!historyURL.isEmpty() && !needPrivacy) {
if (Page* page = m_frame->page())
page->group().addVisitedLink(historyURL);
+
+ if (!didUpdateGlobalHistory && !url().isEmpty())
+ m_client->updateGlobalHistoryForRedirectWithoutHistoryItem();
}
}
@@ -4756,7 +4972,7 @@ void FrameLoader::updateHistoryForCommit()
#endif
FrameLoadType type = loadType();
if (isBackForwardLoadType(type) ||
- (type == FrameLoadTypeReload && !provisionalDocumentLoader()->unreachableURL().isEmpty())) {
+ ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !provisionalDocumentLoader()->unreachableURL().isEmpty())) {
// Once committed, we want to use current item for saving DocState, and
// the provisional item for restoring state.
// Note previousItem must be set before we close the URL, which will
@@ -4831,7 +5047,7 @@ void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceErr
m_client->setMainDocumentError(loader, error);
}
-void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError& error)
+void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError&)
{
loader->setPrimaryLoadComplete(true);
m_client->dispatchDidLoadMainResource(activeDocumentLoader());
@@ -4874,6 +5090,11 @@ void FrameLoader::didFinishLoad(ResourceLoader* loader)
dispatchDidFinishLoading(loader->documentLoader(), loader->identifier());
}
+bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader)
+{
+ return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier());
+}
+
void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
{
m_client->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
@@ -5128,8 +5349,15 @@ void FrameLoader::dispatchAssignIdentifierToInitialRequest(unsigned long identif
void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
+ StringImpl* oldRequestURL = request.url().string().impl();
+ m_documentLoader->didTellClientAboutLoad(request.url());
+
m_client->dispatchWillSendRequest(loader, identifier, request, redirectResponse);
+ // If the URL changed, then we want to put that new URL in the "did tell client" set too.
+ if (!request.isNull() && oldRequestURL != request.url().string().impl())
+ m_documentLoader->didTellClientAboutLoad(request.url());
+
if (Page* page = m_frame->page())
page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse);
}
@@ -5158,6 +5386,33 @@ void FrameLoader::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long
page->inspectorController()->didFinishLoading(loader, identifier);
}
+void FrameLoader::tellClientAboutPastMemoryCacheLoads()
+{
+ ASSERT(m_frame->page());
+ ASSERT(m_frame->page()->areMemoryCacheClientCallsEnabled());
+
+ if (!m_documentLoader)
+ return;
+
+ Vector<String> pastLoads;
+ m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
+
+ size_t size = pastLoads.size();
+ for (size_t i = 0; i < size; ++i) {
+ CachedResource* resource = cache()->resourceForURL(pastLoads[i]);
+
+ // FIXME: These loads, loaded from cache, but now gone from the cache by the time
+ // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
+ // Consider if there's some efficient way of remembering enough to deliver this client call.
+ // We have the URL, but not the rest of the response or the length.
+ if (!resource)
+ continue;
+
+ ResourceRequest request(resource->url());
+ m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
+ }
+}
+
#if USE(LOW_BANDWIDTH_DISPLAY)
bool FrameLoader::addLowBandwidthDisplayRequest(CachedResource* cache)
@@ -5255,8 +5510,6 @@ void FrameLoader::switchOutLowBandwidthDisplayIfReady()
// write decoded data to the new doc, similar to write()
if (m_pendingSourceInLowBandwidthDisplay.length()) {
- // set cachePolicy to Cache to use the loaded resource
- newDoc->docLoader()->setCachePolicy(CachePolicyCache);
if (m_decoder->encoding().usesVisualOrdering())
newDoc->setVisuallyOrdered();
newDoc->recalcStyle(Node::Force);