OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/bind.h" | |
6 #include "base/run_loop.h" | |
7 #include "content/public/test/browser_test.h" | |
8 #include "headless/lib/browser/headless_browser_context_impl.h" | |
9 #include "headless/lib/browser/headless_web_contents_impl.h" | |
10 #include "headless/public/devtools/domains/page.h" | |
11 #include "headless/public/headless_devtools_client.h" | |
12 #include "headless/public/util/expedited_dispatcher.h" | |
13 #include "headless/public/util/generic_url_request_job.h" | |
14 #include "headless/public/util/url_fetcher.h" | |
15 #include "headless/test/headless_browser_test.h" | |
16 #include "net/http/http_response_headers.h" | |
17 #include "net/url_request/url_request_job_factory.h" | |
18 #include "testing/gmock/include/gmock/gmock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 #include "url/gurl.h" | |
21 | |
22 using testing::ContainerEq; | |
23 | |
24 namespace headless { | |
25 | |
26 namespace { | |
27 class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { | |
28 public: | |
29 explicit TestProtocolHandler( | |
30 scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) | |
31 : test_delegate_(new TestDelegate(this)), | |
32 dispatcher_(new ExpeditedDispatcher(io_thread_task_runner)), | |
33 headless_browser_context_(nullptr) {} | |
34 | |
35 ~TestProtocolHandler() override {} | |
36 | |
37 void SetHeadlessBrowserContext( | |
38 HeadlessBrowserContext* headless_browser_context) { | |
39 headless_browser_context_ = headless_browser_context; | |
40 } | |
41 | |
42 struct Response { | |
43 Response() {} | |
44 Response(const std::string& body, const std::string& mime_type) | |
45 : data("HTTP/1.1 200 OK\r\nContent-Type: " + mime_type + "\r\n\r\n" + | |
46 body) {} | |
47 | |
48 std::string data; | |
49 }; | |
50 | |
51 void InsertResponse(const std::string& url, const Response& response) { | |
52 response_map_[url] = response; | |
53 } | |
54 | |
55 const Response* GetResponse(const std::string& url) const { | |
56 std::map<std::string, Response>::const_iterator find_it = | |
57 response_map_.find(url); | |
58 if (find_it == response_map_.end()) | |
59 return nullptr; | |
60 return &find_it->second; | |
61 } | |
62 | |
63 class MockURLFetcher : public URLFetcher { | |
64 public: | |
65 explicit MockURLFetcher(const TestProtocolHandler* protocol_handler) | |
66 : protocol_handler_(protocol_handler) {} | |
67 ~MockURLFetcher() override {} | |
68 | |
69 // URLFetcher implementation: | |
70 void StartFetch(const GURL& url, | |
71 const std::string& method, | |
72 const std::string& post_data, | |
73 const net::HttpRequestHeaders& request_headers, | |
74 ResultListener* result_listener) override { | |
75 EXPECT_EQ("GET", method); | |
76 | |
77 const Response* response = protocol_handler_->GetResponse(url.spec()); | |
78 if (!response) | |
79 result_listener->OnFetchStartError(net::ERR_FILE_NOT_FOUND); | |
80 | |
81 result_listener->OnFetchCompleteExtractHeaders( | |
82 url, response->data.c_str(), response->data.size()); | |
83 } | |
84 | |
85 private: | |
86 const TestProtocolHandler* protocol_handler_; | |
87 | |
88 DISALLOW_COPY_AND_ASSIGN(MockURLFetcher); | |
89 }; | |
90 | |
91 class TestDelegate : public GenericURLRequestJob::Delegate { | |
92 public: | |
93 explicit TestDelegate(TestProtocolHandler* protocol_handler) | |
94 : protocol_handler_(protocol_handler) {} | |
95 | |
96 ~TestDelegate() override {} | |
97 | |
98 // GenericURLRequestJob::Delegate implementation: | |
99 void OnPendingRequest(PendingRequest* pending_request) override { | |
100 const Request* request = pending_request->GetRequest(); | |
101 std::string url = request->GetURLRequest()->url().spec(); | |
102 int frame_tree_node_id = request->GetFrameTreeNodeId(); | |
103 DCHECK_NE(frame_tree_node_id, -1); | |
104 protocol_handler_->url_to_frame_tree_node_id_[url] = frame_tree_node_id; | |
105 pending_request->AllowRequest(); | |
106 } | |
107 | |
108 void OnResourceLoadFailed(const Request* request, | |
109 net::Error error) override {} | |
110 | |
111 void OnResourceLoadComplete( | |
112 const Request* request, | |
113 const GURL& final_url, | |
114 scoped_refptr<net::HttpResponseHeaders> response_headers, | |
115 const char* body, | |
116 size_t body_size) override {} | |
117 | |
118 private: | |
119 TestProtocolHandler* protocol_handler_; // NOT OWNED | |
120 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(TestDelegate); | |
123 }; | |
124 | |
125 // net::URLRequestJobFactory::ProtocolHandler implementation:: | |
126 net::URLRequestJob* MaybeCreateJob( | |
127 net::URLRequest* request, | |
128 net::NetworkDelegate* network_delegate) const override { | |
129 return new GenericURLRequestJob( | |
130 request, network_delegate, dispatcher_.get(), | |
131 base::MakeUnique<MockURLFetcher>(this), test_delegate_.get(), | |
132 headless_browser_context_); | |
133 } | |
134 | |
135 std::map<std::string, int> url_to_frame_tree_node_id_; | |
136 | |
137 private: | |
138 std::unique_ptr<TestDelegate> test_delegate_; | |
139 std::unique_ptr<ExpeditedDispatcher> dispatcher_; | |
140 std::map<std::string, Response> response_map_; | |
141 HeadlessBrowserContext* headless_browser_context_; | |
142 | |
143 DISALLOW_COPY_AND_ASSIGN(TestProtocolHandler); | |
144 }; | |
145 | |
146 const char* kIndexHtml = R"( | |
147 <html> | |
148 <body>Hello. | |
149 <iframe src="iframe1.html"></iframe> | |
150 <iframe src="iframe2.html"></iframe> | |
151 </body> | |
152 </html>)"; | |
153 | |
154 const char* kIFrame1 = "<html><body>IFrame 1</body></html>"; | |
155 | |
156 const char* kIFrame2 = "<html><body>IFrame 2</body></html>"; | |
157 | |
158 } // namespace | |
159 | |
160 class FrameIdTest : public HeadlessAsyncDevTooledBrowserTest, | |
161 public page::Observer { | |
162 public: | |
163 void RunDevTooledTest() override { | |
164 http_handler_->SetHeadlessBrowserContext(browser_context_); | |
165 | |
166 EXPECT_TRUE(embedded_test_server()->Start()); | |
167 devtools_client_->GetPage()->AddObserver(this); | |
168 | |
169 base::RunLoop run_loop; | |
170 devtools_client_->GetPage()->Enable(run_loop.QuitClosure()); | |
171 base::MessageLoop::ScopedNestableTaskAllower nest_loop( | |
172 base::MessageLoop::current()); | |
173 run_loop.Run(); | |
174 | |
175 devtools_client_->GetPage()->Navigate("http://foo.com/index.html"); | |
176 } | |
177 | |
178 ProtocolHandlerMap GetProtocolHandlers() override { | |
179 ProtocolHandlerMap protocol_handlers; | |
180 std::unique_ptr<TestProtocolHandler> http_handler( | |
181 new TestProtocolHandler(browser()->BrowserIOThread())); | |
182 http_handler_ = http_handler.get(); | |
183 http_handler_->InsertResponse("http://foo.com/index.html", | |
184 {kIndexHtml, "text/html"}); | |
185 http_handler_->InsertResponse("http://foo.com/iframe1.html", | |
186 {kIFrame1, "text/html"}); | |
187 http_handler_->InsertResponse("http://foo.com/iframe2.html", | |
188 {kIFrame2, "text/html"}); | |
189 protocol_handlers[url::kHttpScheme] = std::move(http_handler); | |
190 return protocol_handlers; | |
191 } | |
192 | |
193 // page::Observer implementation: | |
194 void OnFrameNavigated(const page::FrameNavigatedParams& params) override { | |
195 url_to_frame_id_[params.GetFrame()->GetUrl()] = params.GetFrame()->GetId(); | |
196 } | |
197 | |
198 void OnLoadEventFired(const page::LoadEventFiredParams& params) override { | |
199 std::map<std::string, std::string> protocol_handler_url_to_frame_id_; | |
200 for (const auto& pair : http_handler_->url_to_frame_tree_node_id_) { | |
201 HeadlessWebContentsImpl* headless_web_contents_impl = | |
202 static_cast<HeadlessWebContentsImpl*>(web_contents_); | |
203 protocol_handler_url_to_frame_id_[pair.first] = | |
204 headless_web_contents_impl | |
205 ->GetUntrustedDevToolsFrameIdForFrameTreeNodeId( | |
206 headless_web_contents_impl->GetRenderProcessId(), | |
Charlie Reis
2017/04/26 19:52:56
Is this assuming that the only loads in the test h
alex clarke (OOO till 29th)
2017/04/27 08:49:44
Yes I expect we'll have to make an number of chang
| |
207 pair.second); | |
208 } | |
209 | |
210 EXPECT_THAT(url_to_frame_id_, protocol_handler_url_to_frame_id_); | |
211 EXPECT_EQ(3u, url_to_frame_id_.size()); | |
212 FinishAsynchronousTest(); | |
213 } | |
214 | |
215 private: | |
216 std::map<std::string, std::string> url_to_frame_id_; | |
217 TestProtocolHandler* http_handler_; // NOT OWNED | |
218 }; | |
219 | |
220 HEADLESS_ASYNC_DEVTOOLED_TEST_F(FrameIdTest); | |
221 | |
222 } // namespace headless | |
OLD | NEW |