Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / loader / NavigationScheduler.cpp
index 295cdfc..13e2a8f 100644 (file)
 #include "config.h"
 #include "core/loader/NavigationScheduler.h"
 
-#include "bindings/v8/ScriptController.h"
+#include "bindings/core/v8/ScriptController.h"
 #include "core/events/Event.h"
+#include "core/fetch/ResourceLoaderOptions.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/html/HTMLFormElement.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
 #include "core/loader/FrameLoaderStateMachine.h"
-#include "core/frame/Frame.h"
 #include "core/page/BackForwardClient.h"
 #include "core/page/Page.h"
+#include "platform/SharedBuffer.h"
 #include "platform/UserGestureIndicator.h"
 #include "wtf/CurrentTime.h"
 
-namespace WebCore {
+namespace blink {
 
 unsigned NavigationDisablerForBeforeUnload::s_navigationDisableCount = 0;
 
@@ -67,9 +70,9 @@ public:
     }
     virtual ~ScheduledNavigation() { }
 
-    virtual void fire(Frame*) = 0;
+    virtual void fire(LocalFrame*) = 0;
 
-    virtual bool shouldStartTimer(Frame*) { return true; }
+    virtual bool shouldStartTimer(LocalFrame*) { return true; }
 
     double delay() const { return m_delay; }
     bool lockBackForwardList() const { return m_lockBackForwardList; }
@@ -81,8 +84,6 @@ public:
         return adoptPtr(new UserGestureIndicator(DefinitelyNotProcessingUserGesture));
     }
 
-    virtual bool isForm() const { return false; }
-
 protected:
     void clearUserGesture() { m_wasUserGesture = false; }
 
@@ -101,13 +102,16 @@ protected:
         , m_originDocument(originDocument)
         , m_url(url)
         , m_referrer(referrer)
+        , m_shouldCheckMainWorldContentSecurityPolicy(CheckContentSecurityPolicy)
     {
+        if (ContentSecurityPolicy::shouldBypassMainWorld(originDocument))
+            m_shouldCheckMainWorldContentSecurityPolicy = DoNotCheckContentSecurityPolicy;
     }
 
-    virtual void fire(Frame* frame) OVERRIDE
+    virtual void fire(LocalFrame* frame) OVERRIDE
     {
         OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
-        FrameLoadRequest request(m_originDocument.get(), ResourceRequest(KURL(ParsedURLString, m_url), m_referrer), "_self");
+        FrameLoadRequest request(m_originDocument.get(), ResourceRequest(KURL(ParsedURLString, m_url), m_referrer), "_self", m_shouldCheckMainWorldContentSecurityPolicy);
         request.setLockBackForwardList(lockBackForwardList());
         request.setClientRedirect(ClientRedirect);
         frame->loader().load(request);
@@ -118,9 +122,10 @@ protected:
     const Referrer& referrer() const { return m_referrer; }
 
 private:
-    RefPtr<Document> m_originDocument;
+    RefPtrWillBePersistent<Document> m_originDocument;
     String m_url;
     Referrer m_referrer;
+    ContentSecurityPolicyCheck m_shouldCheckMainWorldContentSecurityPolicy;
 };
 
 class ScheduledRedirect FINAL : public ScheduledURLNavigation {
@@ -131,9 +136,9 @@ public:
         clearUserGesture();
     }
 
-    virtual bool shouldStartTimer(Frame* frame) OVERRIDE { return frame->loader().allAncestorsAreComplete(); }
+    virtual bool shouldStartTimer(LocalFrame* frame) OVERRIDE { return frame->loader().allAncestorsAreComplete(); }
 
-    virtual void fire(Frame* frame) OVERRIDE
+    virtual void fire(LocalFrame* frame) OVERRIDE
     {
         OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
         FrameLoadRequest request(originDocument(), ResourceRequest(KURL(ParsedURLString, url()), referrer()), "_self");
@@ -151,18 +156,33 @@ public:
         : ScheduledURLNavigation(0.0, originDocument, url, referrer, lockBackForwardList, true) { }
 };
 
