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

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: Reduce number of delta lines in DevToolsProtocolTest 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 e6e83576d6626b1eab23df2ea201c6032e936fe0..d37728b0931643f8c75252894da81ea9f4c2790c 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -9,6 +9,7 @@
#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"
@@ -24,10 +25,14 @@
#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/re2/src/re2/re2.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/codec/png_codec.h"
+using testing::MatchesRegex;
+
namespace content {
namespace {
@@ -170,16 +175,90 @@ class DevToolsProtocolTest : public ContentBrowserTest,
}
}
- void WaitForNotification(const std::string& notification) {
- waiting_for_notification_ = notification;
+ // Waits for an event of type |notification_name| to be sent.
+ void WaitForNotification(const std::string& notification_name) {
+ waiting_for_notification_ = notification_name;
+ waiting_for_notification_count_ =
+ notification_count_[notification_name] + 1;
RunMessageLoop();
}
+ // Waits until the count of events of type |notification_name| is >= count.
+ void WaitForNotificationCount(const std::string& notification_name,
+ int count) {
+ if (notification_count_[notification_name] < count) {
+ waiting_for_notification_ = notification_name;
+ waiting_for_notification_count_ = count;
+ RunMessageLoop();
+ }
+ }
+
+ struct ExpectedNavigation {
+ std::string url_regex;
+ bool renderer_initiated;
+ bool is_in_main_frame;
+ bool is_redirect;
+ std::string navigation_response;
+ };
+
+ // 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 WaitForNavigationsInAnyOrder(
+ 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));
+ int navigation_id;
+ ASSERT_TRUE(requested_notification_params_->GetInteger("navigationId",
+ &navigation_id));
+ bool renderer_initiated;
+ ASSERT_TRUE(requested_notification_params_->GetBoolean(
+ "rendererInitiated", &renderer_initiated));
+ 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 (!RE2::FullMatch(url, it->url_regex) ||
+ renderer_initiated != it->renderer_initiated ||
+ 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 << "renderer_initiated = " << renderer_initiated
+ << "is_in_main_frame = " << is_in_main_frame
+ << "is_redirect = " << is_redirect;
+ }
+ }
+
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_;
+
+ bool NoEventsReceived() const { return notification_count_.empty(); }
private:
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
@@ -201,8 +280,15 @@ class DevToolsProtocolTest : public ContentBrowserTest,
} else {
std::string notification;
EXPECT_TRUE(root->GetString("method", &notification));
- notifications_.push_back(notification);
- if (waiting_for_notification_ == notification) {
+ int count = ++notification_count_[notification];
+ if (waiting_for_notification_ == notification &&
+ count >= waiting_for_notification_count_) {
+ 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();
}
@@ -213,7 +299,9 @@ class DevToolsProtocolTest : public ContentBrowserTest,
EXPECT_TRUE(false);
}
+ std::map<std::string, int> notification_count_;
std::string waiting_for_notification_;
+ int waiting_for_notification_count_;
int waiting_for_command_result_id_;
bool in_dispatch_;
};
@@ -416,14 +504,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) {
EXPECT_EQ(2, result_ids_[1]); // Page.navigate
}
- enough_results = notifications_.size() >= 1u;
- EXPECT_TRUE(enough_results);
- bool found_frame_notification = false;
- for (const std::string& notification : notifications_) {
- if (notification == "Page.frameStartedLoading")
- found_frame_notification = true;
- }
- EXPECT_TRUE(found_frame_notification);
+ WaitForNotificationCount("Page.frameStartedLoading", 1);
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteNoDetach) {
@@ -440,7 +521,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSiteNoDetach) {
"B.com", "/devtools/navigation.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url2, 1);
- EXPECT_EQ(0u, notifications_.size());
+ EXPECT_TRUE(NoEventsReceived());
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReconnectPreservesState) {
@@ -597,4 +678,138 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserNewPage) {
EXPECT_EQ(2u, shell()->windows().size());
}
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigations_MainFrame) {
nasko 2016/07/14 16:47:19 No underscores, just CamelCase.
alex clarke (OOO till 29th) 2016/07/14 17:38:34 Done.
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+ SendCommand("Page.enable", nullptr);
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetBoolean("enabled", true);
+ SendCommand("Page.setControlNavigations", std::move(params), true);
+
+ 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:\\d+/devtools/control_navigations/meta_tag.html",
+ false /* expected_renderer_initiated */,
+ true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
+ "Proceed"},
+ {"http://127.0.0.1:\\d+/devtools/navigation.html",
+ true /* expected_renderer_initiated */,
+ true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
+ "Cancel"}};
+
+ WaitForNavigationsInAnyOrder(std::move(expected_navigations));
+
+ WaitForNotificationCount("Page.frameStoppedLoading", 2);
+
+ // Check main frame has the expected url.
+ SendCommand("Page.getResourceTree", nullptr);
+
+ const base::DictionaryValue* frame_tree;
+ ASSERT_TRUE(result_->GetDictionary("frameTree", &frame_tree));
+ const base::DictionaryValue* frame;
+ ASSERT_TRUE(frame_tree->GetDictionary("frame", &frame));
+
+ std::string frame_url;
+ ASSERT_TRUE(frame->GetString("url", &frame_url));
+ EXPECT_THAT(
+ frame_url,
+ MatchesRegex(
+ "http://127.0.0.1:\\d+/devtools/control_navigations/meta_tag.html"));
nasko 2016/07/14 16:47:19 very minor nit: You could just strip the port numb
alex clarke (OOO till 29th) 2016/07/14 17:38:34 Seems like a good idea, are there any utilities fo
nasko 2016/07/14 17:55:51 You can use a GURL::Replacements. There are some e
alex clarke (OOO till 29th) 2016/07/15 13:21:21 Done.
+}
+
+// TODO(alexclarke): Make this work with IsolateAllSitesForTesting.
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigations_ChildFrames) {
nasko 2016/07/14 16:47:20 Thanks for adding this test!
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ content::SetupCrossSiteRedirector(embedded_test_server());
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
nasko 2016/07/14 16:47:19 Why do you need to navigate to about:blank first?
alex clarke (OOO till 29th) 2016/07/14 17:38:34 For two reasons: 1. To make sure there's a page we
nasko 2016/07/14 17:55:51 In general, each frame starts with an initial blan
+ Attach();
+ SendCommand("Page.enable", nullptr);
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetBoolean("enabled", true);
+ SendCommand("Page.setControlNavigations", std::move(params), true);
+
+ 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:\\d+/devtools/control_navigations/"
+ "iframe_navigation.html",
+ /* expected_renderer_initiated */ false,
+ /* expected_is_in_main_frame */ true,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://127.0.0.1:\\d+/cross-site/a.com/devtools/control_navigations/"
+ "meta_tag.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://127.0.0.1:\\d+/cross-site/b.com/devtools/control_navigations/"
+ "meta_tag.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://a.com:\\d+/devtools/control_navigations/meta_tag.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ true, "Proceed"},
+ {"http://b.com:\\d+/devtools/control_navigations/meta_tag.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ true, "Proceed"},
+ {"http://a.com:\\d+/devtools/navigation.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Proceed"},
+ {"http://b.com:\\d+/devtools/navigation.html",
+ /* expected_renderer_initiated */ true,
+ /* expected_is_in_main_frame */ false,
+ /* expected_is_redirect */ false, "Cancel"}};
+
+ WaitForNavigationsInAnyOrder(std::move(expected_navigations));
+
+ WaitForNotificationCount("Page.frameStoppedLoading", 5);
+
+ // Check that the a.com iframe navigated to /devtools/navigation.html and that
+ // the b.com iframe was stuck at /devtools/control_navigations/meta_tag.html.
+ SendCommand("Page.getResourceTree", nullptr);
+
+ const base::DictionaryValue* frame_tree;
+ ASSERT_TRUE(result_->GetDictionary("frameTree", &frame_tree));
+
+ const base::ListValue* child_frames;
+ ASSERT_TRUE(frame_tree->GetList("childFrames", &child_frames));
+ EXPECT_EQ(2u, child_frames->GetSize());
+
+ const base::DictionaryValue* child_frame0;
+ ASSERT_TRUE(child_frames->GetDictionary(0, &child_frame0));
+ ASSERT_TRUE(child_frame0->GetDictionary("frame", &child_frame0));
+
+ std::string frame0_url;
+ ASSERT_TRUE(child_frame0->GetString("url", &frame0_url));
+ EXPECT_THAT(frame0_url,
+ MatchesRegex("http://a.com:\\d+/devtools/navigation.html"));
+
+ const base::DictionaryValue* child_frame1;
+ ASSERT_TRUE(child_frames->GetDictionary(1, &child_frame1));
+ ASSERT_TRUE(child_frame1->GetDictionary("frame", &child_frame1));
+ std::string frame1_url;
+ ASSERT_TRUE(child_frame1->GetString("url", &frame1_url));
+ EXPECT_THAT(
+ frame1_url,
+ MatchesRegex(
+ "http://b.com:\\d+/devtools/control_navigations/meta_tag.html"));
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698