7f336a575efd5ec58084a6c4cc14f6f89bbdc8f8
[WebKit-https.git] / Source / WebCore / loader / FrameLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
7  * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1.  Redistributions of source code must retain the above copyright
14  *     notice, this list of conditions and the following disclaimer. 
15  * 2.  Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in the
17  *     documentation and/or other materials provided with the distribution. 
18  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
19  *     its contributors may be used to endorse or promote products derived
20  *     from this software without specific prior written permission. 
21  *
22  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "config.h"
35 #include "FrameLoader.h"
36
37 #include "ApplicationCacheHost.h"
38 #include "BackForwardController.h"
39 #include "BeforeUnloadEvent.h"
40 #include "MemoryCache.h"
41 #include "CachedPage.h"
42 #include "CachedResourceLoader.h"
43 #include "Chrome.h"
44 #if ENABLE(TOUCH_EVENTS)
45 #include "ChromeClient.h"
46 #endif
47 #include "Console.h"
48 #include "ContentSecurityPolicy.h"
49 #include "DOMImplementation.h"
50 #include "DOMWindow.h"
51 #include "Document.h"
52 #include "DocumentLoadTiming.h"
53 #include "DocumentLoader.h"
54 #include "Editor.h"
55 #include "EditorClient.h"
56 #include "Element.h"
57 #include "Event.h"
58 #include "EventNames.h"
59 #include "FloatRect.h"
60 #include "FormState.h"
61 #include "FormSubmission.h"
62 #include "Frame.h"
63 #include "FrameLoadRequest.h"
64 #include "FrameLoaderClient.h"
65 #include "FrameNetworkingContext.h"
66 #include "FrameTree.h"
67 #include "FrameView.h"
68 #include "HTMLAnchorElement.h"
69 #include "HTMLFormElement.h"
70 #include "HTMLNames.h"
71 #include "HTMLObjectElement.h"
72 #include "HTTPParsers.h"
73 #include "HistoryItem.h"
74 #include "IconDatabase.h"
75 #include "IconLoader.h"
76 #include "IconURL.h"
77 #include "InspectorController.h"
78 #include "InspectorInstrumentation.h"
79 #include "Logging.h"
80 #include "MIMETypeRegistry.h"
81 #include "MainResourceLoader.h"
82 #include "Page.h"
83 #include "PageCache.h"
84 #include "PageGroup.h"
85 #include "PageTransitionEvent.h"
86 #include "PluginData.h"
87 #include "PluginDatabase.h"
88 #include "PluginDocument.h"
89 #include "ProgressTracker.h"
90 #include "ResourceHandle.h"
91 #include "ResourceRequest.h"
92 #include "SchemeRegistry.h"
93 #include "ScrollAnimator.h"
94 #include "ScriptController.h"
95 #include "ScriptSourceCode.h"
96 #include "SecurityOrigin.h"
97 #include "SegmentedString.h"
98 #include "SerializedScriptValue.h"
99 #include "Settings.h"
100 #include "TextResourceDecoder.h"
101 #include "WindowFeatures.h"
102 #include "XMLDocumentParser.h"
103 #include <wtf/CurrentTime.h>
104 #include <wtf/StdLibExtras.h>
105 #include <wtf/text/CString.h>
106 #include <wtf/text/WTFString.h>
107
108 #if ENABLE(SHARED_WORKERS)
109 #include "SharedWorkerRepository.h"
110 #endif
111
112 #if ENABLE(SVG)
113 #include "SVGDocument.h"
114 #include "SVGLocatable.h"
115 #include "SVGNames.h"
116 #include "SVGPreserveAspectRatio.h"
117 #include "SVGSVGElement.h"
118 #include "SVGViewElement.h"
119 #include "SVGViewSpec.h"
120 #endif
121
122 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
123 #include "Archive.h"
124 #include "ArchiveFactory.h"
125 #endif
126
127 namespace WebCore {
128
129 using namespace HTMLNames;
130
131 #if ENABLE(SVG)
132 using namespace SVGNames;
133 #endif
134
135 #if ENABLE(XHTMLMP)
136 static const char defaultAcceptHeader[] = "application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html,application/xml;q=0.9,*/*;q=0.8";
137 #else
138 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
139 #endif
140
141 static double storedTimeOfLastCompletedLoad;
142
143 bool isBackForwardLoadType(FrameLoadType type)
144 {
145     switch (type) {
146         case FrameLoadTypeStandard:
147         case FrameLoadTypeReload:
148         case FrameLoadTypeReloadFromOrigin:
149         case FrameLoadTypeSame:
150         case FrameLoadTypeRedirectWithLockedBackForwardList:
151         case FrameLoadTypeReplace:
152             return false;
153         case FrameLoadTypeBack:
154         case FrameLoadTypeForward:
155         case FrameLoadTypeIndexedBackForward:
156             return true;
157     }
158     ASSERT_NOT_REACHED();
159     return false;
160 }
161
162 static int numRequests(Document* document)
163 {
164     if (!document)
165         return 0;
166     
167     return document->cachedResourceLoader()->requestCount();
168 }
169
170 // This is not in the FrameLoader class to emphasize that it does not depend on
171 // private FrameLoader data, and to avoid increasing the number of public functions
172 // with access to private data.  Since only this .cpp file needs it, making it
173 // non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
174 // API simpler.
175 //
176 // FIXME: isDocumentSandboxed should eventually replace isSandboxed.
177 static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask)
178 {
179     return frame->document() && frame->document()->securityOrigin()->isSandboxed(mask);
180 }
181
182 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
183     : m_frame(frame)
184     , m_client(client)
185     , m_policyChecker(frame)
186     , m_history(frame)
187     , m_notifer(frame)
188     , m_subframeLoader(frame)
189     , m_state(FrameStateCommittedPage)
190     , m_loadType(FrameLoadTypeStandard)
191     , m_delegateIsHandlingProvisionalLoadError(false)
192     , m_quickRedirectComing(false)
193     , m_sentRedirectNotification(false)
194     , m_inStopAllLoaders(false)
195     , m_isExecutingJavaScriptFormAction(false)
196     , m_didCallImplicitClose(false)
197     , m_wasUnloadEventEmitted(false)
198     , m_pageDismissalEventBeingDispatched(false)
199     , m_isComplete(false)
200     , m_isLoadingMainResource(false)
201     , m_needsClear(false)
202     , m_checkTimer(this, &FrameLoader::checkTimerFired)
203     , m_shouldCallCheckCompleted(false)
204     , m_shouldCallCheckLoadComplete(false)
205     , m_opener(0)
206     , m_didPerformFirstNavigation(false)
207     , m_loadingFromCachedPage(false)
208     , m_suppressOpenerInNewFrame(false)
209     , m_sandboxFlags(SandboxAll)
210     , m_forcedSandboxFlags(SandboxNone)
211 {
212 }
213
214 FrameLoader::~FrameLoader()
215 {
216     setOpener(0);
217
218     HashSet<Frame*>::iterator end = m_openedFrames.end();
219     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
220         (*it)->loader()->m_opener = 0;
221
222     m_client->frameLoaderDestroyed();
223
224     if (m_networkingContext)
225         m_networkingContext->invalidate();
226 }
227
228 void FrameLoader::init()
229 {
230     // Propagate sandbox attributes to this Frameloader and its descendants.
231     // This needs to be done early, so that an initial document gets correct sandbox flags in its SecurityOrigin.
232     updateSandboxFlags();
233
234     // this somewhat odd set of steps is needed to give the frame an initial empty document
235     m_stateMachine.advanceTo(FrameLoaderStateMachine::CreatingInitialEmptyDocument);
236     setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get());
237     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
238     setState(FrameStateProvisional);
239     m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
240     m_provisionalDocumentLoader->finishedLoading();
241     m_documentLoader->writer()->begin(KURL(), false);
242     m_documentLoader->writer()->end();
243     m_frame->document()->cancelParsing();
244     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
245     m_didCallImplicitClose = true;
246
247     m_networkingContext = m_client->createNetworkingContext();
248 }
249
250 void FrameLoader::setDefersLoading(bool defers)
251 {
252     if (m_documentLoader)
253         m_documentLoader->setDefersLoading(defers);
254     if (m_provisionalDocumentLoader)
255         m_provisionalDocumentLoader->setDefersLoading(defers);
256     if (m_policyDocumentLoader)
257         m_policyDocumentLoader->setDefersLoading(defers);
258     history()->setDefersLoading(defers);
259
260     if (!defers) {
261         m_frame->navigationScheduler()->startTimer();
262         startCheckCompleteTimer();
263     }
264 }
265
266 bool FrameLoader::canHandleRequest(const ResourceRequest& request)
267 {
268     return m_client->canHandleRequest(request);
269 }
270
271 void FrameLoader::changeLocation(PassRefPtr<SecurityOrigin> securityOrigin, const KURL& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool refresh)
272 {
273     RefPtr<Frame> protect(m_frame);
274     urlSelected(FrameLoadRequest(securityOrigin, ResourceRequest(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy), "_self"),
275         0, lockHistory, lockBackForwardList, SendReferrer, ReplaceDocumentIfJavaScriptURL);
276 }
277
278 void FrameLoader::urlSelected(const KURL& url, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy)
279 {
280     urlSelected(FrameLoadRequest(m_frame->document()->securityOrigin(), ResourceRequest(url), passedTarget),
281         triggeringEvent, lockHistory, lockBackForwardList, referrerPolicy, DoNotReplaceDocumentIfJavaScriptURL);
282 }
283
284 // The shouldReplaceDocumentIfJavaScriptURL parameter will go away when the FIXME to eliminate the
285 // corresponding parameter from ScriptController::executeIfJavaScriptURL() is addressed.
286 void FrameLoader::urlSelected(const FrameLoadRequest& passedRequest, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL)
287 {
288     ASSERT(!m_suppressOpenerInNewFrame);
289
290     FrameLoadRequest frameRequest(passedRequest);
291
292     if (m_frame->script()->executeIfJavaScriptURL(frameRequest.resourceRequest().url(), shouldReplaceDocumentIfJavaScriptURL))
293         return;
294
295     if (frameRequest.frameName().isEmpty())
296         frameRequest.setFrameName(m_frame->document()->baseTarget());
297
298     if (referrerPolicy == NoReferrer)
299         m_suppressOpenerInNewFrame = true;
300     if (frameRequest.resourceRequest().httpReferrer().isEmpty())
301         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
302     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
303
304     loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy);
305
306     m_suppressOpenerInNewFrame = false;
307 }
308
309 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
310 {
311     ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod);
312
313     // FIXME: Find a good spot for these.
314     ASSERT(submission->data());
315     ASSERT(submission->state());
316     ASSERT(submission->state()->sourceFrame() == m_frame);
317     
318     if (!m_frame->page())
319         return;
320     
321     if (submission->action().isEmpty())
322         return;
323
324     if (isDocumentSandboxed(m_frame, SandboxForms))
325         return;
326
327     if (protocolIsJavaScript(submission->action())) {
328         m_isExecutingJavaScriptFormAction = true;
329         m_frame->script()->executeIfJavaScriptURL(submission->action(), DoNotReplaceDocumentIfJavaScriptURL);
330         m_isExecutingJavaScriptFormAction = false;
331         return;
332     }
333
334     Frame* targetFrame = m_frame->tree()->find(submission->target());
335     if (!shouldAllowNavigation(targetFrame))
336         return;
337     if (!targetFrame) {
338         if (!DOMWindow::allowPopUp(m_frame) && !isProcessingUserGesture())
339             return;
340
341         targetFrame = m_frame;
342     } else
343         submission->clearTarget();
344
345     if (!targetFrame->page())
346         return;
347
348     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
349
350     // We do not want to submit more than one form from the same page, nor do we want to submit a single
351     // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
352     // The flag is reset in each time we start handle a new mouse or key down event, and
353     // also in setView since this part may get reused for a page from the back/forward cache.
354     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
355
356     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
357     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
358     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
359
360     if (m_frame->tree()->isDescendantOf(targetFrame)) {
361         if (m_submittedFormURL == submission->action())
362             return;
363         m_submittedFormURL = submission->action();
364     }
365
366     submission->data()->generateFiles(m_frame->document());
367     submission->setReferrer(m_outgoingReferrer);
368     submission->setOrigin(outgoingOrigin());
369
370     targetFrame->navigationScheduler()->scheduleFormSubmission(submission);
371 }
372
373 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
374 {
375     if (m_frame->document() && m_frame->document()->parser())
376         m_frame->document()->parser()->stopParsing();
377
378     if (unloadEventPolicy != UnloadEventPolicyNone) {
379         if (m_frame->document()) {
380             if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
381                 Node* currentFocusedNode = m_frame->document()->focusedNode();
382                 if (currentFocusedNode)
383                     currentFocusedNode->aboutToUnload();
384                 m_pageDismissalEventBeingDispatched = true;
385                 if (m_frame->domWindow()) {
386                     if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide)
387                         m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
388                     if (!m_frame->document()->inPageCache()) {
389                         RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
390                         // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
391                         // while dispatching the event, so protect it to prevent writing the end
392                         // time into freed memory.
393                         RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
394                         if (documentLoader && !documentLoader->timing()->unloadEventStart && !documentLoader->timing()->unloadEventEnd) {
395                             DocumentLoadTiming* timing = documentLoader->timing();
396                             ASSERT(timing->navigationStart);
397                             m_frame->domWindow()->dispatchTimedEvent(unloadEvent, m_frame->domWindow()->document(), &timing->unloadEventStart, &timing->unloadEventEnd);
398                         } else
399                             m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->domWindow()->document());
400                     }
401                 }
402                 m_pageDismissalEventBeingDispatched = false;
403                 if (m_frame->document())
404                     m_frame->document()->updateStyleIfNeeded();
405                 m_wasUnloadEventEmitted = true;
406             }
407         }
408
409         // Dispatching the unload event could have made m_frame->document() null.
410         if (m_frame->document() && !m_frame->document()->inPageCache()) {
411             // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
412             bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
413                 && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
414
415             if (!keepEventListeners)
416                 m_frame->document()->removeAllEventListeners();
417         }
418     }
419
420     m_isComplete = true; // to avoid calling completed() in finishedParsing()
421     m_isLoadingMainResource = false;
422     m_didCallImplicitClose = true; // don't want that one either
423
424     if (m_frame->document() && m_frame->document()->parsing()) {
425         finishedParsing();
426         m_frame->document()->setParsing(false);
427     }
428   
429     m_workingURL = KURL();
430
431     if (Document* doc = m_frame->document()) {
432         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
433         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
434         doc->setReadyState(Document::Complete);
435
436 #if ENABLE(DATABASE)
437         doc->stopDatabases(0);
438 #endif
439     }
440
441     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
442     m_frame->navigationScheduler()->cancel();
443 }
444
445 void FrameLoader::stop()
446 {
447     // http://bugs.webkit.org/show_bug.cgi?id=10854
448     // The frame's last ref may be removed and it will be deleted by checkCompleted().
449     RefPtr<Frame> protector(m_frame);
450
451     if (DocumentParser* parser = m_frame->document()->parser()) {
452         parser->stopParsing();
453         parser->finish();
454     }
455
456     if (m_iconLoader)
457         m_iconLoader->stopLoading();
458 }
459
460 bool FrameLoader::closeURL()
461 {
462     history()->saveDocumentState();
463     
464     // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.    
465     Document* currentDocument = m_frame->document();
466     stopLoading(currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly);
467     
468     m_frame->editor()->clearUndoRedoOperations();
469     return true;
470 }
471
472 KURL FrameLoader::iconURL()
473 {
474     IconURLs urls = iconURLs(Favicon);
475     return urls.isEmpty() ? KURL() : urls[0].m_iconURL;
476 }
477
478 IconURLs FrameLoader::iconURLs(int iconTypes)
479 {
480     IconURLs iconURLs;
481     // If this isn't a top level frame, return
482     if (m_frame->tree() && m_frame->tree()->parent())
483         return iconURLs;
484
485     if (iconTypes & Favicon && !fillIconURL(Favicon, &iconURLs))
486         iconURLs.append(getDefaultIconURL(Favicon));
487
488 #if ENABLE(TOUCH_ICON_LOADING)
489     bool havePrecomposedIcon = false;
490     if (iconTypes & TouchPrecomposedIcon)
491         havePrecomposedIcon = fillIconURL(TouchPrecomposedIcon, &iconURLs);
492
493     bool haveTouchIcon = false;
494     if (iconTypes & TouchIcon)
495         haveTouchIcon = fillIconURL(TouchIcon, &iconURLs);
496
497     // Only return the default touch icons when the both were required and neither was gotten.
498     if (iconTypes & TouchPrecomposedIcon && iconTypes & TouchIcon && !havePrecomposedIcon && !haveTouchIcon) {
499         iconURLs.append(getDefaultIconURL(TouchPrecomposedIcon));
500         iconURLs.append(getDefaultIconURL(TouchIcon));
501     }
502 #endif
503     return iconURLs;
504 }
505
506 bool FrameLoader::fillIconURL(IconType iconType, IconURLs* iconURLs)
507 {
508     // If we have an iconURL from a Link element, return that
509     IconURL url = m_frame->document()->iconURL(iconType);
510     if (url.m_iconURL.isEmpty())
511         return false;
512
513     iconURLs->append(url);
514
515     return true;
516 }
517
518 IconURL FrameLoader::getDefaultIconURL(IconType iconType)
519 {
520     // Don't return a favicon iconURL unless we're http or https
521     KURL documentURL = m_frame->document()->url();
522     if (!documentURL.protocolInHTTPFamily())
523         return IconURL();
524
525     KURL url;
526     bool couldSetProtocol = url.setProtocol(documentURL.protocol());
527     ASSERT_UNUSED(couldSetProtocol, couldSetProtocol);
528     url.setHost(documentURL.host());
529     if (documentURL.hasPort())
530         url.setPort(documentURL.port());
531     if (iconType == Favicon) {
532         url.setPath("/favicon.ico");
533         return IconURL(KURL(ParsedURLString, url), Favicon);
534     }
535 #if ENABLE(TOUCH_ICON_LOADING)
536     if (iconType == TouchPrecomposedIcon) {
537         url.setPath("/apple-touch-icon-precomposed.png");
538         return IconURL(KURL(ParsedURLString, url), TouchPrecomposedIcon);
539     }
540     if (iconType == TouchIcon) {
541         url.setPath("/apple-touch-icon.png");
542         return IconURL(KURL(ParsedURLString, url), TouchIcon);
543     }
544 #endif
545     return IconURL();
546 }
547
548 bool FrameLoader::didOpenURL(const KURL& url)
549 {
550     if (m_frame->navigationScheduler()->redirectScheduledDuringLoad()) {
551         // A redirect was scheduled before the document was created.
552         // This can happen when one frame changes another frame's location.
553         return false;
554     }
555
556     m_frame->navigationScheduler()->cancel();
557     m_frame->editor()->clearLastEditCommand();
558
559     m_isComplete = false;
560     m_isLoadingMainResource = true;
561     m_didCallImplicitClose = false;
562
563     // If we are still in the process of initializing an empty document then
564     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
565     // since it may cause clients to attempt to render the frame.
566     if (!m_stateMachine.creatingInitialEmptyDocument()) {
567         if (DOMWindow* window = m_frame->existingDOMWindow()) {
568             window->setStatus(String());
569             window->setDefaultStatus(String());
570         }
571     }
572     m_workingURL = url;
573     if (m_workingURL.protocolInHTTPFamily() && !m_workingURL.host().isEmpty() && m_workingURL.path().isEmpty())
574         m_workingURL.setPath("/");
575
576     started();
577
578     return true;
579 }
580
581 void FrameLoader::didExplicitOpen()
582 {
583     m_isComplete = false;
584     m_didCallImplicitClose = false;
585
586     // Calling document.open counts as committing the first real document load.
587     if (!m_stateMachine.committedFirstRealDocumentLoad())
588         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
589     
590     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
591     // from a subsequent window.document.open / window.document.write call. 
592     // Canceling redirection here works for all cases because document.open 
593     // implicitly precedes document.write.
594     m_frame->navigationScheduler()->cancel();
595 }
596
597
598 void FrameLoader::cancelAndClear()
599 {
600     m_frame->navigationScheduler()->cancel();
601
602     if (!m_isComplete)
603         closeURL();
604
605     clear(false);
606     m_frame->script()->updatePlatformScriptObjects();
607 }
608
609 void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
610 {
611     m_frame->editor()->clear();
612
613     if (!m_needsClear)
614         return;
615     m_needsClear = false;
616     
617     if (!m_frame->document()->inPageCache()) {
618         m_frame->document()->cancelParsing();
619         m_frame->document()->stopActiveDOMObjects();
620         if (m_frame->document()->attached()) {
621             m_frame->document()->willRemove();
622             m_frame->document()->detach();
623             
624             m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document());
625         }
626     }
627
628     // Do this after detaching the document so that the unload event works.
629     if (clearWindowProperties) {
630         m_frame->clearDOMWindow();
631         m_frame->script()->clearWindowShell(m_frame->document()->inPageCache());
632     }
633
634     m_frame->selection()->clear();
635     m_frame->eventHandler()->clear();
636     if (clearFrameView && m_frame->view())
637         m_frame->view()->clear();
638
639     // Do not drop the document before the ScriptController and view are cleared
640     // as some destructors might still try to access the document.
641     m_frame->setDocument(0);
642
643     m_subframeLoader.clear();
644
645     if (clearScriptObjects)
646         m_frame->script()->clearScriptObjects();
647
648     m_frame->navigationScheduler()->clear();
649
650     m_checkTimer.stop();
651     m_shouldCallCheckCompleted = false;
652     m_shouldCallCheckLoadComplete = false;
653
654     if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
655         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
656 }
657
658 void FrameLoader::receivedFirstData()
659 {
660     activeDocumentLoader()->writer()->begin(m_workingURL, false);
661     activeDocumentLoader()->writer()->setDocumentWasLoadedAsPartOfNavigation();
662
663     dispatchDidCommitLoad();
664     dispatchDidClearWindowObjectsInAllWorlds();
665     
666     if (m_documentLoader) {
667         StringWithDirection ptitle = m_documentLoader->title();
668         // If we have a title let the WebView know about it.
669         if (!ptitle.isNull())
670             m_client->dispatchDidReceiveTitle(ptitle);
671     }
672
673     m_workingURL = KURL();
674
675     double delay;
676     String url;
677     if (!m_documentLoader)
678         return;
679     if (m_frame->document()->isViewSource())
680         return;
681     if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url))
682         return;
683
684     if (url.isEmpty())
685         url = m_frame->document()->url().string();
686     else
687         url = m_frame->document()->completeURL(url).string();
688
689     m_frame->navigationScheduler()->scheduleRedirect(delay, url);
690 }
691
692 void FrameLoader::setOutgoingReferrer(const KURL& url)
693 {
694     m_outgoingReferrer = url.strippedForUseAsReferrer();
695 }
696
697 void FrameLoader::didBeginDocument(bool dispatch)
698 {
699     m_needsClear = true;
700     m_isComplete = false;
701     m_didCallImplicitClose = false;
702     m_isLoadingMainResource = true;
703     m_frame->document()->setReadyState(Document::Loading);
704
705     if (m_pendingStateObject) {
706         m_frame->document()->statePopped(m_pendingStateObject.get());
707         m_pendingStateObject.clear();
708     }
709
710     if (dispatch)
711         dispatchDidClearWindowObjectsInAllWorlds();
712
713     updateFirstPartyForCookies();
714
715     Settings* settings = m_frame->document()->settings();
716     m_frame->document()->cachedResourceLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically());
717
718     if (m_documentLoader) {
719         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
720         if (!dnsPrefetchControl.isEmpty())
721             m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
722
723         String contentSecurityPolicy = m_documentLoader->response().httpHeaderField("X-WebKit-CSP");
724         if (!contentSecurityPolicy.isEmpty())
725             m_frame->document()->contentSecurityPolicy()->didReceiveHeader(contentSecurityPolicy, ContentSecurityPolicy::EnforcePolicy);
726
727         String reportOnlyContentSecurityPolicy = m_documentLoader->response().httpHeaderField("X-WebKit-CSP-Report-Only");
728         if (!contentSecurityPolicy.isEmpty())
729             m_frame->document()->contentSecurityPolicy()->didReceiveHeader(reportOnlyContentSecurityPolicy, ContentSecurityPolicy::ReportOnly);
730     }
731
732     history()->restoreDocumentState();
733 }
734
735 void FrameLoader::didEndDocument()
736 {
737     m_isLoadingMainResource = false;
738 }
739
740 // Callback for the old-style synchronous IconDatabase interface.
741 void FrameLoader::iconLoadDecisionReceived(IconLoadDecision iconLoadDecision)
742 {
743     if (!m_mayLoadIconLater)
744         return;
745     LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this);
746     continueIconLoadWithDecision(iconLoadDecision);
747     m_mayLoadIconLater = false;
748 }
749
750 void FrameLoader::startIconLoader()
751 {
752     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
753     // But we should instead do it when we're done parsing the head element.
754     if (!isLoadingMainFrame())
755         return;
756
757     if (!iconDatabase().isEnabled())
758         return;
759     
760     KURL url(iconURL());
761     String urlString(url.string());
762     if (urlString.isEmpty())
763         return;
764
765     // People who want to avoid loading images generally want to avoid loading all images, unless an exception has been made for site icons.
766     // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically.
767     Settings* settings = m_frame->settings();
768     if (settings && !settings->loadsImagesAutomatically() && !settings->loadsSiteIconsIgnoringImageLoadingSetting())
769         return;
770
771     // If we're reloading the page, always start the icon load now.
772     if (loadType() == FrameLoadTypeReload && loadType() == FrameLoadTypeReloadFromOrigin) {
773         continueIconLoadWithDecision(IconLoadYes);
774         return;
775     }
776
777     if (iconDatabase().supportsAsynchronousMode()) {
778         m_documentLoader->getIconLoadDecisionForIconURL(urlString);
779         // Commit the icon url mapping to the database just in case we don't end up loading later.
780         commitIconURLToIconDatabase(url);
781         return;
782     }
783     
784     IconLoadDecision decision = iconDatabase().synchronousLoadDecisionForIconURL(urlString, m_documentLoader.get());
785
786     if (decision == IconLoadUnknown) {
787         // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database
788         // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal
789         // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the 
790         // icon is later read in from disk
791         LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data());
792         m_mayLoadIconLater = true;    
793         m_client->registerForIconNotification();
794         commitIconURLToIconDatabase(url);
795         return;
796     }
797
798     continueIconLoadWithDecision(decision);
799 }
800
801 void FrameLoader::continueIconLoadWithDecision(IconLoadDecision iconLoadDecision)
802 {
803     ASSERT(iconLoadDecision != IconLoadUnknown);
804     
805     //  FIXME (<rdar://problem/9168605>) - We should support in-memory-only private browsing icons in asynchronous icon database mode.
806     if (iconDatabase().supportsAsynchronousMode() && m_frame->page()->settings()->privateBrowsingEnabled())
807         return;
808         
809     if (iconLoadDecision == IconLoadNo) {
810         KURL url(iconURL());
811         String urlString(url.string());
812         
813         LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
814         commitIconURLToIconDatabase(url);
815         
816         if (iconDatabase().supportsAsynchronousMode()) {
817             m_documentLoader->getIconDataForIconURL(urlString);
818             return;
819         }
820         
821         // We were told not to load this icon - that means this icon is already known by the database
822         // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone
823         // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method.
824         // Otherwise if the icon data *is* available, notify the delegate
825         if (!iconDatabase().synchronousIconDataKnownForIconURL(urlString)) {
826             LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data());
827             m_client->registerForIconNotification();
828             iconDatabase().synchronousIconForPageURL(m_frame->document()->url().string(), IntSize(0, 0));
829             iconDatabase().synchronousIconForPageURL(originalRequestURL().string(), IntSize(0, 0));
830         } else
831             m_client->dispatchDidReceiveIcon();
832             
833         return;
834     } 
835     
836     if (!m_iconLoader)
837         m_iconLoader = IconLoader::create(m_frame);
838         
839     m_iconLoader->startLoading();
840 }
841
842 void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
843 {
844     LOG(IconDatabase, "Committing iconURL %s to database for pageURLs %s and %s", icon.string().ascii().data(), m_frame->document()->url().string().ascii().data(), originalRequestURL().string().ascii().data());
845     iconDatabase().setIconURLForPageURL(icon.string(), m_frame->document()->url().string());
846     iconDatabase().setIconURLForPageURL(icon.string(), originalRequestURL().string());
847 }
848
849 void FrameLoader::finishedParsing()
850 {
851     m_frame->injectUserScripts(InjectAtDocumentEnd);
852
853     if (m_stateMachine.creatingInitialEmptyDocument())
854         return;
855
856     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
857     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
858     // Null-checking the FrameView indicates whether or not we're in the destructor.
859     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
860
861     m_client->dispatchDidFinishDocumentLoad();
862
863     checkCompleted();
864
865     if (!m_frame->view())
866         return; // We are being destroyed by something checkCompleted called.
867
868     // Check if the scrollbars are really needed for the content.
869     // If not, remove them, relayout, and repaint.
870     m_frame->view()->restoreScrollbar();
871     m_frame->view()->scrollToFragment(m_frame->document()->url());
872 }
873
874 void FrameLoader::loadDone()
875 {
876     checkCompleted();
877 }
878
879 bool FrameLoader::allChildrenAreComplete() const
880 {
881     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
882         if (!child->loader()->m_isComplete)
883             return false;
884     }
885     return true;
886 }
887
888 bool FrameLoader::allAncestorsAreComplete() const
889 {
890     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
891         if (!ancestor->loader()->m_isComplete)
892             return false;
893     }
894     return true;
895 }
896
897 void FrameLoader::checkCompleted()
898 {
899     m_shouldCallCheckCompleted = false;
900
901     if (m_frame->view())
902         m_frame->view()->checkStopDelayingDeferredRepaints();
903
904     // Have we completed before?
905     if (m_isComplete)
906         return;
907
908     // Are we still parsing?
909     if (m_frame->document()->parsing())
910         return;
911
912     // Still waiting for images/scripts?
913     if (numRequests(m_frame->document()))
914         return;
915
916     // Still waiting for elements that don't go through a FrameLoader?
917     if (m_frame->document()->isDelayingLoadEvent())
918         return;
919
920     // Any frame that hasn't completed yet?
921     if (!allChildrenAreComplete())
922         return;
923
924     // OK, completed.
925     m_isComplete = true;
926     m_frame->document()->setReadyState(Document::Complete);
927
928     RefPtr<Frame> protect(m_frame);
929     checkCallImplicitClose(); // if we didn't do it before
930
931     m_frame->navigationScheduler()->startTimer();
932
933     completed();
934     if (m_frame->page())
935         checkLoadComplete();
936 }
937
938 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
939 {
940     if (Page* page = m_frame->page()) {
941         if (page->defersLoading())
942             return;
943     }
944     if (m_shouldCallCheckCompleted)
945         checkCompleted();
946     if (m_shouldCallCheckLoadComplete)
947         checkLoadComplete();
948 }
949
950 void FrameLoader::startCheckCompleteTimer()
951 {
952     if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
953         return;
954     if (m_checkTimer.isActive())
955         return;
956     m_checkTimer.startOneShot(0);
957 }
958
959 void FrameLoader::scheduleCheckCompleted()
960 {
961     m_shouldCallCheckCompleted = true;
962     startCheckCompleteTimer();
963 }
964
965 void FrameLoader::scheduleCheckLoadComplete()
966 {
967     m_shouldCallCheckLoadComplete = true;
968     startCheckCompleteTimer();
969 }
970
971 void FrameLoader::checkCallImplicitClose()
972 {
973     if (m_didCallImplicitClose || m_frame->document()->parsing() || m_frame->document()->isDelayingLoadEvent())
974         return;
975
976     if (!allChildrenAreComplete())
977         return; // still got a frame running -> too early
978
979     m_didCallImplicitClose = true;
980     m_wasUnloadEventEmitted = false;
981     m_frame->document()->implicitClose();
982 }
983
984 KURL FrameLoader::baseURL() const
985 {
986     ASSERT(m_frame->document());
987     return m_frame->document()->baseURL();
988 }
989
990 KURL FrameLoader::completeURL(const String& url)
991 {
992     ASSERT(m_frame->document());
993     return m_frame->document()->completeURL(url);
994 }
995
996 void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
997 {
998     ASSERT(childFrame);
999
1000 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1001     RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->uniqueName(), url);    
1002     if (subframeArchive) {
1003         childFrame->loader()->loadArchive(subframeArchive.release());
1004         return;
1005     }
1006 #endif // ENABLE(WEB_ARCHIVE)
1007
1008     HistoryItem* parentItem = history()->currentItem();
1009     // If we're moving in the back/forward list, we might want to replace the content
1010     // of this child frame with whatever was there at that point.
1011     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType())) {
1012         HistoryItem* childItem = parentItem->childItemWithTarget(childFrame->tree()->uniqueName());
1013         if (childItem) {
1014             childFrame->loader()->loadDifferentDocumentItem(childItem, loadType());
1015             return;
1016         }
1017     }
1018
1019     childFrame->loader()->loadURL(url, referer, String(), false, FrameLoadTypeRedirectWithLockedBackForwardList, 0, 0);
1020 }
1021
1022 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1023 void FrameLoader::loadArchive(PassRefPtr<Archive> archive)
1024 {
1025     m_archive = archive;
1026     
1027     ArchiveResource* mainResource = m_archive->mainResource();
1028     ASSERT(mainResource);
1029     if (!mainResource)
1030         return;
1031         
1032     SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
1033     
1034     ResourceRequest request(mainResource->url());
1035 #if PLATFORM(MAC)
1036     request.applyWebArchiveHackForMail();
1037 #endif
1038
1039     RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
1040     documentLoader->addAllArchiveResources(m_archive.get());
1041     load(documentLoader.get());
1042 }
1043 #endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1044
1045 ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
1046 {
1047     String mimeType = mimeTypeIn;
1048     String extension = url.path().substring(url.path().reverseFind('.') + 1);
1049
1050     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure
1051     if (mimeType.isEmpty())
1052         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1053
1054 #if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL
1055     if (mimeType.isEmpty())
1056         mimeType = PluginDatabase::installedPlugins()->MIMETypeForExtension(extension);
1057 #endif
1058
1059     if (mimeType.isEmpty())
1060         return ObjectContentFrame; // Go ahead and hope that we can display the content.
1061
1062 #if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL
1063     bool plugInSupportsMIMEType = PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType);
1064 #else
1065     bool plugInSupportsMIMEType = false;
1066 #endif
1067
1068     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1069         return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? WebCore::ObjectContentNetscapePlugin : WebCore::ObjectContentImage;
1070
1071     if (plugInSupportsMIMEType)
1072         return WebCore::ObjectContentNetscapePlugin;
1073
1074     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1075         return WebCore::ObjectContentFrame;
1076
1077     return WebCore::ObjectContentNone;
1078 }
1079
1080 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1081 void FrameLoader::hideMediaPlayerProxyPlugin(Widget* widget)
1082 {
1083     m_client->hideMediaPlayerProxyPlugin(widget);
1084 }
1085
1086 void FrameLoader::showMediaPlayerProxyPlugin(Widget* widget)
1087 {
1088     m_client->showMediaPlayerProxyPlugin(widget);
1089 }
1090 #endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1091
1092 String FrameLoader::outgoingReferrer() const
1093 {
1094     return m_outgoingReferrer;
1095 }
1096
1097 String FrameLoader::outgoingOrigin() const
1098 {
1099     return m_frame->document()->securityOrigin()->toString();
1100 }
1101
1102 bool FrameLoader::isMixedContent(SecurityOrigin* context, const KURL& url)
1103 {
1104     if (context->protocol() != "https")
1105         return false;  // We only care about HTTPS security origins.
1106
1107     if (!url.isValid() || SchemeRegistry::shouldTreatURLSchemeAsSecure(url.protocol()))
1108         return false;  // Loading these protocols is secure.
1109
1110     return true;
1111 }
1112
1113 bool FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL& url)
1114 {
1115     if (!isMixedContent(context, url))
1116         return true;
1117
1118     Settings* settings = m_frame->settings();
1119     bool allowed = m_client->allowDisplayingInsecureContent(settings && settings->allowDisplayOfInsecureContent(), context, url);
1120     String message = (allowed ? emptyString() : "[blocked] ") + "The page at " +
1121         m_frame->document()->url().string() + " displayed insecure content from " + url.string() + ".\n";
1122         
1123     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
1124
1125     if (allowed)
1126         m_client->didDisplayInsecureContent();
1127
1128     return allowed;
1129 }
1130
1131 bool FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& url)
1132 {
1133     if (!isMixedContent(context, url))
1134         return true;
1135
1136     Settings* settings = m_frame->settings();
1137     bool allowed = m_client->allowRunningInsecureContent(settings && settings->allowRunningOfInsecureContent(), context, url);
1138     String message = (allowed ? emptyString() : "[blocked] ") + "The page at " +
1139         m_frame->document()->url().string() + " ran insecure content from " + url.string() + ".\n";
1140        
1141     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
1142
1143     if (allowed)
1144         m_client->didRunInsecureContent(context, url);
1145
1146     return allowed;
1147 }
1148
1149 Frame* FrameLoader::opener()
1150 {
1151     return m_opener;
1152 }
1153
1154 void FrameLoader::setOpener(Frame* opener)
1155 {
1156     if (m_opener)
1157         m_opener->loader()->m_openedFrames.remove(m_frame);
1158     if (opener)
1159         opener->loader()->m_openedFrames.add(m_frame);
1160     m_opener = opener;
1161
1162     if (m_frame->document()) {
1163         m_frame->document()->initSecurityContext();
1164         m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
1165     }
1166 }
1167
1168 // FIXME: This does not belong in FrameLoader!
1169 void FrameLoader::handleFallbackContent()
1170 {
1171     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
1172     if (!owner || !owner->hasTagName(objectTag))
1173         return;
1174     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
1175 }
1176
1177 void FrameLoader::provisionalLoadStarted()
1178 {
1179     if (m_stateMachine.firstLayoutDone())
1180         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
1181     m_frame->navigationScheduler()->cancel(true);
1182     m_client->provisionalLoadStarted();
1183 }
1184
1185 bool FrameLoader::isProcessingUserGesture()
1186 {
1187     Frame* frame = m_frame->tree()->top();
1188     if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
1189         return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
1190     return ScriptController::processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.
1191 }
1192
1193 void FrameLoader::resetMultipleFormSubmissionProtection()
1194 {
1195     m_submittedFormURL = KURL();
1196 }
1197
1198 void FrameLoader::willSetEncoding()
1199 {
1200     if (!m_workingURL.isEmpty())
1201         receivedFirstData();
1202 }
1203
1204 void FrameLoader::updateFirstPartyForCookies()
1205 {
1206     if (m_frame->tree()->parent())
1207         setFirstPartyForCookies(m_frame->tree()->parent()->document()->firstPartyForCookies());
1208     else
1209         setFirstPartyForCookies(m_frame->document()->url());
1210 }
1211
1212 void FrameLoader::setFirstPartyForCookies(const KURL& url)
1213 {
1214     m_frame->document()->setFirstPartyForCookies(url);
1215     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1216         child->loader()->setFirstPartyForCookies(url);
1217 }
1218
1219 // This does the same kind of work that didOpenURL does, except it relies on the fact
1220 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
1221 void FrameLoader::loadInSameDocument(const KURL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
1222 {
1223     // If we have a state object, we cannot also be a new navigation.
1224     ASSERT(!stateObject || (stateObject && !isNewNavigation));
1225
1226     // Update the data source's request with the new URL to fake the URL change
1227     KURL oldURL = m_frame->document()->url();
1228     m_frame->document()->setURL(url);
1229     documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1230     if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1231         // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add 
1232         // based on the current request. Must also happen before we openURL and displace the 
1233         // scroll position, since adding the BF item will save away scroll state.
1234         
1235         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
1236         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1237         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
1238         // though its load is not yet done.  I think this all works out OK, for one because
1239         // we have already saved away the scroll and doc state for the long slow load,
1240         // but it's not an obvious case.
1241
1242         history()->updateBackForwardListForFragmentScroll();
1243     }
1244     
1245     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
1246     
1247     history()->updateForSameDocumentNavigation();
1248
1249     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
1250     if (hashChange)
1251         m_frame->eventHandler()->stopAutoscrollTimer();
1252     
1253     // It's important to model this as a load that starts and immediately finishes.
1254     // Otherwise, the parent frame may think we never finished loading.
1255     started();
1256
1257     // We need to scroll to the fragment whether or not a hash change occurred, since
1258     // the user might have scrolled since the previous navigation.
1259     if (FrameView* view = m_frame->view())
1260         view->scrollToFragment(url);
1261     
1262     m_isComplete = false;
1263     checkCompleted();
1264
1265     if (isNewNavigation) {
1266         // This will clear previousItem from the rest of the frame tree that didn't
1267         // doing any loading. We need to make a pass on this now, since for anchor nav
1268         // we'll not go through a real load and reach Completed state.
1269         checkLoadComplete();
1270     }
1271
1272     m_client->dispatchDidNavigateWithinPage();
1273
1274     m_frame->document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
1275     m_client->dispatchDidPopStateWithinPage();
1276     
1277     if (hashChange) {
1278         m_frame->document()->enqueueHashchangeEvent(oldURL, url);
1279         m_client->dispatchDidChangeLocationWithinPage();
1280     }
1281     
1282     // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
1283     m_client->didFinishLoad();
1284 }
1285
1286 bool FrameLoader::isComplete() const
1287 {
1288     return m_isComplete;
1289 }
1290
1291 void FrameLoader::completed()
1292 {
1293     RefPtr<Frame> protect(m_frame);
1294
1295     for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame))
1296         descendant->navigationScheduler()->startTimer();
1297
1298     if (Frame* parent = m_frame->tree()->parent())
1299         parent->loader()->checkCompleted();
1300
1301     if (m_frame->view())
1302         m_frame->view()->maintainScrollPositionAtAnchor(0);
1303 }
1304
1305 void FrameLoader::started()
1306 {
1307     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
1308         frame->loader()->m_isComplete = false;
1309 }
1310
1311 void FrameLoader::prepareForLoadStart()
1312 {
1313     if (Page* page = m_frame->page())
1314         page->progress()->progressStarted(m_frame);
1315     m_client->dispatchDidStartProvisionalLoad();
1316 }
1317
1318 void FrameLoader::setupForReplace()
1319 {
1320     setState(FrameStateProvisional);
1321     m_provisionalDocumentLoader = m_documentLoader;
1322     m_documentLoader = 0;
1323     detachChildren();
1324 }
1325
1326 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
1327 {
1328     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
1329 }
1330
1331 // This is a hack to allow keep navigation to http/https feeds working. To remove this
1332 // we need to introduce new API akin to registerURLSchemeAsLocal, that registers a
1333 // protocols navigation policy.
1334 static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url)
1335 {
1336     const String& urlString = url.string();
1337     if (!urlString.startsWith("feed", false))
1338         return false;
1339
1340     return urlString.startsWith("feed://", false) 
1341         || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false)
1342         || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false)
1343         || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false);
1344 }
1345
1346 void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList,
1347     PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy)
1348 {    
1349     KURL url = request.resourceRequest().url();
1350
1351     ASSERT(m_frame->document());
1352     // FIXME: Should we move the isFeedWithNestedProtocolInHTTPFamily logic inside SecurityOrigin::canDisplay?
1353     if (!isFeedWithNestedProtocolInHTTPFamily(url) && !request.requester()->canDisplay(url)) {
1354         reportLocalLoadFailed(m_frame, url.string());
1355         return;
1356     }
1357
1358     String referrer;
1359     String argsReferrer = request.resourceRequest().httpReferrer();
1360     if (!argsReferrer.isEmpty())
1361         referrer = argsReferrer;
1362     else
1363         referrer = m_outgoingReferrer;
1364
1365     if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer)
1366         referrer = String();
1367     
1368     FrameLoadType loadType;
1369     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
1370         loadType = FrameLoadTypeReload;
1371     else if (lockBackForwardList)
1372         loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
1373     else
1374         loadType = FrameLoadTypeStandard;
1375
1376     if (request.resourceRequest().httpMethod() == "POST")
1377         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
1378     else
1379         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
1380
1381     // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1382     // load if frame names have changed.
1383     Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame;
1384     Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.frameName());
1385     if (targetFrame && targetFrame != sourceFrame) {
1386         if (Page* page = targetFrame->page())
1387             page->chrome()->focus();
1388     }
1389 }
1390
1391 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
1392     PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
1393 {
1394     if (m_inStopAllLoaders)
1395         return;
1396
1397     RefPtr<FormState> formState = prpFormState;
1398     bool isFormSubmission = formState;
1399     
1400     ResourceRequest request(newURL);
1401     if (!referrer.isEmpty()) {
1402         request.setHTTPReferrer(referrer);
1403         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
1404         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
1405     }
1406     addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
1407     if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
1408         request.setCachePolicy(ReloadIgnoringCacheData);
1409
1410     ASSERT(newLoadType != FrameLoadTypeSame);
1411
1412     // The search for a target frame is done earlier in the case of form submission.
1413     Frame* targetFrame = isFormSubmission ? 0 : findFrameForNavigation(frameName);
1414     if (targetFrame && targetFrame != m_frame) {
1415         targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState.release());
1416         return;
1417     }
1418
1419     if (m_pageDismissalEventBeingDispatched)
1420         return;
1421
1422     NavigationAction action(newURL, newLoadType, isFormSubmission, event);
1423
1424     if (!targetFrame && !frameName.isEmpty()) {
1425         policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy,
1426             request, formState.release(), frameName, this);
1427         return;
1428     }
1429
1430     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1431
1432     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
1433     const String& httpMethod = request.httpMethod();
1434     
1435     // Make sure to do scroll to anchor processing even if the URL is
1436     // exactly the same so pages with '#' links and DHTML side effects
1437     // work properly.
1438     if (shouldScrollToAnchor(isFormSubmission, httpMethod, newLoadType, newURL)) {
1439         oldDocumentLoader->setTriggeringAction(action);
1440         policyChecker()->stopCheck();
1441         policyChecker()->setLoadType(newLoadType);
1442         policyChecker()->checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
1443             callContinueFragmentScrollAfterNavigationPolicy, this);
1444     } else {
1445         // must grab this now, since this load may stop the previous load and clear this flag
1446         bool isRedirect = m_quickRedirectComing;
1447         loadWithNavigationAction(request, action, lockHistory, newLoadType, formState.release());
1448         if (isRedirect) {
1449             m_quickRedirectComing = false;
1450             if (m_provisionalDocumentLoader)
1451                 m_provisionalDocumentLoader->setIsClientRedirect(true);
1452         } else if (sameURL)
1453             // Example of this case are sites that reload the same URL with a different cookie
1454             // driving the generated content, or a master frame with links that drive a target
1455             // frame, where the user has clicked on the same link repeatedly.
1456             m_loadType = FrameLoadTypeSame;
1457     }
1458 }
1459
1460 void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
1461 {
1462     load(request, SubstituteData(), lockHistory);
1463 }
1464
1465 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
1466 {
1467     if (m_inStopAllLoaders)
1468         return;
1469         
1470     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
1471     m_loadType = FrameLoadTypeStandard;
1472     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
1473     if (lockHistory && m_documentLoader)
1474         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
1475     load(loader.get());
1476 }
1477
1478 void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
1479 {
1480     if (frameName.isEmpty()) {
1481         load(request, lockHistory);
1482         return;
1483     }
1484
1485     Frame* frame = findFrameForNavigation(frameName);
1486     if (frame) {
1487         frame->loader()->load(request, lockHistory);
1488         return;
1489     }
1490
1491     policyChecker()->checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), FrameLoader::callContinueLoadAfterNewWindowPolicy, request, 0, frameName, this);
1492 }
1493
1494 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
1495 {
1496     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
1497     if (lockHistory && m_documentLoader)
1498         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
1499
1500     loader->setTriggeringAction(action);
1501     if (m_documentLoader)
1502         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1503
1504     loadWithDocumentLoader(loader.get(), type, formState);
1505 }
1506
1507 void FrameLoader::load(DocumentLoader* newDocumentLoader)
1508 {
1509     ResourceRequest& r = newDocumentLoader->request();
1510     addExtraFieldsToMainResourceRequest(r);
1511     FrameLoadType type;
1512
1513     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1514         r.setCachePolicy(ReloadIgnoringCacheData);
1515         type = FrameLoadTypeSame;
1516     } else
1517         type = FrameLoadTypeStandard;
1518
1519     if (m_documentLoader)
1520         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1521     
1522     // When we loading alternate content for an unreachable URL that we're
1523     // visiting in the history list, we treat it as a reload so the history list 
1524     // is appropriately maintained.
1525     //
1526     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
1527     // shouldn't a more explicit type of reload be defined, that means roughly 
1528     // "load without affecting history" ? 
1529     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
1530         // shouldReloadToHandleUnreachableURL() returns true only when the original load type is back-forward.
1531         // In this case we should save the document state now. Otherwise the state can be lost because load type is
1532         // changed and updateForBackForwardNavigation() will not be called when loading is committed.
1533         history()->saveDocumentAndScrollState();
1534
1535         ASSERT(type == FrameLoadTypeStandard);
1536         type = FrameLoadTypeReload;
1537     }
1538
1539     loadWithDocumentLoader(newDocumentLoader, type, 0);
1540 }
1541
1542 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
1543 {
1544     // Retain because dispatchBeforeLoadEvent may release the last reference to it.
1545     RefPtr<Frame> protect(m_frame);
1546
1547     ASSERT(m_client->hasWebView());
1548
1549     // Unfortunately the view must be non-nil, this is ultimately due
1550     // to parser requiring a FrameView.  We should fix this dependency.
1551
1552     ASSERT(m_frame->view());
1553
1554     if (m_pageDismissalEventBeingDispatched)
1555         return;
1556
1557     if (m_frame->document())
1558         m_previousUrl = m_frame->document()->url();
1559
1560     policyChecker()->setLoadType(type);
1561     RefPtr<FormState> formState = prpFormState;
1562     bool isFormSubmission = formState;
1563
1564     const KURL& newURL = loader->request().url();
1565     const String& httpMethod = loader->request().httpMethod();
1566
1567     if (shouldScrollToAnchor(isFormSubmission,  httpMethod, policyChecker()->loadType(), newURL)) {
1568         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1569         NavigationAction action(newURL, policyChecker()->loadType(), isFormSubmission);
1570
1571         oldDocumentLoader->setTriggeringAction(action);
1572         policyChecker()->stopCheck();
1573         policyChecker()->checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
1574             callContinueFragmentScrollAfterNavigationPolicy, this);
1575     } else {
1576         if (Frame* parent = m_frame->tree()->parent())
1577             loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
1578
1579         policyChecker()->stopCheck();
1580         setPolicyDocumentLoader(loader);
1581         if (loader->triggeringAction().isEmpty())
1582             loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission));
1583
1584         if (Element* ownerElement = m_frame->ownerElement()) {
1585             if (!ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
1586                 continueLoadAfterNavigationPolicy(loader->request(), formState, false);
1587                 return;
1588             }
1589         }
1590
1591         policyChecker()->checkNavigationPolicy(loader->request(), loader, formState,
1592             callContinueLoadAfterNavigationPolicy, this);
1593     }
1594 }
1595
1596 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
1597 {
1598     ASSERT(!url.isEmpty());
1599     if (!frame)
1600         return;
1601
1602     frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
1603 }
1604
1605 const ResourceRequest& FrameLoader::initialRequest() const
1606 {
1607     return activeDocumentLoader()->originalRequest();
1608 }
1609
1610 bool FrameLoader::willLoadMediaElementURL(KURL& url)
1611 {
1612     ResourceRequest request(url);
1613
1614     unsigned long identifier;
1615     ResourceError error;
1616     requestFromDelegate(request, identifier, error);
1617     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, -1, error);
1618
1619     url = request.url();
1620
1621     return error.isNull();
1622 }
1623
1624 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
1625 {
1626     KURL unreachableURL = docLoader->unreachableURL();
1627
1628     if (unreachableURL.isEmpty())
1629         return false;
1630
1631     if (!isBackForwardLoadType(policyChecker()->loadType()))
1632         return false;
1633
1634     // We only treat unreachableURLs specially during the delegate callbacks
1635     // for provisional load errors and navigation policy decisions. The former
1636     // case handles well-formed URLs that can't be loaded, and the latter
1637     // case handles malformed URLs and unknown schemes. Loading alternate content
1638     // at other times behaves like a standard load.
1639     DocumentLoader* compareDocumentLoader = 0;
1640     if (policyChecker()->delegateIsDecidingNavigationPolicy() || policyChecker()->delegateIsHandlingUnimplementablePolicy())
1641         compareDocumentLoader = m_policyDocumentLoader.get();
1642     else if (m_delegateIsHandlingProvisionalLoadError)
1643         compareDocumentLoader = m_provisionalDocumentLoader.get();
1644
1645     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
1646 }
1647
1648 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
1649 {
1650     if (!m_documentLoader)
1651         return;
1652
1653     ResourceRequest request = m_documentLoader->request();
1654     KURL unreachableURL = m_documentLoader->unreachableURL();
1655     if (!unreachableURL.isEmpty())
1656         request.setURL(unreachableURL);
1657
1658     request.setCachePolicy(ReturnCacheDataElseLoad);
1659
1660     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
1661     setPolicyDocumentLoader(loader.get());
1662
1663     loader->setOverrideEncoding(encoding);
1664
1665     loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
1666 }
1667
1668 void FrameLoader::reload(bool endToEndReload)
1669 {
1670     if (!m_documentLoader)
1671         return;
1672
1673     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1674     // Reloading in this case will lose the current contents (see 4151001).
1675     if (m_documentLoader->request().url().isEmpty())
1676         return;
1677
1678     ResourceRequest initialRequest = m_documentLoader->request();
1679
1680     // Replace error-page URL with the URL we were trying to reach.
1681     KURL unreachableURL = m_documentLoader->unreachableURL();
1682     if (!unreachableURL.isEmpty())
1683         initialRequest.setURL(unreachableURL);
1684     
1685     // Create a new document loader for the reload, this will become m_documentLoader eventually,
1686     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
1687     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
1688
1689     ResourceRequest& request = loader->request();
1690
1691     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
1692     request.setCachePolicy(ReloadIgnoringCacheData);
1693
1694     // If we're about to re-post, set up action so the application can warn the user.
1695     if (request.httpMethod() == "POST")
1696         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
1697
1698     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1699     
1700     loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
1701 }
1702
1703 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
1704 {
1705     // targetFrame can be NULL when we're trying to navigate a top-level frame
1706     // that has a NULL opener.
1707     if (!targetFrame)
1708         return false;
1709
1710     const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
1711     for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
1712         Document* ancestorDocument = ancestorFrame->document();
1713         if (!ancestorDocument)
1714             return true;
1715
1716         const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
1717         if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
1718             return true;
1719         
1720         // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
1721         if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
1722             return true;
1723     }
1724
1725     return false;
1726 }
1727
1728 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
1729 {
1730     // The navigation change is safe if the active frame is:
1731     //   - in the same security origin as the target or one of the target's
1732     //     ancestors.
1733     //
1734     // Or the target frame is:
1735     //   - a top-level frame in the frame hierarchy and the active frame can
1736     //     navigate the target frame's opener per above or it is the opener of
1737     //     the target frame.
1738
1739     if (!targetFrame)
1740         return true;
1741
1742     // Performance optimization.
1743     if (m_frame == targetFrame)
1744         return true;
1745
1746     // Let a frame navigate the top-level window that contains it.  This is
1747     // important to allow because it lets a site "frame-bust" (escape from a
1748     // frame created by another web site).
1749     if (!isDocumentSandboxed(m_frame, SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
1750         return true;
1751
1752     // A sandboxed frame can only navigate itself and its descendants.
1753     if (isDocumentSandboxed(m_frame, SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame))
1754         return false;
1755
1756     // Let a frame navigate its opener if the opener is a top-level window.
1757     if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
1758         return true;
1759
1760     Document* activeDocument = m_frame->document();
1761     ASSERT(activeDocument);
1762     const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
1763
1764     // For top-level windows, check the opener.
1765     if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
1766         return true;
1767
1768     // In general, check the frame's ancestors.
1769     if (canAccessAncestor(activeSecurityOrigin, targetFrame))
1770         return true;
1771
1772     Settings* settings = targetFrame->settings();
1773     if (settings && !settings->privateBrowsingEnabled()) {
1774         Document* targetDocument = targetFrame->document();
1775         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
1776         String message = "Unsafe JavaScript attempt to initiate a navigation change for frame with URL " +
1777                          targetDocument->url().string() + " from frame with URL " + activeDocument->url().string() + ".\n";
1778
1779         // FIXME: should we print to the console of the activeFrame as well?
1780         targetFrame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
1781     }
1782     
1783     return false;
1784 }
1785
1786 void FrameLoader::stopLoadingSubframes(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
1787 {
1788     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1789         child->loader()->stopAllLoaders(clearProvisionalItemPolicy);
1790 }
1791
1792 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
1793 {
1794     ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
1795     if (m_pageDismissalEventBeingDispatched)
1796         return;
1797
1798     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1799     if (m_inStopAllLoaders)
1800         return;
1801
1802     m_inStopAllLoaders = true;
1803
1804     policyChecker()->stopCheck();
1805
1806     // If no new load is in progress, we should clear the provisional item from history
1807     // before we call stopLoading.
1808     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
1809         history()->setProvisionalItem(0);
1810
1811     stopLoadingSubframes(clearProvisionalItemPolicy);
1812     if (m_provisionalDocumentLoader)
1813         m_provisionalDocumentLoader->stopLoading();
1814     if (m_documentLoader)
1815         m_documentLoader->stopLoading();
1816
1817     setProvisionalDocumentLoader(0);
1818     
1819 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1820     if (m_documentLoader)
1821         m_documentLoader->clearArchiveResources();
1822 #endif
1823
1824     m_checkTimer.stop();
1825
1826     m_inStopAllLoaders = false;    
1827 }
1828
1829 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
1830 {
1831     stopAllLoaders();
1832     
1833     if (deferCheckLoadComplete)
1834         scheduleCheckLoadComplete();
1835     else if (m_frame->page())
1836         checkLoadComplete();
1837 }
1838
1839 DocumentLoader* FrameLoader::activeDocumentLoader() const
1840 {
1841     if (m_state == FrameStateProvisional)
1842         return m_provisionalDocumentLoader.get();
1843     return m_documentLoader.get();
1844 }
1845
1846 bool FrameLoader::isLoading() const
1847 {
1848     DocumentLoader* docLoader = activeDocumentLoader();
1849     if (!docLoader)
1850         return false;
1851     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
1852 }
1853
1854 bool FrameLoader::frameHasLoaded() const
1855 {
1856     return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); 
1857 }
1858
1859 void FrameLoader::transferLoadingResourcesFromPage(Page* oldPage)
1860 {
1861     ASSERT(oldPage != m_frame->page());
1862     if (isLoading()) {
1863         activeDocumentLoader()->transferLoadingResourcesFromPage(oldPage);
1864         oldPage->progress()->progressCompleted(m_frame);
1865         if (m_frame->page())
1866             m_frame->page()->progress()->progressStarted(m_frame);
1867     }
1868 }
1869
1870 void FrameLoader::dispatchTransferLoadingResourceFromPage(unsigned long identifier, DocumentLoader* docLoader, const ResourceRequest& request, Page* oldPage)
1871 {
1872     notifier()->dispatchTransferLoadingResourceFromPage(identifier, docLoader, request, oldPage);
1873 }
1874
1875 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1876 {
1877     if (!loader && !m_documentLoader)
1878         return;
1879     
1880     ASSERT(loader != m_documentLoader);
1881     ASSERT(!loader || loader->frameLoader() == this);
1882
1883     m_client->prepareForDataSourceReplacement();
1884     detachChildren();
1885     if (m_documentLoader)
1886         m_documentLoader->detachFromFrame();
1887
1888     m_documentLoader = loader;
1889 }
1890
1891 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1892 {
1893     if (m_policyDocumentLoader == loader)
1894         return;
1895
1896     ASSERT(m_frame);
1897     if (loader)
1898         loader->setFrame(m_frame);
1899     if (m_policyDocumentLoader
1900             && m_policyDocumentLoader != m_provisionalDocumentLoader
1901             && m_policyDocumentLoader != m_documentLoader)
1902         m_policyDocumentLoader->detachFromFrame();
1903
1904     m_policyDocumentLoader = loader;
1905 }
1906
1907 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1908 {
1909     ASSERT(!loader || !m_provisionalDocumentLoader);
1910     ASSERT(!loader || loader->frameLoader() == this);
1911
1912     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1913         m_provisionalDocumentLoader->detachFromFrame();
1914
1915     m_provisionalDocumentLoader = loader;
1916 }
1917
1918 double FrameLoader::timeOfLastCompletedLoad()
1919 {
1920     return storedTimeOfLastCompletedLoad;
1921 }
1922
1923 void FrameLoader::setState(FrameState newState)
1924 {    
1925     m_state = newState;
1926     
1927     if (newState == FrameStateProvisional)
1928         provisionalLoadStarted();
1929     else if (newState == FrameStateComplete) {
1930         frameLoadCompleted();
1931         storedTimeOfLastCompletedLoad = currentTime();
1932         if (m_documentLoader)
1933             m_documentLoader->stopRecordingResponses();
1934     }
1935 }
1936
1937 void FrameLoader::clearProvisionalLoad()
1938 {
1939     setProvisionalDocumentLoader(0);
1940     if (Page* page = m_frame->page())
1941         page->progress()->progressCompleted(m_frame);
1942     setState(FrameStateComplete);
1943 }
1944
1945 void FrameLoader::markLoadComplete()
1946 {
1947     setState(FrameStateComplete);
1948 }
1949
1950 void FrameLoader::commitProvisionalLoad()
1951 {
1952     RefPtr<CachedPage> cachedPage = m_loadingFromCachedPage ? pageCache()->get(history()->provisionalItem()) : 0;
1953     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
1954
1955     LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame->tree()->uniqueName().string().utf8().data(),
1956         m_frame->document() ? m_frame->document()->url().string().utf8().data() : "", 
1957         pdl ? pdl->url().string().utf8().data() : "<no provisional DocumentLoader>");
1958
1959     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
1960     // We are doing this here because we know for sure that a new page is about to be loaded.
1961     HistoryItem* item = history()->currentItem();
1962     if (!m_frame->tree()->parent() && PageCache::canCache(m_frame->page()) && !item->isInPageCache())
1963         pageCache()->add(item, m_frame->page());
1964
1965     if (m_loadType != FrameLoadTypeReplace)
1966         closeOldDataSources();
1967
1968     if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
1969         m_client->makeRepresentation(pdl.get());
1970
1971     transitionToCommitted(cachedPage);
1972
1973     if (pdl) {
1974         // Check if the destination page is allowed to access the previous page's timing information.
1975         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url());
1976         m_documentLoader->timing()->hasSameOriginAsPreviousDocument = securityOrigin->canRequest(m_previousUrl);
1977     }
1978
1979     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
1980     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
1981     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
1982     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
1983     if (m_sentRedirectNotification)
1984         clientRedirectCancelledOrFinished(false);
1985     
1986     if (cachedPage && cachedPage->document()) {
1987         prepareForCachedPageRestore();
1988         cachedPage->restore(m_frame->page());
1989
1990         dispatchDidCommitLoad();
1991
1992         // If we have a title let the WebView know about it. 
1993         StringWithDirection title = m_documentLoader->title();
1994         if (!title.isNull())
1995             m_client->dispatchDidReceiveTitle(title);
1996
1997         checkCompleted();
1998     } else {        
1999         KURL url = pdl->substituteData().responseURL();
2000         if (url.isEmpty())
2001             url = pdl->url();
2002         if (url.isEmpty())
2003             url = pdl->responseURL();
2004         if (url.isEmpty())
2005             url = blankURL();
2006
2007         didOpenURL(url);
2008     }
2009
2010     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->uniqueName().string().utf8().data(),
2011         m_frame->document() ? m_frame->document()->url().string().utf8().data() : "");
2012
2013     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
2014         history()->updateForClientRedirect();
2015
2016     if (m_loadingFromCachedPage) {
2017         m_frame->document()->documentDidBecomeActive();
2018         
2019         // Force a layout to update view size and thereby update scrollbars.
2020         m_frame->view()->forceLayout();
2021
2022         const ResponseVector& responses = m_documentLoader->responses();
2023         size_t count = responses.size();
2024         for (size_t i = 0; i < count; i++) {
2025             const ResourceResponse& response = responses[i];
2026             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2027             ResourceError error;
2028             unsigned long identifier;
2029             ResourceRequest request(response.url());
2030             requestFromDelegate(request, identifier, error);
2031             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2032             // However, with today's computers and networking speeds, this won't happen in practice.
2033             // Could be an issue with a giant local file.
2034             notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), 0, error);
2035         }
2036         
2037         pageCache()->remove(history()->currentItem());
2038
2039         m_documentLoader->setPrimaryLoadComplete(true);
2040
2041         // FIXME: Why only this frame and not parent frames?
2042         checkLoadCompleteForThisFrame();
2043     }
2044 }
2045
2046 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
2047 {
2048     ASSERT(m_client->hasWebView());
2049     ASSERT(m_state == FrameStateProvisional);
2050
2051     if (m_state != FrameStateProvisional)
2052         return;
2053
2054     if (m_frame->view())
2055         m_frame->view()->scrollAnimator()->cancelAnimations();
2056
2057     m_client->setCopiesOnScroll();
2058     history()->updateForCommit();
2059
2060     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2061     // JavaScript. If the script initiates a new load, we need to abandon the current load,
2062     // or the two will stomp each other.
2063     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
2064     if (m_documentLoader)
2065         closeURL();
2066     if (pdl != m_provisionalDocumentLoader)
2067         return;
2068
2069     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
2070     if (m_documentLoader)
2071         m_documentLoader->stopLoadingSubresources();
2072     if (m_documentLoader)
2073         m_documentLoader->stopLoadingPlugIns();
2074
2075     setDocumentLoader(m_provisionalDocumentLoader.get());
2076     setProvisionalDocumentLoader(0);
2077     setState(FrameStateCommittedPage);
2078
2079 #if ENABLE(TOUCH_EVENTS)
2080     if (isLoadingMainFrame())
2081         m_frame->page()->chrome()->client()->needTouchEvents(false);
2082 #endif
2083
2084     // Handle adding the URL to the back/forward list.
2085     DocumentLoader* dl = m_documentLoader.get();
2086
2087     switch (m_loadType) {
2088         case FrameLoadTypeForward:
2089         case FrameLoadTypeBack:
2090         case FrameLoadTypeIndexedBackForward:
2091             if (m_frame->page()) {
2092                 // If the first load within a frame is a navigation within a back/forward list that was attached
2093                 // without any of the items being loaded then we need to update the history in a similar manner as
2094                 // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
2095                 if (!m_stateMachine.committedFirstRealDocumentLoad() && isLoadingMainFrame())
2096                     history()->updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
2097
2098                 history()->updateForBackForwardNavigation();
2099
2100                 // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
2101                 if (history()->currentItem() && !cachedPage)
2102                     m_pendingStateObject = history()->currentItem()->stateObject();
2103
2104                 // Create a document view for this document, or used the cached view.
2105                 if (cachedPage) {
2106                     DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
2107                     ASSERT(cachedDocumentLoader);
2108                     cachedDocumentLoader->setFrame(m_frame);
2109                     m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
2110
2111                 } else
2112                     m_client->transitionToCommittedForNewPage();
2113             }
2114             break;
2115
2116         case FrameLoadTypeReload:
2117         case FrameLoadTypeReloadFromOrigin:
2118         case FrameLoadTypeSame:
2119         case FrameLoadTypeReplace:
2120             history()->updateForReload();
2121             m_client->transitionToCommittedForNewPage();
2122             break;
2123
2124         case FrameLoadTypeStandard:
2125             history()->updateForStandardLoad();
2126             if (m_frame->view())
2127                 m_frame->view()->setScrollbarsSuppressed(true);
2128             m_client->transitionToCommittedForNewPage();
2129             break;
2130
2131         case FrameLoadTypeRedirectWithLockedBackForwardList:
2132             history()->updateForRedirectWithLockedBackForwardList();
2133             m_client->transitionToCommittedForNewPage();
2134             break;
2135
2136         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
2137         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
2138         default:
2139             ASSERT_NOT_REACHED();
2140     }
2141
2142     m_documentLoader->writer()->setMIMEType(dl->responseMIMEType());
2143
2144     // Tell the client we've committed this URL.
2145     ASSERT(m_frame->view());
2146
2147     if (m_stateMachine.creatingInitialEmptyDocument())
2148         return;
2149
2150     if (!m_stateMachine.committedFirstRealDocumentLoad())
2151         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
2152
2153     if (!m_client->hasHTMLView())
2154         receivedFirstData();
2155 }
2156
2157 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
2158 {
2159     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2160     // the redirect succeeded.  We should either rename this API, or add a new method, like
2161     // -webView:didFinishClientRedirectForFrame:
2162     m_client->dispatchDidCancelClientRedirect();
2163
2164     if (!cancelWithLoadInProgress)
2165         m_quickRedirectComing = false;
2166
2167     m_sentRedirectNotification = false;
2168 }
2169
2170 void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList)
2171 {
2172     m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
2173     
2174     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2175     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2176     m_sentRedirectNotification = true;
2177     
2178     // If a "quick" redirect comes in, we set a special mode so we treat the next
2179     // load as part of the original navigation. If we don't have a document loader, we have
2180     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
2181     // Loads triggered by JavaScript form submissions never count as quick redirects.
2182     m_quickRedirectComing = (lockBackForwardList || history()->currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
2183 }
2184
2185 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
2186 {
2187     // This function implements the rule: "Don't reload if navigating by fragment within
2188     // the same URL, but do reload if going to a new URL or to the same URL with no
2189     // fragment identifier at all."
2190     if (!destinationURL.hasFragmentIdentifier())
2191         return true;
2192     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
2193 }
2194
2195 void FrameLoader::closeOldDataSources()
2196 {
2197     // FIXME: Is it important for this traversal to be postorder instead of preorder?
2198     // If so, add helpers for postorder traversal, and use them. If not, then lets not
2199     // use a recursive algorithm here.
2200     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
2201         child->loader()->closeOldDataSources();
2202     
2203     if (m_documentLoader)
2204         m_client->dispatchWillClose();
2205
2206     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
2207 }
2208
2209 void FrameLoader::prepareForCachedPageRestore()
2210 {
2211     ASSERT(!m_frame->tree()->parent());
2212     ASSERT(m_frame->page());
2213     ASSERT(m_frame->page()->mainFrame() == m_frame);
2214
2215     m_frame->navigationScheduler()->cancel();
2216
2217     // We still have to close the previous part page.
2218     closeURL();
2219     
2220     // Delete old status bar messages (if it _was_ activated on last URL).
2221     if (m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) {
2222         if (DOMWindow* window = m_frame->existingDOMWindow()) {
2223             window->setStatus(String());
2224             window->setDefaultStatus(String());
2225         }
2226     }
2227 }
2228
2229 void FrameLoader::open(CachedFrameBase& cachedFrame)
2230 {
2231     m_isComplete = false;
2232     
2233     // Don't re-emit the load event.
2234     m_didCallImplicitClose = true;
2235
2236     KURL url = cachedFrame.url();
2237
2238     if (url.protocolInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
2239         url.setPath("/");
2240     
2241     m_workingURL = url;
2242
2243     started();
2244     clear(true, true, cachedFrame.isMainFrame());
2245
2246     Document* document = cachedFrame.document();
2247     ASSERT(document);
2248     document->setInPageCache(false);
2249
2250     m_needsClear = true;
2251     m_isComplete = false;
2252     m_didCallImplicitClose = false;
2253     m_outgoingReferrer = url.string();
2254
2255     FrameView* view = cachedFrame.view();
2256     
2257     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
2258     ASSERT(view);
2259     view->setWasScrolledByUser(false);
2260
2261     // Use the current ScrollView's frame rect.
2262     if (m_frame->view()) {
2263         IntRect rect = m_frame->view()->frameRect();
2264         view->setFrameRect(rect);
2265         view->setBoundsSize(rect.size());
2266     }
2267     m_frame->setView(view);
2268     
2269     m_frame->setDocument(document);
2270     m_frame->setDOMWindow(cachedFrame.domWindow());
2271     m_frame->domWindow()->setURL(document->url());
2272     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
2273
2274     updateFirstPartyForCookies();
2275
2276     cachedFrame.restore();
2277 }
2278
2279 bool FrameLoader::isStopping() const
2280 {
2281     return activeDocumentLoader()->isStopping();
2282 }
2283
2284 void FrameLoader::finishedLoading()
2285 {
2286     // Retain because the stop may release the last reference to it.
2287     RefPtr<Frame> protect(m_frame);
2288
2289     RefPtr<DocumentLoader> dl = activeDocumentLoader();
2290     dl->finishedLoading();
2291     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
2292         return;
2293     dl->setPrimaryLoadComplete(true);
2294     m_client->dispatchDidLoadMainResource(dl.get());
2295     checkLoadComplete();
2296 }
2297
2298 bool FrameLoader::isHostedByObjectElement() const
2299 {
2300     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
2301     return owner && owner->hasTagName(objectTag);
2302 }
2303
2304 bool FrameLoader::isLoadingMainFrame() const
2305 {
2306     Page* page = m_frame->page();
2307     return page && m_frame == page->mainFrame();
2308 }
2309
2310 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
2311 {
2312     return m_client->canShowMIMEType(MIMEType);
2313 }
2314
2315 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
2316 {
2317     return m_client->representationExistsForURLScheme(URLScheme);
2318 }
2319
2320 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
2321 {
2322     return m_client->generatedMIMETypeForURLScheme(URLScheme);
2323 }
2324
2325 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
2326 {
2327     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
2328 }
2329
2330 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
2331 {
2332     // FIXME: Platforms shouldn't differ here!
2333 #if PLATFORM(WIN) || PLATFORM(CHROMIUM)
2334     if (m_stateMachine.creatingInitialEmptyDocument())
2335         return;
2336 #endif
2337
2338 #if !ENABLE(WEB_ARCHIVE) && !ENABLE(MHTML)
2339     m_client->finishedLoading(loader);
2340 #else
2341     // Give archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0.
2342     m_archive = ArchiveFactory::create(loader->response().url(), loader->mainResourceData().get(), loader->responseMIMEType());
2343     if (!m_archive) {
2344         m_client->finishedLoading(loader);
2345         return;
2346     }
2347
2348     // FIXME: The remainder of this function should be moved to DocumentLoader.
2349
2350     loader->addAllArchiveResources(m_archive.get());
2351
2352     ArchiveResource* mainResource = m_archive->mainResource();
2353     loader->setParsedArchiveData(mainResource->data());
2354
2355     loader->writer()->setMIMEType(mainResource->mimeType());
2356
2357     closeURL();
2358     didOpenURL(mainResource->url());
2359
2360     ASSERT(m_frame->document());
2361     String userChosenEncoding = documentLoader()->overrideEncoding();
2362     bool encodingIsUserChosen = !userChosenEncoding.isNull();
2363     loader->writer()->setEncoding(encodingIsUserChosen ? userChosenEncoding : mainResource->textEncoding(), encodingIsUserChosen);
2364     loader->writer()->addData(mainResource->data()->data(), mainResource->data()->size());
2365 #endif // ENABLE(WEB_ARCHIVE)
2366 }
2367
2368 bool FrameLoader::isReplacing() const
2369 {
2370     return m_loadType == FrameLoadTypeReplace;
2371 }
2372
2373 void FrameLoader::setReplacing()
2374 {
2375     m_loadType = FrameLoadTypeReplace;
2376 }
2377
2378 void FrameLoader::revertToProvisional(DocumentLoader* loader)
2379 {
2380     m_client->revertToProvisionalState(loader);
2381 }
2382
2383 bool FrameLoader::subframeIsLoading() const
2384 {
2385     // It's most likely that the last added frame is the last to load so we walk backwards.
2386     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
2387         FrameLoader* childLoader = child->loader();
2388         DocumentLoader* documentLoader = childLoader->documentLoader();
2389         if (documentLoader && documentLoader->isLoadingInAPISense())
2390             return true;
2391         documentLoader = childLoader->provisionalDocumentLoader();
2392         if (documentLoader && documentLoader->isLoadingInAPISense())
2393             return true;
2394         documentLoader = childLoader->policyDocumentLoader();
2395         if (documentLoader)
2396             return true;
2397     }
2398     return false;
2399 }
2400
2401 void FrameLoader::willChangeTitle(DocumentLoader* loader)
2402 {
2403     m_client->willChangeTitle(loader);
2404 }
2405
2406 FrameLoadType FrameLoader::loadType() const
2407 {
2408     return m_loadType;
2409 }
2410     
2411 CachePolicy FrameLoader::subresourceCachePolicy() const
2412 {
2413     if (m_isComplete)
2414         return CachePolicyVerify;
2415
2416     if (m_loadType == FrameLoadTypeReloadFromOrigin)
2417         return CachePolicyReload;
2418
2419     if (Frame* parentFrame = m_frame->tree()->parent()) {
2420         CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy();
2421         if (parentCachePolicy != CachePolicyVerify)
2422             return parentCachePolicy;
2423     }
2424     
2425     if (m_loadType == FrameLoadTypeReload)
2426         return CachePolicyRevalidate;
2427
2428     const ResourceRequest& request(documentLoader()->request());
2429 #if PLATFORM(MAC)
2430     if (request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post") && ResourceRequest::useQuickLookResourceCachingQuirks())
2431         return CachePolicyRevalidate;
2432 #endif
2433
2434     if (request.cachePolicy() == ReturnCacheDataElseLoad)
2435         return CachePolicyHistoryBuffer;
2436
2437     return CachePolicyVerify;
2438 }
2439
2440 void FrameLoader::checkLoadCompleteForThisFrame()
2441 {
2442     ASSERT(m_client->hasWebView());
2443
2444     switch (m_state) {
2445         case FrameStateProvisional: {
2446             if (m_delegateIsHandlingProvisionalLoadError)
2447                 return;
2448
2449             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2450             if (!pdl)
2451                 return;
2452                 
2453             // If we've received any errors we may be stuck in the provisional state and actually complete.
2454             const ResourceError& error = pdl->mainDocumentError();
2455             if (error.isNull())
2456                 return;
2457
2458             // Check all children first.
2459             RefPtr<HistoryItem> item;
2460             if (Page* page = m_frame->page())
2461                 if (isBackForwardLoadType(loadType()))
2462                     // Reset the back forward list to the last committed history item at the top level.
2463                     item = page->mainFrame()->loader()->history()->currentItem();
2464                 
2465             // Only reset if we aren't already going to a new provisional item.
2466             bool shouldReset = !history()->provisionalItem();
2467             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
2468                 m_delegateIsHandlingProvisionalLoadError = true;
2469                 m_client->dispatchDidFailProvisionalLoad(error);
2470                 m_delegateIsHandlingProvisionalLoadError = false;
2471
2472                 ASSERT(!pdl->isLoading());
2473                 ASSERT(!pdl->isLoadingMainResource());
2474                 ASSERT(!pdl->isLoadingSubresources());
2475                 ASSERT(!pdl->isLoadingPlugIns());
2476
2477                 // If we're in the middle of loading multipart data, we need to restore the document loader.
2478                 if (isReplacing() && !m_documentLoader.get())
2479                     setDocumentLoader(m_provisionalDocumentLoader.get());
2480
2481                 // Finish resetting the load state, but only if another load hasn't been started by the
2482                 // delegate callback.
2483                 if (pdl == m_provisionalDocumentLoader)
2484                     clearProvisionalLoad();
2485                 else if (activeDocumentLoader()) {
2486                     KURL unreachableURL = activeDocumentLoader()->unreachableURL();
2487                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2488                         shouldReset = false;
2489                 }
2490             }
2491             if (shouldReset && item)
2492                 if (Page* page = m_frame->page()) {
2493                     page->backForward()->setCurrentItem(item.get());
2494                     m_frame->loader()->client()->updateGlobalHistoryItemForPage();
2495                 }
2496             return;
2497         }
2498         
2499         case FrameStateCommittedPage: {
2500             DocumentLoader* dl = m_documentLoader.get();            
2501             if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
2502                 return;
2503
2504             markLoadComplete();
2505
2506             // FIXME: Is this subsequent work important if we already navigated away?
2507             // Maybe there are bugs because of that, or extra work we can skip because
2508             // the new page is ready.
2509
2510             m_client->forceLayoutForNonHTML();
2511              
2512             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
2513             if (m_frame->page()) {
2514                 if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin)
2515                     history()->restoreScrollPositionAndViewState();
2516             }
2517
2518             if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
2519                 return;
2520
2521             const ResourceError& error = dl->mainDocumentError();
2522             if (!error.isNull())
2523                 m_client->dispatchDidFailLoad(error);
2524             else
2525                 m_client->dispatchDidFinishLoad();
2526
2527             if (Page* page = m_frame->page())
2528                 page->progress()->progressCompleted(m_frame);
2529             return;
2530         }
2531         
2532         case FrameStateComplete:
2533             frameLoadCompleted();
2534             return;
2535     }
2536
2537     ASSERT_NOT_REACHED();
2538 }
2539
2540 void FrameLoader::continueLoadAfterWillSubmitForm()
2541 {
2542     if (!m_provisionalDocumentLoader)
2543         return;
2544
2545     // DocumentLoader calls back to our prepareForLoadStart
2546     m_provisionalDocumentLoader->prepareForLoadStart();
2547     
2548     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader, 
2549     // so we need to null check it again.
2550     if (!m_provisionalDocumentLoader)
2551         return;
2552
2553     DocumentLoader* activeDocLoader = activeDocumentLoader();
2554     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2555         return;
2556
2557     m_loadingFromCachedPage = false;
2558
2559     unsigned long identifier = 0;
2560
2561     if (Page* page = m_frame->page()) {
2562         identifier = page->progress()->createUniqueIdentifier();
2563         notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
2564     }
2565
2566     ASSERT(!m_provisionalDocumentLoader->timing()->navigationStart);
2567     m_provisionalDocumentLoader->timing()->navigationStart = currentTime();
2568
2569     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
2570         m_provisionalDocumentLoader->updateLoading();
2571 }
2572
2573 void FrameLoader::didFirstLayout()
2574 {
2575     if (m_frame->page() && isBackForwardLoadType(m_loadType))
2576         history()->restoreScrollPositionAndViewState();
2577
2578     if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2579         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2580     m_client->dispatchDidFirstLayout();
2581 }
2582
2583 void FrameLoader::didFirstVisuallyNonEmptyLayout()
2584 {
2585     m_client->dispatchDidFirstVisuallyNonEmptyLayout();
2586 }
2587
2588 void FrameLoader::frameLoadCompleted()
2589 {
2590     // Note: Can be called multiple times.
2591
2592     m_client->frameLoadCompleted();
2593
2594     history()->updateForFrameLoadCompleted();
2595
2596     // After a canceled provisional load, firstLayoutDone is false.
2597     // Reset it to true if we're displaying a page.
2598     if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2599         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2600 }
2601
2602 void FrameLoader::detachChildren()
2603 {
2604     // FIXME: Is it really necessary to do this in reverse order?
2605     Frame* previous;
2606     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
2607         previous = child->tree()->previousSibling();
2608         child->loader()->detachFromParent();
2609     }
2610 }
2611
2612 void FrameLoader::closeAndRemoveChild(Frame* child)
2613 {
2614     child->tree()->detachFromParent();
2615
2616     child->setView(0);
2617     if (child->ownerElement() && child->page())
2618         child->page()->decrementFrameCount();
2619     // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed().
2620     child->pageDestroyed();
2621
2622     m_frame->tree()->removeChild(child);
2623 }
2624
2625 void FrameLoader::recursiveCheckLoadComplete()
2626 {
2627     Vector<RefPtr<Frame>, 10> frames;
2628     
2629     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
2630         frames.append(frame);
2631     
2632     unsigned size = frames.size();
2633     for (unsigned i = 0; i < size; i++)
2634         frames[i]->loader()->recursiveCheckLoadComplete();
2635     
2636     checkLoadCompleteForThisFrame();
2637 }
2638
2639 // Called every time a resource is completely loaded, or an error is received.
2640 void FrameLoader::checkLoadComplete()
2641 {
2642     ASSERT(m_client->hasWebView());
2643     
2644     m_shouldCallCheckLoadComplete = false;
2645
2646     // FIXME: Always traversing the entire frame tree is a bit inefficient, but 
2647     // is currently needed in order to null out the previous history item for all frames.
2648     if (Page* page = m_frame->page())
2649         page->mainFrame()->loader()->recursiveCheckLoadComplete();
2650 }
2651
2652 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2653 {
2654     if (!recurse)
2655         return numRequests(m_frame->document());
2656
2657     int count = 0;
2658     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
2659         count += numRequests(frame->document());
2660     return count;
2661 }
2662
2663 String FrameLoader::userAgent(const KURL& url) const
2664 {
2665     String userAgent = m_client->userAgent(url);
2666     InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
2667     return userAgent;
2668 }
2669
2670 void FrameLoader::handledOnloadEvents()
2671 {
2672     m_client->dispatchDidHandleOnloadEvents();
2673
2674     if (documentLoader()) {
2675         documentLoader()->handledOnloadEvents();
2676 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
2677         documentLoader()->applicationCacheHost()->stopDeferringEvents();
2678 #endif
2679     }
2680 }
2681
2682 void FrameLoader::frameDetached()
2683 {
2684     stopAllLoaders();
2685     m_frame->document()->stopActiveDOMObjects();
2686     detachFromParent();
2687 }
2688
2689 void FrameLoader::detachFromParent()
2690 {
2691     RefPtr<Frame> protect(m_frame);
2692
2693     closeURL();
2694     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
2695     detachChildren();
2696     // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
2697     // will trigger the unload event handlers of any child frames, and those event
2698     // handlers might start a new subresource load in this frame.
2699     stopAllLoaders();
2700
2701     InspectorInstrumentation::frameDetachedFromParent(m_frame);
2702
2703     detachViewsAndDocumentLoader();
2704
2705     if (Frame* parent = m_frame->tree()->parent()) {
2706         parent->loader()->closeAndRemoveChild(m_frame);
2707         parent->loader()->scheduleCheckCompleted();
2708     } else {
2709         m_frame->setView(0);
2710         // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed().
2711         m_frame->pageDestroyed();
2712     }
2713 }
2714
2715 void FrameLoader::detachViewsAndDocumentLoader()
2716 {
2717     m_client->detachedFromParent2();
2718     setDocumentLoader(0);
2719     m_client->detachedFromParent3();
2720 }
2721     
2722 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
2723 {
2724     addExtraFieldsToRequest(request, m_loadType, false, false);
2725 }
2726
2727 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
2728 {
2729     addExtraFieldsToRequest(request, m_loadType, true, false);
2730 }
2731
2732 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
2733 {
2734     // Don't set the cookie policy URL if it's already been set.
2735     // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>).
2736     if (request.firstPartyForCookies().isEmpty()) {
2737         if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
2738             request.setFirstPartyForCookies(request.url());
2739         else if (Document* document = m_frame->document())
2740             request.setFirstPartyForCookies(document->firstPartyForCookies());
2741     }
2742
2743     // The remaining modifications are only necessary for HTTP and HTTPS.
2744     if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily())
2745         return;
2746
2747     applyUserAgent(request);
2748     
2749     // If we inherit cache policy from a main resource, we use the DocumentLoader's 
2750     // original request cache policy for two reasons:
2751     // 1. For POST requests, we mutate the cache policy for the main resource,
2752     //    but we do not want this to apply to subresources
2753     // 2. Delegates that modify the cache policy using willSendRequest: should
2754     //    not affect any other resources. Such changes need to be done
2755     //    per request.
2756     if (!mainResource) {
2757         if (request.isConditional())
2758             request.setCachePolicy(ReloadIgnoringCacheData);
2759         else if (documentLoader()->isLoadingInAPISense())
2760             request.setCachePolicy(documentLoader()->originalRequest().cachePolicy());
2761         else
2762             request.setCachePolicy(UseProtocolCachePolicy);
2763     } else if (loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadFromOrigin || request.isConditional())
2764         request.setCachePolicy(ReloadIgnoringCacheData);
2765     else if (isBackForwardLoadType(loadType) && m_stateMachine.committedFirstRealDocumentLoad() && !request.url().protocolIs("https"))
2766         request.setCachePolicy(ReturnCacheDataElseLoad);
2767         
2768     if (request.cachePolicy() == ReloadIgnoringCacheData) {
2769         if (loadType == FrameLoadTypeReload)
2770             request.setHTTPHeaderField("Cache-Control", "max-age=0");
2771         else if (loadType == FrameLoadTypeReloadFromOrigin) {
2772             request.setHTTPHeaderField("Cache-Control", "no-cache");
2773             request.setHTTPHeaderField("Pragma", "no-cache");
2774         }
2775     }
2776     
2777     if (mainResource)
2778         request.setHTTPAccept(defaultAcceptHeader);
2779
2780     // Make sure we send the Origin header.
2781     addHTTPOriginIfNeeded(request, String());
2782
2783     // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
2784     // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
2785     Settings* settings = m_frame->settings();
2786     request.setResponseContentDispositionEncodingFallbackArray("UTF-8", activeDocumentLoader()->writer()->deprecatedFrameEncoding(), settings ? settings->defaultTextEncodingName() : String());
2787 }
2788
2789 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
2790 {
2791     if (!request.httpOrigin().isEmpty())
2792         return;  // Request already has an Origin header.
2793
2794     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2795     // For example, if an intranet page has a hyperlink to an external web
2796     // site, we don't want to include the Origin of the request because it
2797     // will leak the internal host name. Similar privacy concerns have lead
2798     // to the widespread suppression of the Referer header at the network
2799     // layer.
2800     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2801         return;
2802
2803     // For non-GET and non-HEAD methods, always send an Origin header so the
2804     // server knows we support this feature.
2805
2806     if (origin.isEmpty()) {
2807         // If we don't know what origin header to attach, we attach the value
2808         // for an empty origin.
2809         origin = SecurityOrigin::createEmpty()->toString();
2810     }
2811
2812     request.setHTTPOrigin(origin);
2813 }
2814
2815 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
2816 {
2817     RefPtr<FormState> formState = prpFormState;
2818
2819     // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a 
2820     // bunch of parameters that would come in here and then be built back up to a ResourceRequest.  In case
2821     // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
2822     // from scratch as it did all along.
2823     const KURL& url = inRequest.url();
2824     RefPtr<FormData> formData = inRequest.httpBody();
2825     const String& contentType = inRequest.httpContentType();
2826     String origin = inRequest.httpOrigin();
2827
2828     ResourceRequest workingResourceRequest(url);    
2829
2830     if (!referrer.isEmpty())
2831         workingResourceRequest.setHTTPReferrer(referrer);
2832     workingResourceRequest.setHTTPOrigin(origin);
2833     workingResourceRequest.setHTTPMethod("POST");
2834     workingResourceRequest.setHTTPBody(formData);
2835     workingResourceRequest.setHTTPContentType(contentType);
2836     addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
2837
2838     NavigationAction action(url, loadType, true, event);
2839
2840     if (!frameName.isEmpty()) {
2841         // The search for a target frame is done earlier in the case of form submission.
2842         if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName))
2843             targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
2844         else
2845             policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, workingResourceRequest, formState.release(), frameName, this);
2846     } else
2847         loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());    
2848 }
2849
2850 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
2851 {
2852     String referrer = m_outgoingReferrer;
2853     if (SecurityOrigin::shouldHideReferrer(request.url(), referrer))
2854         referrer = String();
2855     
2856     ResourceRequest initialRequest = request;
2857     initialRequest.setTimeoutInterval(10);
2858     
2859     if (!referrer.isEmpty())
2860         initialRequest.setHTTPReferrer(referrer);
2861     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
2862
2863     if (Page* page = m_frame->page())
2864         initialRequest.setFirstPartyForCookies(page->mainFrame()->loader()->documentLoader()->request().url());
2865     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
2866     
2867     addExtraFieldsToSubresourceRequest(initialRequest);
2868
2869     unsigned long identifier = 0;    
2870     ResourceRequest newRequest(initialRequest);
2871     requestFromDelegate(newRequest, identifier, error);
2872
2873     if (error.isNull()) {
2874         ASSERT(!newRequest.isNull());
2875         
2876 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
2877         if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
2878 #endif
2879             ResourceHandle::loadResourceSynchronously(networkingContext(), newRequest, storedCredentials, error, response, data);
2880 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
2881             documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
2882         }
2883 #endif
2884     }
2885     int encodedDataLength = response.resourceLoadInfo() ? static_cast<int>(response.resourceLoadInfo()->encodedDataLength) : -1;
2886     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), encodedDataLength, error);
2887     return identifier;
2888 }
2889
2890 const ResourceRequest& FrameLoader::originalRequest() const
2891 {
2892     return activeDocumentLoader()->originalRequestCopy();
2893 }
2894
2895 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
2896 {
2897     // Retain because the stop may release the last reference to it.
2898     RefPtr<Frame> protect(m_frame);
2899
2900     RefPtr<DocumentLoader> loader = activeDocumentLoader();
2901
2902     if (isComplete) {
2903         // FIXME: Don't want to do this if an entirely new load is going, so should check
2904         // that both data sources on the frame are either this or nil.
2905         stop();
2906         if (m_client->shouldFallBack(error))
2907             handleFallbackContent();
2908     }
2909
2910     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
2911         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
2912             m_submittedFormURL = KURL();
2913             
2914         // We might have made a page cache item, but now we're bailing out due to an error before we ever
2915         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
2916         // so that the existing view (that wenever got far enough to replace) can continue being used.
2917         history()->invalidateCurrentItemCachedPage();
2918         
2919         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
2920         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2921         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
2922         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
2923         // has ended.
2924         if (m_sentRedirectNotification)
2925             clientRedirectCancelledOrFinished(false);
2926     }
2927
2928     loader->mainReceivedError(error, isComplete);
2929 }
2930
2931 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
2932     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
2933 {
2934     FrameLoader* loader = static_cast<FrameLoader*>(argument);
2935     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
2936 }
2937
2938 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
2939 {
2940     m_quickRedirectComing = false;
2941
2942     if (!shouldContinue)
2943         return;
2944
2945     bool isRedirect = m_quickRedirectComing || policyChecker()->loadType() == FrameLoadTypeRedirectWithLockedBackForwardList;    
2946     loadInSameDocument(request.url(), 0, !isRedirect);
2947 }
2948
2949 bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
2950 {
2951     // Should we do anchor navigation within the existing content?
2952
2953     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
2954     // currently displaying a frameset, or if the URL does not have a fragment.
2955     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
2956
2957     // FIXME: What about load types other than Standard and Reload?
2958
2959     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
2960         && loadType != FrameLoadTypeReload
2961         && loadType != FrameLoadTypeReloadFromOrigin
2962         && loadType != FrameLoadTypeSame
2963         && !shouldReload(m_frame->document()->url(), url)
2964         // We don't want to just scroll if a link from within a
2965         // frameset is trying to reload the frameset into _top.
2966         && !m_frame->document()->isFrameSet();
2967 }
2968
2969 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
2970     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
2971 {
2972     FrameLoader* loader = static_cast<FrameLoader*>(argument);
2973     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
2974 }
2975
2976 bool FrameLoader::shouldClose()
2977 {
2978     Page* page = m_frame->page();
2979     Chrome* chrome = page ? page->chrome() : 0;
2980     if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
2981         return true;
2982
2983     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
2984     Vector<RefPtr<Frame> > targetFrames;
2985     targetFrames.append(m_frame);
2986     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame))
2987         targetFrames.append(child);
2988
2989     bool shouldClose = false;
2990     {
2991         NavigationDisablerForBeforeUnload navigationDisabler;
2992         size_t i;
2993
2994         for (i = 0; i < targetFrames.size(); i++) {
2995             if (!targetFrames[i]->tree()->isDescendantOf(m_frame))
2996                 continue;
2997             if (!targetFrames[i]->loader()->fireBeforeUnloadEvent(chrome))
2998                 break;
2999         }
3000
3001         if (i == targetFrames.size())
3002             shouldClose = true;
3003     }
3004
3005     return shouldClose;
3006 }
3007
3008 bool FrameLoader::fireBeforeUnloadEvent(Chrome* chrome)
3009 {
3010     DOMWindow* domWindow = m_frame->existingDOMWindow();
3011     if (!domWindow)
3012         return true;
3013
3014     RefPtr<Document> document = m_frame->document();
3015     if (!document->body())
3016         return true;
3017
3018     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
3019     m_pageDismissalEventBeingDispatched = true;
3020     domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
3021     m_pageDismissalEventBeingDispatched = false;
3022
3023     if (!beforeUnloadEvent->defaultPrevented())
3024         document->defaultEventHandler(beforeUnloadEvent.get());
3025     if (beforeUnloadEvent->result().isNull())
3026         return true;
3027
3028     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->result());
3029     return chrome->runBeforeUnloadConfirmPanel(text, m_frame);
3030 }
3031
3032 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
3033 {
3034     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3035     // nil policyDataSource because loading the alternate page will have passed
3036     // through this method already, nested; otherwise, policyDataSource should still be set.
3037     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3038
3039     bool isTargetItem = history()->provisionalItem() ? history()->provisionalItem()->isTargetItem() : false;
3040
3041     // Two reasons we can't continue:
3042     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
3043     //       is the user responding Cancel to the form repost nag sheet.
3044     //    2) User responded Cancel to an alert popped up by the before unload event handler.
3045     bool canContinue = shouldContinue && shouldClose();
3046
3047     if (!canContinue) {
3048         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
3049         // need to report that the client redirect was cancelled.
3050         if (m_quickRedirectComing)
3051             clientRedirectCancelledOrFinished(false);
3052
3053         setPolicyDocumentLoader(0);
3054
3055         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
3056         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
3057         // we only do this when punting a navigation for the target frame or top-level frame.  
3058         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(policyChecker()->loadType())) {
3059             if (Page* page = m_frame->page()) {
3060                 Frame* mainFrame = page->mainFrame();
3061                 if (HistoryItem* resetItem = mainFrame->loader()->history()->currentItem()) {
3062                     page->backForward()->setCurrentItem(resetItem);
3063                     m_frame->loader()->client()->updateGlobalHistoryItemForPage();
3064                 }
3065             }
3066         }
3067         return;
3068     }
3069
3070     FrameLoadType type = policyChecker()->loadType();
3071     // A new navigation is in progress, so don't clear the history's provisional item.
3072     stopAllLoaders(ShouldNotClearProvisionalItem);
3073     
3074     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3075     // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 
3076     if (!m_frame->page())
3077         return;
3078
3079 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) && ENABLE(INSPECTOR)
3080     if (Page* page = m_frame->page()) {
3081         if (page->mainFrame() == m_frame)
3082             m_frame->page()->inspectorController()->resume();
3083     }
3084 #endif
3085
3086     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3087     m_loadType = type;
3088     setState(FrameStateProvisional);
3089
3090     setPolicyDocumentLoader(0);
3091
3092     if (isBackForwardLoadType(type) && history()->provisionalItem()->isInPageCache()) {
3093         loadProvisionalItemFromCachedPage();
3094         return;
3095     }
3096
3097     if (formState)
3098         m_client->dispatchWillSubmitForm(&PolicyChecker::continueLoadAfterWillSubmitForm, formState);
3099     else
3100         continueLoadAfterWillSubmitForm();
3101 }
3102
3103 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
3104     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue)
3105 {
3106     FrameLoader* loader = static_cast<FrameLoader*>(argument);
3107     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue);
3108 }
3109
3110 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
3111     PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue)
3112 {
3113     if (!shouldContinue)
3114         return;
3115
3116     RefPtr<Frame> frame = m_frame;
3117     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(action);
3118     if (!mainFrame)
3119         return;
3120
3121     if (frameName != "_blank")
3122         mainFrame->tree()->setName(frameName);
3123
3124     mainFrame->page()->setOpenedByDOM();
3125     mainFrame->loader()->m_client->dispatchShow();
3126     if (!m_suppressOpenerInNewFrame)
3127         mainFrame->loader()->setOpener(frame.get());
3128     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
3129 }
3130
3131 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
3132 {
3133     ASSERT(!request.isNull());
3134
3135     identifier = 0;
3136     if (Page* page = m_frame->page()) {
3137         identifier = page->progress()->createUniqueIdentifier();
3138         notifier()->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
3139     }
3140
3141     ResourceRequest newRequest(request);
3142     notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
3143
3144     if (newRequest.isNull())
3145         error = cancelledError(request);
3146     else
3147         error = ResourceError();
3148
3149     request = newRequest;
3150 }
3151
3152 void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
3153 {
3154     Page* page = m_frame->page();
3155     if (!page)
3156         return;
3157
3158     if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
3159         return;
3160
3161     if (!page->areMemoryCacheClientCallsEnabled()) {
3162         InspectorInstrumentation::didLoadResourceFromMemoryCache(page, m_documentLoader.get(), resource);
3163         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
3164         m_documentLoader->didTellClientAboutLoad(resource->url());
3165         return;
3166     }
3167
3168     ResourceRequest request(resource->url());
3169     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
3170         InspectorInstrumentation::didLoadResourceFromMemoryCache(page, m_documentLoader.get(), resource);
3171         m_documentLoader->didTellClientAboutLoad(resource->url());
3172         return;
3173     }
3174
3175     unsigned long identifier;
3176     ResourceError error;
3177     requestFromDelegate(request, identifier, error);
3178     InspectorInstrumentation::markResourceAsCached(page, identifier);
3179     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), 0, error);
3180 }
3181
3182 void FrameLoader::applyUserAgent(ResourceRequest& request)
3183 {
3184     String userAgent = this->userAgent(request.url());
3185     ASSERT(!userAgent.isNull());
3186     request.setHTTPUserAgent(userAgent);
3187 }
3188
3189 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url)
3190 {
3191     Frame* topFrame = m_frame->tree()->top();
3192     if (m_frame == topFrame)
3193         return false;
3194
3195     if (equalIgnoringCase(content, "deny"))
3196         return true;
3197
3198     if (equalIgnoringCase(content, "sameorigin")) {
3199         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
3200         if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin()))
3201             return true;
3202     }
3203
3204     return false;
3205 }
3206
3207 void FrameLoader::loadProvisionalItemFromCachedPage()
3208 {
3209     DocumentLoader* provisionalLoader = provisionalDocumentLoader();
3210     LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().string().utf8().data());
3211
3212     provisionalLoader->prepareForLoadStart();
3213
3214     m_loadingFromCachedPage = true;
3215     
3216     // Should have timing data from previous time(s) the page was shown.
3217     ASSERT(provisionalLoader->timing()->navigationStart);
3218     provisionalLoader->resetTiming();
3219     provisionalLoader->timing()->navigationStart = currentTime();    
3220
3221     provisionalLoader->setCommitted(true);
3222     commitProvisionalLoad();
3223 }
3224
3225 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
3226 {
3227     if (!history()->currentItem())
3228         return false;
3229     return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL();
3230 }
3231
3232 void FrameLoader::checkDidPerformFirstNavigation()
3233 {
3234     Page* page = m_frame->page();
3235     if (!page)
3236         return;
3237
3238     if (!m_didPerformFirstNavigation && page->backForward()->currentItem() && !page->backForward()->backItem() && !page->backForward()->forwardItem()) {
3239         m_didPerformFirstNavigation = true;
3240         m_client->didPerformFirstNavigation();
3241     }
3242 }
3243
3244 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name)
3245 {
3246     Frame* frame = m_frame->tree()->find(name);
3247     if (!shouldAllowNavigation(frame))
3248         return 0;
3249     return frame;
3250 }
3251
3252 void FrameLoader::loadSameDocumentItem(HistoryItem* item)
3253 {
3254     ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber());
3255
3256     // Save user view state to the current history item here since we don't do a normal load.
3257     // FIXME: Does form state need to be saved here too?
3258     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
3259     if (FrameView* view = m_frame->view())
3260         view->setWasScrolledByUser(false);
3261
3262     history()->setCurrentItem(item);
3263         
3264     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
3265     loadInSameDocument(item->url(), item->stateObject(), false);
3266
3267     // Restore user view state from the current history item here since we don't do a normal load.
3268     history()->restoreScrollPositionAndViewState();
3269 }
3270
3271 // FIXME: This function should really be split into a couple pieces, some of
3272 // which should be methods of HistoryController and some of which should be
3273 // methods of FrameLoader.
3274 void FrameLoader::loadDifferentDocumentItem(HistoryItem* item, FrameLoadType loadType)
3275 {
3276     // Remember this item so we can traverse any child items as child frames load
3277     history()->setProvisionalItem(item);
3278
3279     if (CachedPage* cachedPage = pageCache()->get(item)) {
3280         loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0);   
3281         return;
3282     }
3283
3284     KURL itemURL = item->url();
3285     KURL itemOriginalURL = item->originalURL();
3286     KURL currentURL;
3287     if (documentLoader())
3288         currentURL = documentLoader()->url();
3289     RefPtr<FormData> formData = item->formData();
3290
3291     bool addedExtraFields = false;
3292     ResourceRequest request(itemURL);
3293
3294     if (!item->referrer().isNull())
3295         request.setHTTPReferrer(item->referrer());
3296     
3297     // If this was a repost that failed the page cache, we might try to repost the form.
3298     NavigationAction action;
3299     if (formData) {
3300         formData->generateFiles(m_frame->document());
3301
3302         request.setHTTPMethod("POST");
3303         request.setHTTPBody(formData);
3304         request.setHTTPContentType(item->formContentType());
3305         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
3306         addHTTPOriginIfNeeded(request, securityOrigin->toString());
3307
3308         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
3309         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
3310         addExtraFieldsToRequest(request, m_loadType, true, formData);
3311         addedExtraFields = true;
3312         
3313         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3314         // We want to know this before talking to the policy delegate, since it affects whether 
3315         // we show the DoYouReallyWantToRepost nag.
3316         //
3317         // This trick has a small bug (3123893) where we might find a cache hit, but then
3318         // have the item vanish when we try to use it in the ensuing nav.  This should be
3319         // extremely rare, but in that case the user will get an error on the navigation.
3320         
3321         if (ResourceHandle::willLoadFromCache(request, m_frame))
3322             action = NavigationAction(itemURL, loadType, false);
3323         else {
3324             request.setCachePolicy(ReloadIgnoringCacheData);
3325             action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
3326         }
3327     } else {
3328         switch (loadType) {
3329             case FrameLoadTypeReload:
3330             case FrameLoadTypeReloadFromOrigin:
3331                 request.setCachePolicy(ReloadIgnoringCacheData);
3332                 break;
3333             case FrameLoadTypeBack:
3334             case FrameLoadTypeForward:
3335             case FrameLoadTypeIndexedBackForward:
3336                 // If the first load within a frame is a navigation within a back/forward list that was attached 
3337                 // without any of the items being loaded then we should use the default caching policy (<rdar://problem/8131355>).
3338                 if (m_stateMachine.committedFirstRealDocumentLoad() && !itemURL.protocolIs("https"))
3339                     request.setCachePolicy(ReturnCacheDataElseLoad);
3340                 break;
3341             case FrameLoadTypeStandard:
3342             case FrameLoadTypeRedirectWithLockedBackForwardList:
3343                 break;
3344             case FrameLoadTypeSame:
3345             default:
3346                 ASSERT_NOT_REACHED();
3347         }
3348
3349         action = NavigationAction(itemOriginalURL, loadType, false);
3350     }
3351     
3352     if (!addedExtraFields)
3353         addExtraFieldsToRequest(request, m_loadType, true, formData);
3354
3355     loadWithNavigationAction(request, action, false, loadType, 0);
3356 }
3357
3358 // Loads content into this frame, as specified by history item
3359 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
3360 {
3361     HistoryItem* currentItem = history()->currentItem();
3362     bool sameDocumentNavigation = currentItem && item->shouldDoSameDocumentNavigationTo(currentItem);
3363
3364     if (sameDocumentNavigation)
3365         loadSameDocumentItem(item);
3366     else
3367         loadDifferentDocumentItem(item, loadType);
3368 }
3369
3370 void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
3371 {
3372     m_client->setMainDocumentError(loader, error);
3373 }
3374
3375 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError&)
3376 {
3377     loader->setPrimaryLoadComplete(true);
3378     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
3379     checkCompleted();
3380     if (m_frame->page())
3381         checkLoadComplete();
3382 }
3383
3384 void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete)
3385 {
3386     activeDocumentLoader()->mainReceivedError(error, isComplete);
3387 }
3388
3389 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3390 {
3391     ResourceError error = m_client->cancelledError(request);
3392     error.setIsCancellation(true);
3393     return error;
3394 }
3395
3396 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
3397 {
3398     return m_client->blockedError(request);
3399 }
3400
3401 ResourceError FrameLoader::cannotShowURLError(const ResourceRequest& request) const
3402 {
3403     return m_client->cannotShowURLError(request);
3404 }
3405
3406 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request) const
3407 {
3408     return m_client->interruptForPolicyChangeError(request);
3409 }
3410
3411 ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const
3412 {
3413     return m_client->fileDoesNotExistError(response);    
3414 }
3415
3416 bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader)
3417 {
3418     return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier());
3419 }
3420
3421 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
3422 bool FrameLoader::canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace)
3423 {
3424     return m_client->canAuthenticateAgainstProtectionSpace(loader->documentLoader(), loader->identifier(), protectionSpace);
3425 }
3426 #endif
3427
3428 void FrameLoader::setTitle(const StringWithDirection& title)
3429 {
3430     documentLoader()->setTitle(title);
3431 }
3432
3433 void FrameLoader::setIconURL(const IconURL& iconURL)
3434 {
3435     documentLoader()->setIconURL(iconURL);
3436 }
3437
3438 KURL FrameLoader::originalRequestURL() const
3439 {
3440     return activeDocumentLoader()->originalRequest().url();
3441 }
3442
3443 String FrameLoader::referrer() const
3444 {
3445     return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
3446 }
3447
3448 void FrameLoader::dispatchDocumentElementAvailable()
3449 {
3450     m_frame->injectUserScripts(InjectAtDocumentStart);
3451     m_client->documentElementAvailable();
3452 }
3453
3454 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
3455 {
3456     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript))
3457         return;
3458
3459     Vector<DOMWrapperWorld*> worlds;
3460     ScriptController::getAllWorlds(worlds);
3461     for (size_t i = 0; i < worlds.size(); ++i)
3462         dispatchDidClearWindowObjectInWorld(worlds[i]);
3463 }
3464
3465 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
3466 {
3467     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script()->existingWindowShell(world))
3468         return;
3469
3470     m_client->dispatchDidClearWindowObjectInWorld(world);
3471
3472 #if ENABLE(INSPECTOR)
3473     if (Page* page = m_frame->page())
3474         page->inspectorController()->didClearWindowObjectInWorld(m_frame, world);
3475 #endif
3476
3477     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
3478 }
3479
3480 void FrameLoader::updateSandboxFlags()
3481 {
3482     SandboxFlags flags = m_forcedSandboxFlags;
3483     if (Frame* parentFrame = m_frame->tree()->parent())
3484         flags |= parentFrame->loader()->sandboxFlags();
3485     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
3486         flags |= ownerElement->sandboxFlags();
3487
3488     if (m_sandboxFlags == flags)
3489         return;
3490
3491     m_sandboxFlags = flags;
3492
3493     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
3494         child->loader()->updateSandboxFlags();
3495 }
3496
3497 void FrameLoader::didChangeTitle(DocumentLoader* loader)
3498 {
3499     m_client->didChangeTitle(loader);
3500
3501     if (loader == m_documentLoader) {
3502         // Must update the entries in the back-forward list too.
3503         history()->setCurrentItemTitle(loader->title());
3504         // This must go through the WebFrame because it has the right notion of the current b/f item.
3505         m_client->setTitle(loader->title(), loader->urlForHistory());
3506         m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
3507         m_client->dispatchDidReceiveTitle(loader->title());
3508     }
3509 }
3510
3511 void FrameLoader::didChangeIcons(DocumentLoader* loader, IconType type)
3512 {
3513     if (loader == m_documentLoader)
3514         m_client->dispatchDidChangeIcons(type);
3515 }
3516
3517 void FrameLoader::dispatchDidCommitLoad()
3518 {
3519     if (m_stateMachine.creatingInitialEmptyDocument())
3520         return;
3521
3522     m_client->dispatchDidCommitLoad();
3523
3524     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
3525 }
3526
3527 void FrameLoader::tellClientAboutPastMemoryCacheLoads()
3528 {
3529     ASSERT(m_frame->page());
3530     ASSERT(m_frame->page()->areMemoryCacheClientCallsEnabled());
3531
3532     if (!m_documentLoader)
3533         return;
3534
3535     Vector<String> pastLoads;
3536     m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
3537
3538     size_t size = pastLoads.size();
3539     for (size_t i = 0; i < size; ++i) {
3540         CachedResource* resource = memoryCache()->resourceForURL(KURL(ParsedURLString, pastLoads[i]));
3541
3542         // FIXME: These loads, loaded from cache, but now gone from the cache by the time
3543         // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
3544         // Consider if there's some efficient way of remembering enough to deliver this client call.
3545         // We have the URL, but not the rest of the response or the length.
3546         if (!resource)
3547             continue;
3548
3549         ResourceRequest request(resource->url());
3550         m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
3551     }
3552 }
3553
3554 NetworkingContext* FrameLoader::networkingContext() const
3555 {
3556     return m_networkingContext.get();
3557 }
3558
3559 bool FrameLoaderClient::hasHTMLView() const
3560 {
3561     return true;
3562 }
3563
3564 Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
3565 {
3566     ASSERT(!features.dialog || request.frameName().isEmpty());
3567
3568     if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
3569         Frame* frame = lookupFrame->tree()->find(request.frameName());
3570         if (frame && openerFrame->loader()->shouldAllowNavigation(frame)) {
3571             if (Page* page = frame->page())
3572                 page->chrome()->focus();
3573             created = false;
3574             return frame;
3575         }
3576     }
3577
3578     // Sandboxed frames cannot open new auxiliary browsing contexts.
3579     if (isDocumentSandboxed(openerFrame, SandboxNavigation))
3580         return 0;
3581
3582     // FIXME: Setting the referrer should be the caller's responsibility.
3583     FrameLoadRequest requestWithReferrer = request;
3584     requestWithReferrer.resourceRequest().setHTTPReferrer(openerFrame->loader()->outgoingReferrer());
3585     FrameLoader::addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), openerFrame->loader()->outgoingOrigin());
3586
3587     Page* oldPage = openerFrame->page();
3588     if (!oldPage)
3589         return 0;
3590
3591     NavigationAction action;
3592     Page* page = oldPage->chrome()->createWindow(openerFrame, requestWithReferrer, features, action);
3593     if (!page)
3594         return 0;
3595
3596     Frame* frame = page->mainFrame();
3597     if (request.frameName() != "_blank")
3598         frame->tree()->setName(request.frameName());
3599
3600     page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
3601     page->chrome()->setStatusbarVisible(features.statusBarVisible);
3602     page->chrome()->setScrollbarsVisible(features.scrollbarsVisible);
3603     page->chrome()->setMenubarVisible(features.menuBarVisible);
3604     page->chrome()->setResizable(features.resizable);
3605
3606     // 'x' and 'y' specify the location of the window, while 'width' and 'height'
3607     // specify the size of the page. We can only resize the window, so
3608     // adjust for the difference between the window size and the page size.
3609
3610     FloatRect windowRect = page->chrome()->windowRect();
3611     FloatSize pageSize = page->chrome()->pageRect().size();
3612     if (features.xSet)
3613         windowRect.setX(features.x);
3614     if (features.ySet)
3615         windowRect.setY(features.y);
3616     if (features.widthSet)
3617         windowRect.setWidth(features.width + (windowRect.width() - pageSize.width()));
3618     if (features.heightSet)
3619         windowRect.setHeight(features.height + (windowRect.height() - pageSize.height()));
3620     page->chrome()->setWindowRect(windowRect);
3621
3622     page->chrome()->show();
3623
3624     created = true;
3625     return frame;
3626 }
3627
3628 } // namespace WebCore