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

Unified Diff: content/browser/devtools/protocol/devtools_protocol_browsertest.cc

Issue 2132673002: Adding Navigation Throttles to DevTools (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove print Created 4 years, 5 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
Index: content/browser/devtools/protocol/devtools_protocol_browsertest.cc
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 858070b7014c8dde5409075cf9e990e16e8760d5..99f9ee59cb173a0cf1c4e581c0448b4a537e72b9 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -9,11 +9,14 @@
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/javascript_dialog_manager.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
@@ -24,10 +27,13 @@
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/codec/png_codec.h"
+using testing::ElementsAre;
+
namespace content {
namespace {
@@ -175,11 +181,83 @@ class DevToolsProtocolTest : public ContentBrowserTest,
RunMessageLoop();
}
+ struct ExpectedNavigation {
+ std::string url;
+ bool is_in_main_frame;
+ bool is_redirect;
+ std::string navigation_response;
+ };
+
+ std::string RemovePort(const GURL& url) {
+ GURL::Replacements remove_port;
+ remove_port.ClearPort();
+ return url.ReplaceComponents(remove_port).spec();
+ }
+
+ // Waits for the expected navigations to occur in any order. If an expected
+ // navigation occurs, Page.processNavigation is called with the specified
+ // navigation_response to either allow it to proceed or to cancel it.
+ void ProcessNavigationsAnyOrder(
+ std::vector<ExpectedNavigation> expected_navigations) {
+ while (!expected_navigations.empty()) {
+ WaitForNotification("Page.navigationRequested");
+ ASSERT_TRUE(requested_notification_params_.get());
+
+ std::string url;
+ ASSERT_TRUE(requested_notification_params_->GetString("url", &url));
+
+ // The url will typically have a random port which we want to remove.
+ url = RemovePort(GURL(url));
+
+ int navigation_id;
+ ASSERT_TRUE(requested_notification_params_->GetInteger("navigationId",
+ &navigation_id));
+ bool is_in_main_frame;
+ ASSERT_TRUE(requested_notification_params_->GetBoolean(
+ "isInMainFrame", &is_in_main_frame));
+ bool is_redirect;
+ ASSERT_TRUE(requested_notification_params_->GetBoolean("isRedirect",
+ &is_redirect));
+
+ bool navigation_was_expected;
+ for (auto it = expected_navigations.begin();
+ it != expected_navigations.end(); it++) {
+ if (url != it->url || is_in_main_frame != it->is_in_main_frame ||
+ is_redirect != it->is_redirect) {
+ continue;
+ }
+
+ std::unique_ptr<base::DictionaryValue> params(
+ new base::DictionaryValue());
+ params->SetString("response", it->navigation_response);
+ params->SetInteger("navigationId", navigation_id);
+ SendCommand("Page.processNavigation", std::move(params), false);
+
+ navigation_was_expected = true;
+ expected_navigations.erase(it);
+ break;
+ }
+ EXPECT_TRUE(navigation_was_expected)
+ << "url = " << url << "is_in_main_frame = " << is_in_main_frame
+ << "is_redirect = " << is_redirect;
+ }
+ }
+
+ std::vector<std::string> GetAllFrameUrls() {
+ std::vector<std::string> urls;
+ for (RenderFrameHost* render_frame_host :
+ shell()->web_contents()->GetAllFrames()) {
+ urls.push_back(RemovePort(render_frame_host->GetLastCommittedURL()));
+ }
+ return urls;
+ }
+
std::unique_ptr<base::DictionaryValue> result_;
scoped_refptr<DevToolsAgentHost> agent_host_;
int last_sent_id_;
std::vector<int> result_ids_;
std::vector<std::string> notifications_;
+ std::unique_ptr<base::DictionaryValue> requested_notification_params_;
private:
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
@@ -203,6 +281,12 @@ class DevToolsProtocolTest : public ContentBrowserTest,
EXPECT_TRUE(root->GetString("method", &notification));
notifications_.push_back(notification);
if (waiting_for_notification_ == notification) {
+ base::DictionaryValue* params;
+ if (root->GetDictionary("params", &params)) {
+ requested_notification_params_ = params->CreateDeepCopy();
+ } else {
+ requested_notification_params_.reset();
+ }
waiting_for_notification_ = std::string();
base::MessageLoop::current()->QuitNow();
}
@@ -597,4 +681,155 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateTarget) {
EXPECT_EQ(2u, shell()->windows().size());
}
+namespace {
+class NavigationFinishedObserver : public content::WebContentsObserver {
+ public:
+ explicit NavigationFinishedObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ num_finished_(0),
+ num_to_wait_for_(0) {}
+
+ ~NavigationFinishedObserver() override {}
+
+ void DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) override {
+ if (navigation_handle->WasServerRedirect())
+ return;
+
+ num_finished_++;
+ if (num_finished_ >= num_to_wait_for_ && num_to_wait_for_ != 0) {
+ base::MessageLoop::current()->QuitNow();
+ }
+ }
+
+ void WaitForNavigationsToFinish(int num_to_wait_for) {
+ if (num_finished_ < num_to_wait_for) {
+ num_to_wait_for_ = num_to_wait_for;
+ RunMessageLoop();
+ }
+ num_to_wait_for_ = 0;
+ }
+
+ private:
+ int num_finished_;
+ int num_to_wait_for_;
+};
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigationsMainFrame) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Navigate to about:blank first so we can make sure there is a target page we
+ // can attach to, and have Page.setControlNavigations complete before we start
+ // the navigations we're interested in.
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetBoolean("enabled", true);
+ SendCommand("Page.setControlNavigations", std::move(params), true);
+
+ NavigationFinishedObserver navigation_finished_observer(
+ shell()->web_contents());
+
+ GURL test_url = embedded_test_server()->GetURL(
+ "/devtools/control_navigations/meta_tag.html");
+ shell()->LoadURL(test_url);
+
+ std::vector<ExpectedNavigation> expected_navigations = {
+ {"http://127.0.0.1/devtools/control_navigations/meta_tag.html",
+ true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
+ "Proceed"},
+ {"http://127.0.0.1/devtools/navigation.html",
+ true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
+ "Cancel"}};
+
+ ProcessNavigationsAnyOrder(std::move(expected_navigations));
+
+ // Wait for the initial navigation and the cancelled meta refresh navigation
+ // to finish.
+ navigation_finished_observer.WaitForNavigationsToFinish(2);
+
+ // Check main frame has the expected url.
+ EXPECT_EQ(
+ "http://127.0.0.1/devtools/control_navigations/meta_tag.html",
+ RemovePort(
+ shell()->web_contents()->GetMainFrame()->GetLastCommittedURL()));
+}
+
+class IsolatedDevToolsProtocolTest : public DevToolsProtocolTest {
+ public:
+ ~IsolatedDevToolsProtocolTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolateAllSitesForTesting(command_line);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
+ ControlNavigationsChildFrames) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ content::SetupCrossSiteRedirector(embedded_test_server());
+
+ // Navigate to about:blank first so we can make sure there is a target page we
+ // can attach to, and have Page.setControlNavigations complete before we start
+ // the navigations we're interested in.
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetBoolean("enabled", true);
+ SendCommand("Page.setControlNavigations", std::move(params), true);
+
+ NavigationFinishedObserver navigation_finished_observer(
+ shell()->web_contents());
+
+ GURL test_url = embedded_test_server()->GetURL(
+ "/devtools/control_navigations/iframe_navigation.html");
+ shell()->LoadURL(test_url);
+
+ // Allow main frame navigation, and all iframe navigations to http://a.com
+ // Allow initial iframe navigation to http://b.com but dissallow it to
+ // navigate to /devtools/navigation.html.
+ std::vector<ExpectedNavigation> expected_navigations = {
+ {"http://127.0.0.1/devtools/control_navigations/"
+ "iframe_navigation.html",
+ /* expected_is_in_main_frame */ true,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://127.0.0.1/cross-site/a.com/devtools/control_navigations/"
+ "meta_tag.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://127.0.0.1/cross-site/b.com/devtools/control_navigations/"
+ "meta_tag.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://a.com/devtools/control_navigations/meta_tag.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ true, "Proceed"},
+ {"http://b.com/devtools/control_navigations/meta_tag.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ true, "Proceed"},
+ {"http://a.com/devtools/navigation.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://b.com/devtools/navigation.html",
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Cancel"}};
+
+ ProcessNavigationsAnyOrder(std::move(expected_navigations));
+
+ // Wait for each frame's navigation to finish, ignoring redirects.
+ navigation_finished_observer.WaitForNavigationsToFinish(3);
+
+ // Make sure each frame has the expected url.
+ EXPECT_THAT(
+ GetAllFrameUrls(),
+ ElementsAre("http://127.0.0.1/devtools/control_navigations/"
+ "iframe_navigation.html",
+ "http://a.com/devtools/navigation.html",
+ "http://b.com/devtools/control_navigations/meta_tag.html"));
+}
+
} // namespace content
« no previous file with comments | « content/browser/devtools/page_navigation_throttle.cc ('k') | content/browser/devtools/protocol/page_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698