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