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