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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 <stddef.h> 5 #include <stddef.h>
6 #include <utility> 6 #include <utility>
7 7
8 #include "base/base64.h" 8 #include "base/base64.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h" 11 #include "base/json/json_writer.h"
12 #include "base/memory/ptr_util.h"
12 #include "base/run_loop.h" 13 #include "base/run_loop.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "build/build_config.h" 15 #include "build/build_config.h"
15 #include "content/public/browser/devtools_agent_host.h" 16 #include "content/public/browser/devtools_agent_host.h"
16 #include "content/public/browser/javascript_dialog_manager.h" 17 #include "content/public/browser/javascript_dialog_manager.h"
18 #include "content/public/browser/navigation_handle.h"
19 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/render_view_host.h" 20 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/url_constants.h" 22 #include "content/public/common/url_constants.h"
20 #include "content/public/test/browser_test_utils.h" 23 #include "content/public/test/browser_test_utils.h"
21 #include "content/public/test/content_browser_test.h" 24 #include "content/public/test/content_browser_test.h"
22 #include "content/public/test/content_browser_test_utils.h" 25 #include "content/public/test/content_browser_test_utils.h"
23 #include "content/public/test/test_navigation_observer.h" 26 #include "content/public/test/test_navigation_observer.h"
24 #include "content/shell/browser/shell.h" 27 #include "content/shell/browser/shell.h"
25 #include "net/dns/mock_host_resolver.h" 28 #include "net/dns/mock_host_resolver.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h" 29 #include "net/test/embedded_test_server/embedded_test_server.h"
30 #include "testing/gmock/include/gmock/gmock.h"
27 #include "third_party/skia/include/core/SkBitmap.h" 31 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/compositor/compositor_switches.h" 32 #include "ui/compositor/compositor_switches.h"
29 #include "ui/gfx/codec/png_codec.h" 33 #include "ui/gfx/codec/png_codec.h"
30 34
35 using testing::ElementsAre;
36
31 namespace content { 37 namespace content {
32 38
33 namespace { 39 namespace {
34 40
35 const char kIdParam[] = "id"; 41 const char kIdParam[] = "id";
36 const char kMethodParam[] = "method"; 42 const char kMethodParam[] = "method";
37 const char kParamsParam[] = "params"; 43 const char kParamsParam[] = "params";
38 44
39 class TestJavaScriptDialogManager : public JavaScriptDialogManager, 45 class TestJavaScriptDialogManager : public JavaScriptDialogManager,
40 public WebContentsDelegate { 46 public WebContentsDelegate {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 agent_host_->DetachClient(this); 174 agent_host_->DetachClient(this);
169 agent_host_ = nullptr; 175 agent_host_ = nullptr;
170 } 176 }
171 } 177 }
172 178
173 void WaitForNotification(const std::string& notification) { 179 void WaitForNotification(const std::string& notification) {
174 waiting_for_notification_ = notification; 180 waiting_for_notification_ = notification;
175 RunMessageLoop(); 181 RunMessageLoop();
176 } 182 }
177 183
184 struct ExpectedNavigation {
185 std::string url;
186 bool is_in_main_frame;
187 bool is_redirect;
188 std::string navigation_response;
189 };
190
191 std::string RemovePort(const GURL& url) {
192 GURL::Replacements remove_port;
193 remove_port.ClearPort();
194 return url.ReplaceComponents(remove_port).spec();
195 }
196
197 // Waits for the expected navigations to occur in any order. If an expected
198 // navigation occurs, Page.processNavigation is called with the specified
199 // navigation_response to either allow it to proceed or to cancel it.
200 void ProcessNavigationsAnyOrder(
201 std::vector<ExpectedNavigation> expected_navigations) {
202 while (!expected_navigations.empty()) {
203 WaitForNotification("Page.navigationRequested");
204 ASSERT_TRUE(requested_notification_params_.get());
205
206 std::string url;
207 ASSERT_TRUE(requested_notification_params_->GetString("url", &url));
208
209 // The url will typically have a random port which we want to remove.
210 url = RemovePort(GURL(url));
211
212 int navigation_id;
213 ASSERT_TRUE(requested_notification_params_->GetInteger("navigationId",
214 &navigation_id));
215 bool is_in_main_frame;
216 ASSERT_TRUE(requested_notification_params_->GetBoolean(
217 "isInMainFrame", &is_in_main_frame));
218 bool is_redirect;
219 ASSERT_TRUE(requested_notification_params_->GetBoolean("isRedirect",
220 &is_redirect));
221
222 bool navigation_was_expected;
223 for (auto it = expected_navigations.begin();
224 it != expected_navigations.end(); it++) {
225 if (url != it->url || is_in_main_frame != it->is_in_main_frame ||
226 is_redirect != it->is_redirect) {
227 continue;
228 }
229
230 std::unique_ptr<base::DictionaryValue> params(
231 new base::DictionaryValue());
232 params->SetString("response", it->navigation_response);
233 params->SetInteger("navigationId", navigation_id);
234 SendCommand("Page.processNavigation", std::move(params), false);
235
236 navigation_was_expected = true;
237 expected_navigations.erase(it);
238 break;
239 }
240 EXPECT_TRUE(navigation_was_expected)
241 << "url = " << url << "is_in_main_frame = " << is_in_main_frame
242 << "is_redirect = " << is_redirect;
243 }
244 }
245
246 std::vector<std::string> GetAllFrameUrls() {
247 std::vector<std::string> urls;
248 for (RenderFrameHost* render_frame_host :
249 shell()->web_contents()->GetAllFrames()) {
250 urls.push_back(RemovePort(render_frame_host->GetLastCommittedURL()));
251 }
252 return urls;
253 }
254
178 std::unique_ptr<base::DictionaryValue> result_; 255 std::unique_ptr<base::DictionaryValue> result_;
179 scoped_refptr<DevToolsAgentHost> agent_host_; 256 scoped_refptr<DevToolsAgentHost> agent_host_;
180 int last_sent_id_; 257 int last_sent_id_;
181 std::vector<int> result_ids_; 258 std::vector<int> result_ids_;
182 std::vector<std::string> notifications_; 259 std::vector<std::string> notifications_;
260 std::unique_ptr<base::DictionaryValue> requested_notification_params_;
183 261
184 private: 262 private:
185 void DispatchProtocolMessage(DevToolsAgentHost* agent_host, 263 void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
186 const std::string& message) override { 264 const std::string& message) override {
187 std::unique_ptr<base::DictionaryValue> root( 265 std::unique_ptr<base::DictionaryValue> root(
188 static_cast<base::DictionaryValue*>( 266 static_cast<base::DictionaryValue*>(
189 base::JSONReader::Read(message).release())); 267 base::JSONReader::Read(message).release()));
190 int id; 268 int id;
191 if (root->GetInteger("id", &id)) { 269 if (root->GetInteger("id", &id)) {
192 result_ids_.push_back(id); 270 result_ids_.push_back(id);
193 base::DictionaryValue* result; 271 base::DictionaryValue* result;
194 ASSERT_TRUE(root->GetDictionary("result", &result)); 272 ASSERT_TRUE(root->GetDictionary("result", &result));
195 result_.reset(result->DeepCopy()); 273 result_.reset(result->DeepCopy());
196 in_dispatch_ = false; 274 in_dispatch_ = false;
197 if (id && id == waiting_for_command_result_id_) { 275 if (id && id == waiting_for_command_result_id_) {
198 waiting_for_command_result_id_ = 0; 276 waiting_for_command_result_id_ = 0;
199 base::MessageLoop::current()->QuitNow(); 277 base::MessageLoop::current()->QuitNow();
200 } 278 }
201 } else { 279 } else {
202 std::string notification; 280 std::string notification;
203 EXPECT_TRUE(root->GetString("method", &notification)); 281 EXPECT_TRUE(root->GetString("method", &notification));
204 notifications_.push_back(notification); 282 notifications_.push_back(notification);
205 if (waiting_for_notification_ == notification) { 283 if (waiting_for_notification_ == notification) {
284 base::DictionaryValue* params;
285 if (root->GetDictionary("params", &params)) {
286 requested_notification_params_ = params->CreateDeepCopy();
287 } else {
288 requested_notification_params_.reset();
289 }
206 waiting_for_notification_ = std::string(); 290 waiting_for_notification_ = std::string();
207 base::MessageLoop::current()->QuitNow(); 291 base::MessageLoop::current()->QuitNow();
208 } 292 }
209 } 293 }
210 } 294 }
211 295
212 void AgentHostClosed(DevToolsAgentHost* agent_host, bool replaced) override { 296 void AgentHostClosed(DevToolsAgentHost* agent_host, bool replaced) override {
213 EXPECT_TRUE(false); 297 EXPECT_TRUE(false);
214 } 298 }
215 299
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateTarget) { 674 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateTarget) {
591 NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1); 675 NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
592 Attach(); 676 Attach();
593 EXPECT_EQ(1u, shell()->windows().size()); 677 EXPECT_EQ(1u, shell()->windows().size());
594 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); 678 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
595 params->SetString("url", "about:blank"); 679 params->SetString("url", "about:blank");
596 SendCommand("Browser.createTarget", std::move(params), true); 680 SendCommand("Browser.createTarget", std::move(params), true);
597 EXPECT_EQ(2u, shell()->windows().size()); 681 EXPECT_EQ(2u, shell()->windows().size());
598 } 682 }
599 683
684 namespace {
685 class NavigationFinishedObserver : public content::WebContentsObserver {
686 public:
687 explicit NavigationFinishedObserver(WebContents* web_contents)
688 : WebContentsObserver(web_contents),
689 num_finished_(0),
690 num_to_wait_for_(0) {}
691
692 ~NavigationFinishedObserver() override {}
693
694 void DidFinishNavigation(
695 content::NavigationHandle* navigation_handle) override {
696 if (navigation_handle->WasServerRedirect())
697 return;
698
699 num_finished_++;
700 if (num_finished_ >= num_to_wait_for_ && num_to_wait_for_ != 0) {
701 base::MessageLoop::current()->QuitNow();
702 }
703 }
704
705 void WaitForNavigationsToFinish(int num_to_wait_for) {
706 if (num_finished_ < num_to_wait_for) {
707 num_to_wait_for_ = num_to_wait_for;
708 RunMessageLoop();
709 }
710 num_to_wait_for_ = 0;
711 }
712
713 private:
714 int num_finished_;
715 int num_to_wait_for_;
716 };
717 } // namespace
718
719 IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigationsMainFrame) {
720 ASSERT_TRUE(embedded_test_server()->Start());
721
722 // Navigate to about:blank first so we can make sure there is a target page we
723 // can attach to, and have Page.setControlNavigations complete before we start
724 // the navigations we're interested in.
725 NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
726 Attach();
727
728 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
729 params->SetBoolean("enabled", true);
730 SendCommand("Page.setControlNavigations", std::move(params), true);
731
732 NavigationFinishedObserver navigation_finished_observer(
733 shell()->web_contents());
734
735 GURL test_url = embedded_test_server()->GetURL(
736 "/devtools/control_navigations/meta_tag.html");
737 shell()->LoadURL(test_url);
738
739 std::vector<ExpectedNavigation> expected_navigations = {
740 {"http://127.0.0.1/devtools/control_navigations/meta_tag.html",
741 true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
742 "Proceed"},
743 {"http://127.0.0.1/devtools/navigation.html",
744 true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
745 "Cancel"}};
746
747 ProcessNavigationsAnyOrder(std::move(expected_navigations));
748
749 // Wait for the initial navigation and the cancelled meta refresh navigation
750 // to finish.
751 navigation_finished_observer.WaitForNavigationsToFinish(2);
752
753 // Check main frame has the expected url.
754 EXPECT_EQ(
755 "http://127.0.0.1/devtools/control_navigations/meta_tag.html",
756 RemovePort(
757 shell()->web_contents()->GetMainFrame()->GetLastCommittedURL()));
758 }
759
760 class IsolatedDevToolsProtocolTest : public DevToolsProtocolTest {
761 public:
762 ~IsolatedDevToolsProtocolTest() override {}
763
764 void SetUpCommandLine(base::CommandLine* command_line) override {
765 IsolateAllSitesForTesting(command_line);
766 }
767 };
768
769 IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
770 ControlNavigationsChildFrames) {
771 host_resolver()->AddRule("*", "127.0.0.1");
772 ASSERT_TRUE(embedded_test_server()->Start());
773 content::SetupCrossSiteRedirector(embedded_test_server());
774
775 // Navigate to about:blank first so we can make sure there is a target page we
776 // can attach to, and have Page.setControlNavigations complete before we start
777 // the navigations we're interested in.
778 NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
779 Attach();
780
781 std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
782 params->SetBoolean("enabled", true);
783 SendCommand("Page.setControlNavigations", std::move(params), true);
784
785 NavigationFinishedObserver navigation_finished_observer(
786 shell()->web_contents());
787
788 GURL test_url = embedded_test_server()->GetURL(
789 "/devtools/control_navigations/iframe_navigation.html");
790 shell()->LoadURL(test_url);
791
792 // Allow main frame navigation, and all iframe navigations to http://a.com
793 // Allow initial iframe navigation to http://b.com but dissallow it to
794 // navigate to /devtools/navigation.html.
795 std::vector<ExpectedNavigation> expected_navigations = {
796 {"http://127.0.0.1/devtools/control_navigations/"
797 "iframe_navigation.html",
798 /* expected_is_in_main_frame */ true,
799 /* expected_is_redirect */ false, "Proceed"},
800 {"http://127.0.0.1/cross-site/a.com/devtools/control_navigations/"
801 "meta_tag.html",
802 /* expected_is_in_main_frame */ false,
803 /* expected_is_redirect */ false, "Proceed"},
804 {"http://127.0.0.1/cross-site/b.com/devtools/control_navigations/"
805 "meta_tag.html",
806 /* expected_is_in_main_frame */ false,
807 /* expected_is_redirect */ false, "Proceed"},
808 {"http://a.com/devtools/control_navigations/meta_tag.html",
809 /* expected_is_in_main_frame */ false,
810 /* expected_is_redirect */ true, "Proceed"},
811 {"http://b.com/devtools/control_navigations/meta_tag.html",
812 /* expected_is_in_main_frame */ false,
813 /* expected_is_redirect */ true, "Proceed"},
814 {"http://a.com/devtools/navigation.html",
815 /* expected_is_in_main_frame */ false,
816 /* expected_is_redirect */ false, "Proceed"},
817 {"http://b.com/devtools/navigation.html",
818 /* expected_is_in_main_frame */ false,
819 /* expected_is_redirect */ false, "Cancel"}};
820
821 ProcessNavigationsAnyOrder(std::move(expected_navigations));
822
823 // Wait for each frame's navigation to finish, ignoring redirects.
824 navigation_finished_observer.WaitForNavigationsToFinish(3);
825
826 // Make sure each frame has the expected url.
827 EXPECT_THAT(
828 GetAllFrameUrls(),
829 ElementsAre("http://127.0.0.1/devtools/control_navigations/"
830 "iframe_navigation.html",
831 "http://a.com/devtools/navigation.html",
832 "http://b.com/devtools/control_navigations/meta_tag.html"));
833 }
834
600 } // namespace content 835 } // namespace content
OLDNEW
« 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