Fix ScopedPageLoadDeferrer to work with pages that have remote main frames.

BUG=628942

Review-Url: https://codereview.chromium.org/2155393002
Cr-Commit-Position: refs/heads/master@{#406632}
diff --git a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
index 9ef36dc..8a41b18 100644
--- a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
+++ b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
@@ -32,18 +32,15 @@
 
 ScopedPageLoadDeferrer::ScopedPageLoadDeferrer(Page* exclusion)
 {
-    for (const Page* page : Page::ordinaryPages()) {
+    for (Page* page : Page::ordinaryPages()) {
         if (page == exclusion || page->defersLoading())
             continue;
-
-        if (!page->mainFrame()->isLocalFrame())
-            continue;
-
-        m_deferredFrames.append(page->deprecatedLocalMainFrame());
+        m_deferredPages.append(page);
 
         // Ensure that we notify the client if the initial empty document is accessed before
         // showing anything modal, to prevent spoofs while the modal window or sheet is visible.
-        page->deprecatedLocalMainFrame()->loader().notifyIfInitialDocumentAccessed();
+        if (page->mainFrame()->isLocalFrame())
+            page->deprecatedLocalMainFrame()->loader().notifyIfInitialDocumentAccessed();
     }
 
     setDefersLoading(true);
@@ -58,10 +55,9 @@
 
 void ScopedPageLoadDeferrer::setDefersLoading(bool isDeferred)
 {
-    for (const auto& frame : m_deferredFrames) {
-        if (Page* page = frame->page())
-            page->setDefersLoading(isDeferred);
-    }
+
+    for (const auto& page : m_deferredPages)
+        page->setDefersLoading(isDeferred);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.h b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.h
index a129e0e..f0c66475 100644
--- a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.h
+++ b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.h
@@ -40,7 +40,7 @@
 private:
     void setDefersLoading(bool);
 
-    Vector<Persistent<LocalFrame>, 16> m_deferredFrames;
+    Vector<Persistent<Page>, 16> m_deferredPages;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 2d6f561d..142b51a 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -71,6 +71,7 @@
 #include "core/loader/FrameLoadRequest.h"
 #include "core/loader/ThreadableLoader.h"
 #include "core/page/Page.h"
+#include "core/page/ScopedPageLoadDeferrer.h"
 #include "core/paint/PaintLayer.h"
 #include "core/testing/NullExecutionContext.h"
 #include "modules/mediastream/MediaStream.h"
@@ -8171,6 +8172,46 @@
     view->close();
 }
 
+// See https://crbug.com/628942.
+TEST_P(ParameterizedWebFrameTest, DeferredPageLoadWithRemoteMainFrame)
+{
+    // Prepare a page with a remote main frame.
+    FrameTestHelpers::TestWebViewClient viewClient;
+    FrameTestHelpers::TestWebRemoteFrameClient remoteClient;
+    WebView* view = WebView::create(&viewClient, WebPageVisibilityStateVisible);
+    view->setMainFrame(remoteClient.frame());
+    WebRemoteFrame* remoteRoot = view->mainFrame()->toWebRemoteFrame();
+    remoteRoot->setReplicatedOrigin(SecurityOrigin::createUnique());
+
+    // Check that ScopedPageLoadDeferrer properly triggers deferred loading for
+    // the current Page.
+    Page* page = remoteRoot->toImplBase()->frame()->page();
+    EXPECT_FALSE(page->defersLoading());
+    {
+        ScopedPageLoadDeferrer deferrer;
+        EXPECT_TRUE(page->defersLoading());
+    }
+    EXPECT_FALSE(page->defersLoading());
+
+    // Repeat this for a page with a local child frame, and ensure that the
+    // child frame's loads are also deferred.
+    WebLocalFrame* webLocalChild = FrameTestHelpers::createLocalChild(remoteRoot);
+    registerMockedHttpURLLoad("foo.html");
+    FrameTestHelpers::loadFrame(webLocalChild, m_baseURL + "foo.html");
+    LocalFrame* localChild = toWebLocalFrameImpl(webLocalChild)->frame();
+    EXPECT_FALSE(page->defersLoading());
+    EXPECT_FALSE(localChild->document()->fetcher()->defersLoading());
+    {
+        ScopedPageLoadDeferrer deferrer;
+        EXPECT_TRUE(page->defersLoading());
+        EXPECT_TRUE(localChild->document()->fetcher()->defersLoading());
+    }
+    EXPECT_FALSE(page->defersLoading());
+    EXPECT_FALSE(localChild->document()->fetcher()->defersLoading());
+
+    view->close();
+}
+
 class OverscrollWebViewClient : public FrameTestHelpers::TestWebViewClient {
 public:
     MOCK_METHOD4(didOverscroll, void(const WebFloatSize&, const WebFloatSize&, const WebFloatPoint&, const WebFloatSize&));