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 616819bc2c5684847caf6f4e816de3b3c9924f24..baff335bf4023ee43809ca6987b9d463403bfa41 100644 |
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc |
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc |
@@ -39,6 +39,7 @@ |
#include "content/public/test/content_browser_test_utils.h" |
#include "content/public/test/test_navigation_observer.h" |
#include "content/shell/browser/shell.h" |
+#include "content/test/content_browser_test_utils_internal.h" |
#include "net/dns/mock_host_resolver.h" |
#include "net/test/cert_test_util.h" |
#include "net/test/embedded_test_server/embedded_test_server.h" |
@@ -230,9 +231,34 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
} |
} |
- void WaitForNotification(const std::string& notification) { |
+ std::unique_ptr<base::DictionaryValue> WaitForNotification( |
+ const std::string& notification) { |
+ return WaitForNotification(notification, false); |
+ } |
+ |
+ std::unique_ptr<base::DictionaryValue> WaitForNotification( |
+ const std::string& notification, |
+ bool allow_existing) { |
+ if (allow_existing) { |
+ for (size_t i = 0; i < notifications_.size(); i++) { |
+ if (notifications_[i] == notification) { |
+ std::unique_ptr<base::DictionaryValue> result = |
+ std::move(notification_params_[i]); |
+ notifications_.erase(notifications_.begin() + i); |
+ notification_params_.erase(notification_params_.begin() + i); |
+ return result; |
+ } |
+ } |
+ } |
+ |
waiting_for_notification_ = notification; |
RunMessageLoop(); |
+ return std::move(waiting_for_notification_params_); |
+ } |
+ |
+ void ClearNotifications() { |
+ notifications_.clear(); |
+ notification_params_.clear(); |
} |
struct ExpectedNavigation { |
@@ -254,24 +280,21 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
void ProcessNavigationsAnyOrder( |
std::vector<ExpectedNavigation> expected_navigations) { |
while (!expected_navigations.empty()) { |
- WaitForNotification("Page.navigationRequested"); |
- ASSERT_TRUE(requested_notification_params_.get()); |
+ std::unique_ptr<base::DictionaryValue> params = |
+ WaitForNotification("Page.navigationRequested"); |
std::string url; |
- ASSERT_TRUE(requested_notification_params_->GetString("url", &url)); |
+ ASSERT_TRUE(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)); |
+ ASSERT_TRUE(params->GetInteger("navigationId", &navigation_id)); |
bool is_in_main_frame; |
- ASSERT_TRUE(requested_notification_params_->GetBoolean( |
- "isInMainFrame", &is_in_main_frame)); |
+ ASSERT_TRUE(params->GetBoolean( "isInMainFrame", &is_in_main_frame)); |
bool is_redirect; |
- ASSERT_TRUE(requested_notification_params_->GetBoolean("isRedirect", |
- &is_redirect)); |
+ ASSERT_TRUE(params->GetBoolean("isRedirect", &is_redirect)); |
bool navigation_was_expected; |
for (auto it = expected_navigations.begin(); |
@@ -281,11 +304,11 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
continue; |
} |
- std::unique_ptr<base::DictionaryValue> params( |
+ std::unique_ptr<base::DictionaryValue> process_params( |
new base::DictionaryValue()); |
- params->SetString("response", it->navigation_response); |
- params->SetInteger("navigationId", navigation_id); |
- SendCommand("Page.processNavigation", std::move(params), false); |
+ process_params->SetString("response", it->navigation_response); |
+ process_params->SetInteger("navigationId", navigation_id); |
+ SendCommand("Page.processNavigation", std::move(process_params), false); |
navigation_was_expected = true; |
expected_navigations.erase(it); |
@@ -322,7 +345,7 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
std::vector<int> result_ids_; |
std::vector<std::string> notifications_; |
std::vector<std::string> console_messages_; |
- std::unique_ptr<base::DictionaryValue> requested_notification_params_; |
+ std::vector<std::unique_ptr<base::DictionaryValue>> notification_params_; |
private: |
void DispatchProtocolMessage(DevToolsAgentHost* agent_host, |
@@ -345,14 +368,17 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
std::string notification; |
EXPECT_TRUE(root->GetString("method", ¬ification)); |
notifications_.push_back(notification); |
+ base::DictionaryValue* params; |
+ if (root->GetDictionary("params", ¶ms)) { |
+ notification_params_.push_back(params->CreateDeepCopy()); |
+ } else { |
+ notification_params_.push_back( |
+ base::WrapUnique(new base::DictionaryValue())); |
+ } |
if (waiting_for_notification_ == notification) { |
- base::DictionaryValue* params; |
- if (root->GetDictionary("params", ¶ms)) { |
- requested_notification_params_ = params->CreateDeepCopy(); |
- } else { |
- requested_notification_params_.reset(); |
- } |
waiting_for_notification_ = std::string(); |
+ waiting_for_notification_params_ = base::WrapUnique( |
+ notification_params_[notification_params_.size() - 1]->DeepCopy()); |
base::MessageLoop::current()->QuitNow(); |
} |
} |
@@ -363,6 +389,7 @@ class DevToolsProtocolTest : public ContentBrowserTest, |
} |
std::string waiting_for_notification_; |
+ std::unique_ptr<base::DictionaryValue> waiting_for_notification_params_; |
int waiting_for_command_result_id_; |
bool in_dispatch_; |
scoped_refptr<net::X509Certificate> last_shown_certificate_; |
@@ -1217,4 +1244,91 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ShowCertificateViewer) { |
EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate()); |
} |
+class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest { |
+ public: |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ DevToolsProtocolTest::SetUpCommandLine(command_line); |
+ IsolateAllSitesForTesting(command_line); |
+ }; |
+ |
+ void SetUpOnMainThread() override { |
+ DevToolsProtocolTest::SetUpOnMainThread(); |
+ host_resolver()->AddRule("*", "127.0.0.1"); |
+ ASSERT_TRUE(embedded_test_server()->Start()); |
+ SetupCrossSiteRedirector(embedded_test_server()); |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) { |
+ std::string temp; |
+ std::string target_id; |
+ std::unique_ptr<base::DictionaryValue> command_params; |
+ std::unique_ptr<base::DictionaryValue> params; |
+ |
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
+ NavigateToURLBlockUntilNavigationsComplete(shell(), main_url, 1); |
+ // It is safe to obtain the root frame tree node here, as it doesn't change. |
+ FrameTreeNode* root = |
+ static_cast<WebContentsImpl*>(shell()->web_contents())-> |
+ GetFrameTree()->root(); |
+ |
+ // Load cross-site page into iframe. |
+ GURL::Replacements replace_host; |
+ GURL cross_site_url(embedded_test_server()->GetURL("/title1.html")); |
+ replace_host.SetHostStr("foo.com"); |
+ cross_site_url = cross_site_url.ReplaceComponents(replace_host); |
+ NavigateFrameToURL(root->child_at(0), cross_site_url); |
+ |
+ // Enable auto-attach. |
+ Attach(); |
+ command_params.reset(new base::DictionaryValue()); |
+ command_params->SetBoolean("autoAttach", true); |
+ command_params->SetBoolean("waitForDebuggerOnStart", true); |
+ SendCommand("Target.setAutoAttach", std::move(command_params), true); |
+ EXPECT_TRUE(notifications_.empty()); |
+ command_params.reset(new base::DictionaryValue()); |
+ command_params->SetBoolean("value", true); |
+ SendCommand("Target.setAttachToFrames", std::move(command_params), false); |
+ params = WaitForNotification("Target.targetCreated", true); |
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id)); |
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp)); |
+ EXPECT_EQ("iframe", temp); |
+ params = WaitForNotification("Target.attachedToTarget", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+ |
+ // Load same-site page into iframe. |
+ FrameTreeNode* child = root->child_at(0); |
+ GURL http_url(embedded_test_server()->GetURL("/title1.html")); |
+ NavigateFrameToURL(child, http_url); |
+ params = WaitForNotification("Target.detachedFromTarget", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+ params = WaitForNotification("Target.targetRemoved", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+ |
+ // Navigate back to cross-site iframe. |
+ NavigateFrameToURL(root->child_at(0), cross_site_url); |
+ params = WaitForNotification("Target.targetCreated", true); |
+ EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id)); |
+ EXPECT_TRUE(params->GetString("targetInfo.type", &temp)); |
+ EXPECT_EQ("iframe", temp); |
+ params = WaitForNotification("Target.attachedToTarget", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+ |
+ // Disable auto-attach. |
+ command_params.reset(new base::DictionaryValue()); |
+ command_params->SetBoolean("autoAttach", false); |
+ command_params->SetBoolean("waitForDebuggerOnStart", false); |
+ SendCommand("Target.setAutoAttach", std::move(command_params), false); |
+ params = WaitForNotification("Target.detachedFromTarget", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+ params = WaitForNotification("Target.targetRemoved", true); |
+ EXPECT_TRUE(params->GetString("targetId", &temp)); |
+ EXPECT_EQ(target_id, temp); |
+} |
+ |
} // namespace content |