-class ScheduledRefresh FINAL : public ScheduledURLNavigation {
+class ScheduledReload FINAL : public ScheduledNavigation {
+public:
+    ScheduledReload()
+        : ScheduledNavigation(0.0, true, true)
+    {
+    }
+
+    virtual void fire(LocalFrame* frame) OVERRIDE
+    {
+        OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
+        frame->loader().reload(NormalReload, KURL(), nullAtom, ClientRedirect);
+    }
+};
+
+class ScheduledPageBlock FINAL : public ScheduledURLNavigation {
 public:
-    ScheduledRefresh(Document* originDocument, const String& url, const Referrer& referrer)
+    ScheduledPageBlock(Document* originDocument, const String& url, const Referrer& referrer)
         : ScheduledURLNavigation(0.0, originDocument, url, referrer, true, true)
     {
     }
 
-    virtual void fire(Frame* frame) OVERRIDE
+    virtual void fire(LocalFrame* frame) OVERRIDE
     {
         OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
-        FrameLoadRequest request(originDocument(), ResourceRequest(KURL(ParsedURLString, url()), referrer(), ReloadIgnoringCacheData), "_self");
-        request.setLockBackForwardList(lockBackForwardList());
+        SubstituteData substituteData(SharedBuffer::create(), "text/plain", "UTF-8", KURL(), ForceSynchronousLoad);
+        FrameLoadRequest request(originDocument(), ResourceRequest(KURL(ParsedURLString, url()), referrer(), ReloadIgnoringCacheData), substituteData);
+        request.setLockBackForwardList(true);
         request.setClientRedirect(ClientRedirect);
         frame->loader().load(request);
     }
@@ -176,21 +196,12 @@ public:
     {
     }
 
-    virtual void fire(Frame* frame) OVERRIDE
+    virtual void fire(LocalFrame* frame) OVERRIDE
     {
         OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
-
-        if (!m_historySteps) {
-            FrameLoadRequest frameRequest(frame->document(), ResourceRequest(frame->document()->url()));
-            frameRequest.setLockBackForwardList(lockBackForwardList());
-            // Special case for go(0) from a frame -> reload only the frame
-            // To follow Firefox and IE's behavior, history reload can only navigate the self frame.
-            frame->loader().load(frameRequest);
-            return;
-        }
         // go(i!=0) from a frame navigates into the history of the frame only,
         // in both IE and NS (but not in Mozilla). We can't easily do that.
-        frame->page()->mainFrame()->loader().client()->navigateBackForward(m_historySteps);
+        frame->page()->deprecatedLocalMainFrame()->loader().client()->navigateBackForward(m_historySteps);
     }
 
 private:
@@ -199,14 +210,14 @@ private:
 
 class ScheduledFormSubmission FINAL : public ScheduledNavigation {
 public:
-    ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBackForwardList)
+    ScheduledFormSubmission(PassRefPtrWillBeRawPtr<FormSubmission> submission, bool lockBackForwardList)
         : ScheduledNavigation(0, lockBackForwardList, true)
         , m_submission(submission)
     {
         ASSERT(m_submission->state());
     }
 
-    virtual void fire(Frame* frame) OVERRIDE
+    virtual void fire(LocalFrame* frame) OVERRIDE
     {
         OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator();
         FrameLoadRequest frameRequest(m_submission->state()->sourceDocument());
@@ -217,14 +228,11 @@ public:
         frame->loader().load(frameRequest);
     }
 
-    virtual bool isForm() const OVERRIDE { return true; }
-    FormSubmission* submission() const { return m_submission.get(); }
-
 private:
-    RefPtr<FormSubmission> m_submission;
+    RefPtrWillBePersistent<FormSubmission> m_submission;
 };
 
-NavigationScheduler::NavigationScheduler(Frame* frame)
+NavigationScheduler::NavigationScheduler(LocalFrame* frame)
     : m_frame(frame)
     , m_timer(this, &NavigationScheduler::timerFired)
 {
@@ -239,14 +247,6 @@ bool NavigationScheduler::locationChangePending()
     return m_redirect && m_redirect->isLocationChange();
 }
 
-void NavigationScheduler::clear()
-{
-    if (m_timer.isActive())
-        InspectorInstrumentation::frameClearedScheduledNavigation(m_frame);
-    m_timer.stop();
-    m_redirect.clear();
-}
-
 inline bool NavigationScheduler::shouldScheduleNavigation() const
 {
     return m_frame->page();
@@ -271,7 +271,7 @@ void NavigationScheduler::scheduleRedirect(double delay, const String& url)
         schedule(adoptPtr(new ScheduledRedirect(delay, m_frame->document(), url, delay <= 1)));
 }
 
-bool NavigationScheduler::mustLockBackForwardList(Frame* targetFrame)
+bool NavigationScheduler::mustLockBackForwardList(LocalFrame* targetFrame)
 {
     // Non-user navigation before the page has finished firing onload should not create a new back/forward item.
     // See https://webkit.org/b/42861 for the original motivation for this.
@@ -289,7 +289,8 @@ bool NavigationScheduler::mustLockBackForwardList(Frame* targetFrame)
     // Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item.
     // The definition of "during load" is any time before all handlers for the load event have been run.
     // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this.
-    return targetFrame->tree().parent() && !targetFrame->tree().parent()->loader().allAncestorsAreComplete();
+    Frame* parentFrame = targetFrame->tree().parent();
+    return parentFrame && parentFrame->isLocalFrame() && !toLocalFrame(parentFrame)->loader().allAncestorsAreComplete();
 }
 
 void NavigationScheduler::scheduleLocationChange(Document* originDocument, const String& url, const Referrer& referrer, bool lockBackForwardList)
@@ -320,21 +321,26 @@ void NavigationScheduler::scheduleLocationChange(Document* originDocument, const
     schedule(adoptPtr(new ScheduledLocationChange(originDocument, url, referrer, lockBackForwardList)));
 }
 
-void NavigationScheduler::scheduleFormSubmission(PassRefPtr<FormSubmission> submission)
+void NavigationScheduler::schedulePageBlock(Document* originDocument, const Referrer& referrer)
+{
+    ASSERT(m_frame->page());
+    const KURL& url = m_frame->document()->url();
+    schedule(adoptPtr(new ScheduledPageBlock(originDocument, url, referrer)));
+}
+
+void NavigationScheduler::scheduleFormSubmission(PassRefPtrWillBeRawPtr<FormSubmission> submission)
 {
     ASSERT(m_frame->page());
     schedule(adoptPtr(new ScheduledFormSubmission(submission, mustLockBackForwardList(m_frame))));
 }
 
-void NavigationScheduler::scheduleRefresh()
+void NavigationScheduler::scheduleReload()
 {
     if (!shouldScheduleNavigation())
         return;
-    const KURL& url = m_frame->document()->url();
-    if (url.isEmpty())
+    if (m_frame->document()->url().isEmpty())
         return;
-
-    schedule(adoptPtr(new ScheduledRefresh(m_frame->document(), url.string(), Referrer(m_frame->document()->outgoingReferrer(), m_frame->document()->referrerPolicy()))));
+    schedule(adoptPtr(new ScheduledReload));
 }
 
 void NavigationScheduler::scheduleHistoryNavigation(int steps)
@@ -351,7 +357,10 @@ void NavigationScheduler::scheduleHistoryNavigation(int steps)
     }
 
     // In all other cases, schedule the history traversal to occur asynchronously.
