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

Side by Side 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, 2 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/frame_host/navigation_controller_impl.h" 5 #include "content/browser/frame_host/navigation_controller_impl.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "content/browser/frame_host/frame_navigation_entry.h" 15 #include "content/browser/frame_host/frame_navigation_entry.h"
16 #include "content/browser/frame_host/frame_tree.h" 16 #include "content/browser/frame_host/frame_tree.h"
17 #include "content/browser/frame_host/navigation_entry_impl.h" 17 #include "content/browser/frame_host/navigation_entry_impl.h"
18 #include "content/browser/loader/resource_dispatcher_host_impl.h" 18 #include "content/browser/loader/resource_dispatcher_host_impl.h"
19 #include "content/browser/web_contents/web_contents_impl.h" 19 #include "content/browser/web_contents/web_contents_impl.h"
20 #include "content/common/frame_messages.h" 20 #include "content/common/frame_messages.h"
21 #include "content/common/page_state_serialization.h" 21 #include "content/common/page_state_serialization.h"
22 #include "content/common/site_isolation_policy.h" 22 #include "content/common/site_isolation_policy.h"
23 #include "content/public/browser/navigation_handle.h" 23 #include "content/public/browser/navigation_handle.h"
24 #include "content/public/browser/render_view_host.h" 24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/resource_controller.h" 25 #include "content/public/browser/resource_controller.h"
26 #include "content/public/browser/resource_dispatcher_host.h" 26 #include "content/public/browser/resource_dispatcher_host.h"
27 #include "content/public/browser/resource_dispatcher_host_delegate.h" 27 #include "content/public/browser/resource_dispatcher_host_delegate.h"
28 #include "content/public/browser/resource_throttle.h" 28 #include "content/public/browser/resource_throttle.h"
29 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
30 #include "content/public/browser/web_contents_delegate.h"
30 #include "content/public/browser/web_contents_observer.h" 31 #include "content/public/browser/web_contents_observer.h"
31 #include "content/public/common/bindings_policy.h" 32 #include "content/public/common/bindings_policy.h"
32 #include "content/public/common/browser_side_navigation_policy.h" 33 #include "content/public/common/browser_side_navigation_policy.h"
33 #include "content/public/common/renderer_preferences.h" 34 #include "content/public/common/renderer_preferences.h"
34 #include "content/public/common/url_constants.h" 35 #include "content/public/common/url_constants.h"
35 #include "content/public/test/browser_test_utils.h" 36 #include "content/public/test/browser_test_utils.h"
36 #include "content/public/test/content_browser_test.h" 37 #include "content/public/test/content_browser_test.h"
37 #include "content/public/test/content_browser_test_utils.h" 38 #include "content/public/test/content_browser_test_utils.h"
38 #include "content/public/test/test_navigation_observer.h" 39 #include "content/public/test/test_navigation_observer.h"
39 #include "content/public/test/test_utils.h" 40 #include "content/public/test/test_utils.h"
(...skipping 5921 matching lines...) Expand 10 before | Expand all | Expand 10 after
5961 } 5962 }
5962 5963
5963 // Verify the expected origin through JavaScript. It also has the additional 5964 // Verify the expected origin through JavaScript. It also has the additional
5964 // verification of the process also being still alive. 5965 // verification of the process also being still alive.
5965 std::string origin; 5966 std::string origin;
5966 EXPECT_TRUE(ExecuteScriptAndExtractString( 5967 EXPECT_TRUE(ExecuteScriptAndExtractString(
5967 web_contents, "domAutomationController.send(document.origin)", &origin)); 5968 web_contents, "domAutomationController.send(document.origin)", &origin));
5968 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); 5969 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
5969 } 5970 }
5970 5971
5971 // A BrowserMessageFilter that delays FrameHostMsg_DidCommitProvisionaLoad IPC 5972 // A BrowserMessageFilter that delays FrameHostMsg_DidCommitProvisionalLoad IPC
5972 // message for a specified URL, navigates the WebContents back and then 5973 // message for a specified URL, navigates the WebContents back and then
5973 // processes the commit message. 5974 // processes the commit message.
5974 class GoBackAndCommitFilter : public BrowserMessageFilter { 5975 class GoBackAndCommitFilter : public BrowserMessageFilter {
5975 public: 5976 public:
5976 GoBackAndCommitFilter(const GURL& url, WebContentsImpl* web_contents) 5977 GoBackAndCommitFilter(const GURL& url, WebContentsImpl* web_contents)
5977 : BrowserMessageFilter(FrameMsgStart), 5978 : BrowserMessageFilter(FrameMsgStart),
5978 url_(url), 5979 url_(url),
5979 web_contents_(web_contents) {} 5980 web_contents_(web_contents) {}
5980 5981
5981 protected: 5982 protected:
5982 ~GoBackAndCommitFilter() override {} 5983 ~GoBackAndCommitFilter() override {}
5983 5984
5984 private: 5985 private:
5985 static void NavigateBackAndCommit(const IPC::Message& message, 5986 static void NavigateBackAndCommit(const IPC::Message& message,
5986 WebContentsImpl* web_contents) { 5987 WebContentsImpl* web_contents) {
5987 web_contents->GetController().GoBack(); 5988 web_contents->GetController().GoBack();
5988 5989
5989 RenderFrameHostImpl* rfh = web_contents->GetMainFrame(); 5990 RenderFrameHostImpl* rfh = web_contents->GetMainFrame();
5990 DCHECK_EQ(rfh->routing_id(), message.routing_id()); 5991 DCHECK_EQ(rfh->routing_id(), message.routing_id());
5991 rfh->OnMessageReceived(message); 5992 rfh->OnMessageReceived(message);
5992 } 5993 }
5993 5994
5994 // BrowserMessageFilter: 5995 // BrowserMessageFilter:
5995 bool OnMessageReceived(const IPC::Message& message) override { 5996 bool OnMessageReceived(const IPC::Message& message) override {
5996 if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID) 5997 if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID)
5997 return false; 5998 return false;
5998 5999
5999 // Parse the IPC message so the URL can be checked agains the expected one. 6000 // Parse the IPC message so the URL can be checked against the expected one.
6000 base::PickleIterator iter(message); 6001 base::PickleIterator iter(message);
6001 FrameHostMsg_DidCommitProvisionalLoad_Params validated_params; 6002 FrameHostMsg_DidCommitProvisionalLoad_Params validated_params;
6002 if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read( 6003 if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read(
6003 &message, &iter, &validated_params)) { 6004 &message, &iter, &validated_params)) {
6004 return false; 6005 return false;
6005 } 6006 }
6006 6007
6007 // Only handle the message if the URLs are matching. 6008 // Only handle the message if the URLs are matching.
6008 if (validated_params.url != url_) 6009 if (validated_params.url != url_)
6009 return false; 6010 return false;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
6130 entry = controller.GetLastCommittedEntry(); 6131 entry = controller.GetLastCommittedEntry();
6131 content::FaviconStatus& favicon_status2 = entry->GetFavicon(); 6132 content::FaviconStatus& favicon_status2 = entry->GetFavicon();
6132 EXPECT_TRUE(favicon_status2.valid); 6133 EXPECT_TRUE(favicon_status2.valid);
6133 6134
6134 ASSERT_TRUE(RendererLocationReplace(shell(), GURL("data:text/html,page2"))); 6135 ASSERT_TRUE(RendererLocationReplace(shell(), GURL("data:text/html,page2")));
6135 entry = controller.GetLastCommittedEntry(); 6136 entry = controller.GetLastCommittedEntry();
6136 content::FaviconStatus& favicon_status3 = entry->GetFavicon(); 6137 content::FaviconStatus& favicon_status3 = entry->GetFavicon();
6137 EXPECT_FALSE(favicon_status3.valid); 6138 EXPECT_FALSE(favicon_status3.valid);
6138 } 6139 }
6139 6140
6141 namespace {
6142
6143 // A BrowserMessageFilter that delays the FrameHostMsg_RunJavaScriptMessage IPC
6144 // message until a commit happens on a given WebContents. This allows testing a
6145 // race condition.
6146 class AllowDialogIPCOnCommitFilter : public BrowserMessageFilter,
6147 public WebContentsDelegate {
6148 public:
6149 AllowDialogIPCOnCommitFilter(WebContents* web_contents)
6150 : BrowserMessageFilter(FrameMsgStart),
6151 render_frame_host_(web_contents->GetMainFrame()) {
6152 web_contents_observer_.Observe(web_contents);
6153 }
6154
6155 protected:
6156 ~AllowDialogIPCOnCommitFilter() override {}
6157
6158 private:
6159 // BrowserMessageFilter:
6160 bool OnMessageReceived(const IPC::Message& message) override {
6161 DCHECK_CURRENTLY_ON(BrowserThread::IO);
6162 if (message.type() != FrameHostMsg_RunJavaScriptMessage::ID)
6163 return false;
6164
6165 // Suspend the message.
6166 web_contents_observer_.SetCallback(
6167 base::Bind(&RenderFrameHost::OnMessageReceived,
6168 base::Unretained(render_frame_host_), message));
6169 return true;
6170 }
6171
6172 // WebContentsDelegate:
6173 JavaScriptDialogManager* GetJavaScriptDialogManager(
6174 WebContents* source) override {
6175 CHECK(false);
6176 return nullptr; // agh compiler
6177 }
6178
6179 // Separate because WebContentsObserver and BrowserMessageFilter each have an
6180 // OnMessageReceived function; this is the simplest way to disambiguate.
6181 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
6182 public:
6183 using Callback = base::Callback<bool()>;
6184
6185 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
6186
6187 void SetCallback(Callback callback) { callback_ = callback; }
6188
6189 private:
6190 void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
6191 const LoadCommittedDetails& details,
6192 const FrameNavigateParams& params) override {
6193 DCHECK_CURRENTLY_ON(BrowserThread::UI);
6194
6195 // Resume the message.
6196 callback_.Run();
6197 }
6198
6199 Callback callback_;
6200 } web_contents_observer_;
6201
6202 RenderFrameHost* render_frame_host_;
6203
6204 DISALLOW_COPY_AND_ASSIGN(AllowDialogIPCOnCommitFilter);
6205 };
6206
6207 } // namespace
6208
6209 // Check that swapped out frames cannot spawn JavaScript dialogs.
6210 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
6211 NoDialogsFromSwappedOutFrames) {
6212 // Start on a normal page.
6213 GURL url1 = embedded_test_server()->GetURL(
6214 "/navigation_controller/beforeunload_dialog.html");
6215 EXPECT_TRUE(NavigateToURL(shell(), url1));
6216
6217 // Add a filter to allow us to force an IPC race.
6218 WebContents* web_contents = shell()->web_contents();
6219 scoped_refptr<AllowDialogIPCOnCommitFilter> filter =
6220 new AllowDialogIPCOnCommitFilter(web_contents);
6221 web_contents->SetDelegate(filter.get());
6222 web_contents->GetMainFrame()->GetProcess()->AddFilter(filter.get());
6223
6224 // Use a chrome:// url to force the second page to be in a different process.
6225 GURL url2(std::string(kChromeUIScheme) + url::kStandardSchemeSeparator +
6226 kChromeUIGpuHost);
6227 EXPECT_TRUE(NavigateToURL(shell(), url2));
6228
6229 // What happens now is that attempting to unload the first page will trigger a
6230 // JavaScript alert but allow navigation. The alert IPC will be suspended by
6231 // the message filter. The commit of the second page will unblock the IPC. If
6232 // the dialog IPC is allowed to spawn a dialog, the call by the WebContents to
6233 // its delegate to get the JavaScriptDialogManager will cause a CHECK and the
6234 // test will fail.
6235 }
6236
6140 } // namespace content 6237 } // namespace content
OLDNEW
« 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