OLD | NEW |
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 "content/shell/browser/shell_devtools_frontend.h" | 5 #include "content/shell/browser/shell_devtools_frontend.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/values.h" |
| 14 #include "content/public/browser/browser_thread.h" |
13 #include "content/public/browser/devtools_http_handler.h" | 15 #include "content/public/browser/devtools_http_handler.h" |
14 #include "content/public/browser/render_frame_host.h" | 16 #include "content/public/browser/render_frame_host.h" |
15 #include "content/public/browser/render_view_host.h" | 17 #include "content/public/browser/render_view_host.h" |
16 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
17 #include "content/public/common/content_client.h" | 19 #include "content/public/common/content_client.h" |
18 #include "content/shell/browser/shell.h" | 20 #include "content/shell/browser/shell.h" |
19 #include "content/shell/browser/shell_browser_context.h" | 21 #include "content/shell/browser/shell_browser_context.h" |
20 #include "content/shell/browser/shell_browser_main_parts.h" | 22 #include "content/shell/browser/shell_browser_main_parts.h" |
21 #include "content/shell/browser/shell_content_browser_client.h" | 23 #include "content/shell/browser/shell_content_browser_client.h" |
22 #include "content/shell/browser/shell_devtools_manager_delegate.h" | 24 #include "content/shell/browser/shell_devtools_manager_delegate.h" |
23 #include "content/shell/browser/webkit_test_controller.h" | 25 #include "content/shell/browser/webkit_test_controller.h" |
24 #include "content/shell/common/shell_switches.h" | 26 #include "content/shell/common/shell_switches.h" |
25 #include "net/base/io_buffer.h" | 27 #include "net/base/io_buffer.h" |
26 #include "net/base/net_errors.h" | 28 #include "net/base/net_errors.h" |
27 #include "net/http/http_response_headers.h" | 29 #include "net/http/http_response_headers.h" |
28 #include "net/url_request/url_fetcher.h" | 30 #include "net/url_request/url_fetcher.h" |
29 #include "net/url_request/url_fetcher_response_writer.h" | 31 #include "net/url_request/url_fetcher_response_writer.h" |
30 | 32 |
31 namespace content { | 33 namespace content { |
32 | 34 |
33 namespace { | 35 namespace { |
34 | 36 |
35 | 37 |
36 // ResponseWriter ------------------------------------------------------------- | 38 // ResponseWriter ------------------------------------------------------------- |
37 | 39 |
38 class ResponseWriter : public net::URLFetcherResponseWriter { | 40 class ResponseWriter : public net::URLFetcherResponseWriter { |
39 public: | 41 public: |
40 ResponseWriter(Shell* shell, int stream_id); | 42 ResponseWriter(base::WeakPtr<ShellDevToolsFrontend> shell_devtools_, |
| 43 int stream_id); |
41 ~ResponseWriter() override; | 44 ~ResponseWriter() override; |
42 | 45 |
43 // URLFetcherResponseWriter overrides: | 46 // URLFetcherResponseWriter overrides: |
44 int Initialize(const net::CompletionCallback& callback) override; | 47 int Initialize(const net::CompletionCallback& callback) override; |
45 int Write(net::IOBuffer* buffer, | 48 int Write(net::IOBuffer* buffer, |
46 int num_bytes, | 49 int num_bytes, |
47 const net::CompletionCallback& callback) override; | 50 const net::CompletionCallback& callback) override; |
48 int Finish(const net::CompletionCallback& callback) override; | 51 int Finish(const net::CompletionCallback& callback) override; |
49 | 52 |
50 private: | 53 private: |
51 Shell* shell_; | 54 base::WeakPtr<ShellDevToolsFrontend> shell_devtools_; |
52 int stream_id_; | 55 int stream_id_; |
53 | 56 |
54 DISALLOW_COPY_AND_ASSIGN(ResponseWriter); | 57 DISALLOW_COPY_AND_ASSIGN(ResponseWriter); |
55 }; | 58 }; |
56 | 59 |
57 ResponseWriter::ResponseWriter(Shell* shell, | 60 ResponseWriter::ResponseWriter( |
58 int stream_id) | 61 base::WeakPtr<ShellDevToolsFrontend> shell_devtools, |
59 : shell_(shell), | 62 int stream_id) |
| 63 : shell_devtools_(shell_devtools), |
60 stream_id_(stream_id) { | 64 stream_id_(stream_id) { |
61 } | 65 } |
62 | 66 |
63 ResponseWriter::~ResponseWriter() { | 67 ResponseWriter::~ResponseWriter() { |
64 } | 68 } |
65 | 69 |
66 int ResponseWriter::Initialize(const net::CompletionCallback& callback) { | 70 int ResponseWriter::Initialize(const net::CompletionCallback& callback) { |
67 return net::OK; | 71 return net::OK; |
68 } | 72 } |
69 | 73 |
70 int ResponseWriter::Write(net::IOBuffer* buffer, | 74 int ResponseWriter::Write(net::IOBuffer* buffer, |
71 int num_bytes, | 75 int num_bytes, |
72 const net::CompletionCallback& callback) { | 76 const net::CompletionCallback& callback) { |
73 base::StringValue chunk(std::string(buffer->data(), num_bytes)); | 77 base::FundamentalValue* id = new base::FundamentalValue(stream_id_); |
74 std::string encoded; | 78 base::StringValue* chunk = |
75 base::JSONWriter::Write(&chunk, &encoded); | 79 new base::StringValue(std::string(buffer->data(), num_bytes)); |
76 | 80 |
77 std::string code = base::StringPrintf( | 81 content::BrowserThread::PostTask( |
78 "DevToolsAPI.streamWrite(%d, %s)", stream_id_, encoded.c_str()); | 82 content::BrowserThread::UI, FROM_HERE, |
79 shell_->web_contents()->GetMainFrame()->ExecuteJavaScript( | 83 base::Bind(&ShellDevToolsFrontend::CallClientFunction, |
80 base::UTF8ToUTF16(code)); | 84 shell_devtools_, "DevToolsAPI.streamWrite", |
81 | 85 base::Owned(id), base::Owned(chunk), nullptr)); |
82 return num_bytes; | 86 return num_bytes; |
83 } | 87 } |
84 | 88 |
85 int ResponseWriter::Finish(const net::CompletionCallback& callback) { | 89 int ResponseWriter::Finish(const net::CompletionCallback& callback) { |
86 std::string code = base::StringPrintf( | |
87 "DevToolsAPI.streamFinish(%d)", stream_id_); | |
88 shell_->web_contents()->GetMainFrame()->ExecuteJavaScript( | |
89 base::UTF8ToUTF16(code)); | |
90 return net::OK; | 90 return net::OK; |
91 } | 91 } |
92 | 92 |
93 } // namespace | 93 } // namespace |
94 | 94 |
95 // This constant should be in sync with | 95 // This constant should be in sync with |
96 // the constant at devtools_ui_bindings.cc. | 96 // the constant at devtools_ui_bindings.cc. |
97 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; | 97 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; |
98 | 98 |
99 // static | 99 // static |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 if (!agent_host_) | 138 if (!agent_host_) |
139 return; | 139 return; |
140 agent_host_->DetachClient(); | 140 agent_host_->DetachClient(); |
141 agent_host_ = NULL; | 141 agent_host_ = NULL; |
142 } | 142 } |
143 | 143 |
144 ShellDevToolsFrontend::ShellDevToolsFrontend(Shell* frontend_shell, | 144 ShellDevToolsFrontend::ShellDevToolsFrontend(Shell* frontend_shell, |
145 DevToolsAgentHost* agent_host) | 145 DevToolsAgentHost* agent_host) |
146 : WebContentsObserver(frontend_shell->web_contents()), | 146 : WebContentsObserver(frontend_shell->web_contents()), |
147 frontend_shell_(frontend_shell), | 147 frontend_shell_(frontend_shell), |
148 agent_host_(agent_host) { | 148 agent_host_(agent_host), |
| 149 weak_factory_(this) { |
149 } | 150 } |
150 | 151 |
151 ShellDevToolsFrontend::~ShellDevToolsFrontend() { | 152 ShellDevToolsFrontend::~ShellDevToolsFrontend() { |
152 for (const auto& pair : pending_requests_) | 153 for (const auto& pair : pending_requests_) |
153 delete pair.first; | 154 delete pair.first; |
154 } | 155 } |
155 | 156 |
156 void ShellDevToolsFrontend::RenderViewCreated( | 157 void ShellDevToolsFrontend::RenderViewCreated( |
157 RenderViewHost* render_view_host) { | 158 RenderViewHost* render_view_host) { |
158 if (!frontend_host_) { | 159 if (!frontend_host_) { |
(...skipping 21 matching lines...) Expand all Loading... |
180 return; | 181 return; |
181 std::string method; | 182 std::string method; |
182 base::ListValue* params = NULL; | 183 base::ListValue* params = NULL; |
183 base::DictionaryValue* dict = NULL; | 184 base::DictionaryValue* dict = NULL; |
184 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); | 185 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); |
185 if (!parsed_message || | 186 if (!parsed_message || |
186 !parsed_message->GetAsDictionary(&dict) || | 187 !parsed_message->GetAsDictionary(&dict) || |
187 !dict->GetString("method", &method)) { | 188 !dict->GetString("method", &method)) { |
188 return; | 189 return; |
189 } | 190 } |
190 int id = 0; | 191 int request_id = 0; |
191 dict->GetInteger("id", &id); | 192 dict->GetInteger("id", &request_id); |
192 dict->GetList("params", ¶ms); | 193 dict->GetList("params", ¶ms); |
193 | 194 |
194 std::string browser_message; | 195 std::string browser_message; |
195 if (method == "sendMessageToBrowser" && params && | 196 if (method == "sendMessageToBrowser" && params && |
196 params->GetSize() == 1 && params->GetString(0, &browser_message)) { | 197 params->GetSize() == 1 && params->GetString(0, &browser_message)) { |
197 agent_host_->DispatchProtocolMessage(browser_message); | 198 agent_host_->DispatchProtocolMessage(browser_message); |
198 } else if (method == "loadCompleted") { | 199 } else if (method == "loadCompleted") { |
199 web_contents()->GetMainFrame()->ExecuteJavaScript( | 200 web_contents()->GetMainFrame()->ExecuteJavaScript( |
200 base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);")); | 201 base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);")); |
201 } else if (method == "loadNetworkResource" && params->GetSize() == 3) { | 202 } else if (method == "loadNetworkResource" && params->GetSize() == 3) { |
202 // TODO(pfeldman): handle some of the embedder messages in content. | 203 // TODO(pfeldman): handle some of the embedder messages in content. |
203 std::string url; | 204 std::string url; |
204 std::string headers; | 205 std::string headers; |
205 int stream_id; | 206 int stream_id; |
206 if (!params->GetString(0, &url) || | 207 if (!params->GetString(0, &url) || |
207 !params->GetString(1, &headers) || | 208 !params->GetString(1, &headers) || |
208 !params->GetInteger(2, &stream_id)) { | 209 !params->GetInteger(2, &stream_id)) { |
209 return; | 210 return; |
210 } | 211 } |
| 212 |
211 GURL gurl(url); | 213 GURL gurl(url); |
212 if (!gurl.is_valid()) { | 214 if (!gurl.is_valid()) { |
213 std::string code = base::StringPrintf( | 215 base::DictionaryValue response; |
214 "DevToolsAPI.embedderMessageAck(%d, { statusCode: 404 });", id); | 216 response.SetInteger("statusCode", 404); |
215 web_contents()->GetMainFrame()->ExecuteJavaScript( | 217 SendMessageAck(request_id, &response); |
216 base::UTF8ToUTF16(code)); | |
217 return; | 218 return; |
218 } | 219 } |
219 | 220 |
220 net::URLFetcher* fetcher = | 221 net::URLFetcher* fetcher = |
221 net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); | 222 net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); |
222 pending_requests_[fetcher] = id; | 223 pending_requests_[fetcher] = request_id; |
223 fetcher->SetRequestContext(web_contents()->GetBrowserContext()-> | 224 fetcher->SetRequestContext(web_contents()->GetBrowserContext()-> |
224 GetRequestContext()); | 225 GetRequestContext()); |
225 fetcher->SetExtraRequestHeaders(headers); | 226 fetcher->SetExtraRequestHeaders(headers); |
226 fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( | 227 fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( |
227 new ResponseWriter(frontend_shell(), stream_id))); | 228 new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id))); |
228 fetcher->Start(); | 229 fetcher->Start(); |
229 return; | 230 return; |
230 } else { | 231 } else { |
231 return; | 232 return; |
232 } | 233 } |
233 | 234 |
234 if (id) { | 235 if (request_id) |
235 std::string code = "DevToolsAPI.embedderMessageAck(" + | 236 SendMessageAck(request_id, nullptr); |
236 base::IntToString(id) + ",\"\");"; | |
237 base::string16 javascript = base::UTF8ToUTF16(code); | |
238 web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); | |
239 } | |
240 } | 237 } |
241 | 238 |
242 void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( | 239 void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( |
243 const std::string& message) { | 240 const std::string& message) { |
244 if (agent_host_) | 241 if (agent_host_) |
245 agent_host_->DispatchProtocolMessage(message); | 242 agent_host_->DispatchProtocolMessage(message); |
246 } | 243 } |
247 | 244 |
248 void ShellDevToolsFrontend::DispatchProtocolMessage( | 245 void ShellDevToolsFrontend::DispatchProtocolMessage( |
249 DevToolsAgentHost* agent_host, const std::string& message) { | 246 DevToolsAgentHost* agent_host, const std::string& message) { |
(...skipping 28 matching lines...) Expand all Loading... |
278 net::HttpResponseHeaders* rh = source->GetResponseHeaders(); | 275 net::HttpResponseHeaders* rh = source->GetResponseHeaders(); |
279 response.SetInteger("statusCode", rh ? rh->response_code() : 200); | 276 response.SetInteger("statusCode", rh ? rh->response_code() : 200); |
280 response.Set("headers", headers); | 277 response.Set("headers", headers); |
281 | 278 |
282 void* iterator = NULL; | 279 void* iterator = NULL; |
283 std::string name; | 280 std::string name; |
284 std::string value; | 281 std::string value; |
285 while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) | 282 while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) |
286 headers->SetString(name, value); | 283 headers->SetString(name, value); |
287 | 284 |
288 std::string json; | 285 SendMessageAck(it->second, &response); |
289 base::JSONWriter::Write(&response, &json); | |
290 | |
291 std::string message = base::StringPrintf( | |
292 "DevToolsAPI.embedderMessageAck(%d, %s)", | |
293 it->second, | |
294 json.c_str()); | |
295 web_contents()->GetMainFrame()-> | |
296 ExecuteJavaScript(base::UTF8ToUTF16(message)); | |
297 | |
298 pending_requests_.erase(it); | 286 pending_requests_.erase(it); |
299 delete source; | 287 delete source; |
300 } | 288 } |
301 | 289 |
| 290 void ShellDevToolsFrontend::CallClientFunction( |
| 291 const std::string& function_name, |
| 292 const base::Value* arg1, |
| 293 const base::Value* arg2, |
| 294 const base::Value* arg3) { |
| 295 std::string javascript = function_name + "("; |
| 296 if (arg1) { |
| 297 std::string json; |
| 298 base::JSONWriter::Write(arg1, &json); |
| 299 javascript.append(json); |
| 300 if (arg2) { |
| 301 base::JSONWriter::Write(arg2, &json); |
| 302 javascript.append(", ").append(json); |
| 303 if (arg3) { |
| 304 base::JSONWriter::Write(arg3, &json); |
| 305 javascript.append(", ").append(json); |
| 306 } |
| 307 } |
| 308 } |
| 309 javascript.append(");"); |
| 310 web_contents()->GetMainFrame()->ExecuteJavaScript( |
| 311 base::UTF8ToUTF16(javascript)); |
| 312 } |
| 313 |
| 314 void ShellDevToolsFrontend::SendMessageAck(int request_id, |
| 315 const base::Value* arg) { |
| 316 base::FundamentalValue id_value(request_id); |
| 317 CallClientFunction("DevToolsAPI.embedderMessageAck", |
| 318 &id_value, arg, nullptr); |
| 319 } |
| 320 |
302 void ShellDevToolsFrontend::AttachTo(WebContents* inspected_contents) { | 321 void ShellDevToolsFrontend::AttachTo(WebContents* inspected_contents) { |
303 DisconnectFromTarget(); | 322 DisconnectFromTarget(); |
304 agent_host_ = DevToolsAgentHost::GetOrCreateFor(inspected_contents); | 323 agent_host_ = DevToolsAgentHost::GetOrCreateFor(inspected_contents); |
305 } | 324 } |
306 | 325 |
307 void ShellDevToolsFrontend::AgentHostClosed( | 326 void ShellDevToolsFrontend::AgentHostClosed( |
308 DevToolsAgentHost* agent_host, bool replaced) { | 327 DevToolsAgentHost* agent_host, bool replaced) { |
309 frontend_shell_->Close(); | 328 frontend_shell_->Close(); |
310 } | 329 } |
311 | 330 |
312 } // namespace content | 331 } // namespace content |
OLD | NEW |