-    schedule(adoptPtr(new ScheduledHistoryNavigation(steps)));
+    if (steps)
+        schedule(adoptPtr(new ScheduledHistoryNavigation(steps)));
+    else
+        schedule(adoptPtr(new ScheduledReload));
 }
 
 void NavigationScheduler::timerFired(Timer<NavigationScheduler>*)
@@ -363,7 +372,7 @@ void NavigationScheduler::timerFired(Timer<NavigationScheduler>*)
         return;
     }
 
-    RefPtr<Frame> protect(m_frame);
+    RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
 
     OwnPtr<ScheduledNavigation> redirect(m_redirect.release());
     redirect->fire(m_frame);
@@ -373,6 +382,18 @@ void NavigationScheduler::timerFired(Timer<NavigationScheduler>*)
 void NavigationScheduler::schedule(PassOwnPtr<ScheduledNavigation> redirect)
 {
     ASSERT(m_frame->page());
+
+    // In a back/forward navigation, we sometimes restore history state to iframes, even though the state was generated
+    // dynamically and JS will try to put something different in the iframe. In this case, we will load stale things
+    // and/or confuse the JS when it shortly thereafter tries to schedule a location change. Let the JS have its way.
+    // FIXME: This check seems out of place.
+    if (!m_frame->loader().stateMachine()->committedFirstRealDocumentLoad() && m_frame->loader().provisionalDocumentLoader()) {
+        RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
+        m_frame->loader().provisionalDocumentLoader()->stopLoading();
+        if (!m_frame->host())
+            return;
+    }
+
     cancel();
     m_redirect = redirect;
     startTimer();
@@ -389,7 +410,7 @@ void NavigationScheduler::startTimer()
     if (!m_redirect->shouldStartTimer(m_frame))
         return;
 
-    m_timer.startOneShot(m_redirect->delay());
+    m_timer.startOneShot(m_redirect->delay(), FROM_HERE);
     InspectorInstrumentation::frameScheduledNavigation(m_frame, m_redirect->delay());
 }
 
@@ -401,4 +422,9 @@ void NavigationScheduler::cancel()
     m_redirect.clear();
 }
 
-} // namespace WebCore
+void NavigationScheduler::trace(Visitor* visitor)
+{
+    visitor->trace(m_frame);
+}
+
+} // namespace blink