Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Unified Diff: content/browser/frame_host/navigation_controller_impl_browsertest.cc

Issue 2366693006: Don't show dialogs from swapped out frames. (Closed)
Patch Set: now thread safe Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/browser/frame_host/render_frame_host_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/frame_host/navigation_controller_impl_browsertest.cc
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 405e65008a2fc1db15c2f90f86afeeb48db0a749..e88f507f5769faa5bf3ec34f341fde320a2ffb90 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -27,6 +27,7 @@
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
@@ -5968,7 +5969,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
}
-// A BrowserMessageFilter that delays FrameHostMsg_DidCommitProvisionaLoad IPC
+// A BrowserMessageFilter that delays FrameHostMsg_DidCommitProvisionalLoad IPC
// message for a specified URL, navigates the WebContents back and then
// processes the commit message.
class GoBackAndCommitFilter : public BrowserMessageFilter {
@@ -5996,7 +5997,7 @@ class GoBackAndCommitFilter : public BrowserMessageFilter {
if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID)
return false;
- // Parse the IPC message so the URL can be checked agains the expected one.
+ // Parse the IPC message so the URL can be checked against the expected one.
base::PickleIterator iter(message);
FrameHostMsg_DidCommitProvisionalLoad_Params validated_params;
if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read(
@@ -6137,4 +6138,100 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_FALSE(favicon_status3.valid);
}
+namespace {
+
+// A BrowserMessageFilter that delays the FrameHostMsg_RunJavaScriptMessage IPC
+// message until a commit happens on a given WebContents. This allows testing a
+// race condition.
+class AllowDialogIPCOnCommitFilter : public BrowserMessageFilter,
+ public WebContentsDelegate {
+ public:
+ AllowDialogIPCOnCommitFilter(WebContents* web_contents)
+ : BrowserMessageFilter(FrameMsgStart),
+ render_frame_host_(web_contents->GetMainFrame()) {
+ web_contents_observer_.Observe(web_contents);
+ }
+
+ protected:
+ ~AllowDialogIPCOnCommitFilter() override {}
+
+ private:
+ // BrowserMessageFilter:
+ bool OnMessageReceived(const IPC::Message& message) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (message.type() != FrameHostMsg_RunJavaScriptMessage::ID)
+ return false;
+
+ // Suspend the message.
+ web_contents_observer_.SetCallback(
+ base::Bind(&RenderFrameHost::OnMessageReceived,
+ base::Unretained(render_frame_host_), message));
+ return true;
+ }
+
+ // WebContentsDelegate:
+ JavaScriptDialogManager* GetJavaScriptDialogManager(
+ WebContents* source) override {
+ CHECK(false);
+ return nullptr; // agh compiler
+ }
+
+ // Separate because WebContentsObserver and BrowserMessageFilter each have an
+ // OnMessageReceived function; this is the simplest way to disambiguate.
+ class : public WebContentsObserver {
Charlie Reis 2016/09/28 17:14:16 Wow, I don't know that I've seen anonymous inner c
Avi (use Gerrit) 2016/09/28 17:46:16 Thanks! I'm not trying to be clever; this seems to
+ public:
+ using Callback = base::Callback<bool()>;
+
+ using WebContentsObserver::Observe;
Charlie Reis 2016/09/28 17:14:16 Is this needed? Seems like we should be able to r
Avi (use Gerrit) 2016/09/28 17:46:16 No, it's protected, and even though (I think) ther
+
+ void SetCallback(Callback callback) { callback_ = callback; }
+
+ private:
+ void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Resume the message.
+ callback_.Run();
+ }
+
+ Callback callback_;
+ } web_contents_observer_;
+
+ RenderFrameHost* render_frame_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllowDialogIPCOnCommitFilter);
+};
+
+} // namespace
+
+// Check that swapped out frames cannot spawn JavaScript dialogs.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ NoDialogsFromSwappedOutFrames) {
+ // Start on a normal page.
+ GURL url1 = embedded_test_server()->GetURL(
+ "/navigation_controller/beforeunload_dialog.html");
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+
+ // Add a filter to allow us to force an IPC race.
+ WebContents* web_contents = shell()->web_contents();
+ scoped_refptr<AllowDialogIPCOnCommitFilter> filter =
+ new AllowDialogIPCOnCommitFilter(web_contents);
+ web_contents->SetDelegate(filter.get());
+ web_contents->GetMainFrame()->GetProcess()->AddFilter(filter.get());
+
+ // Use a chrome:// url to force the second page to be in a different process.
+ GURL url2(std::string(kChromeUIScheme) + url::kStandardSchemeSeparator +
+ kChromeUIGpuHost);
+ EXPECT_TRUE(NavigateToURL(shell(), url2));
+
+ // What happens now is that attempting to unload the first page will trigger a
+ // JavaScript alert but allow navigation. The alert IPC will be suspended by
+ // the message filter. The commit of the second page will unblock the IPC. If
+ // the dialog IPC is allowed to spawn a dialog, the call by the WebContents to
+ // its delegate to get the JavaScriptDialogManager will cause a CHECK and the
+ // test will fail.
+}
+
} // namespace content
« no previous file with comments | « no previous file | content/browser/frame_host/render_frame_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698