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( | 90 base::FundamentalValue* id = new base::FundamentalValue(stream_id_); |
87 "DevToolsAPI.streamFinish(%d)", stream_id_); | 91 content::BrowserThread::PostTask( |
88 shell_->web_contents()->GetMainFrame()->ExecuteJavaScript( | 92 content::BrowserThread::UI, FROM_HERE, |
89 base::UTF8ToUTF16(code)); | 93 base::Bind(&ShellDevToolsFrontend::CallClientFunction, |
94 shell_devtools_, "DevToolsAPI.streamFinish", | |
95 base::Owned(id), nullptr, nullptr)); | |
90 return net::OK; | 96 return net::OK; |
91 } | 97 } |
92 | 98 |
93 } // namespace | 99 } // namespace |
94 | 100 |
95 // This constant should be in sync with | 101 // This constant should be in sync with |
96 // the constant at devtools_ui_bindings.cc. | 102 // the constant at devtools_ui_bindings.cc. |
97 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; | 103 const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; |
98 | 104 |
99 // static | 105 // static |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 if (!agent_host_) | 144 if (!agent_host_) |
139 return; | 145 return; |
140 agent_host_->DetachClient(); | 146 agent_host_->DetachClient(); |
141 agent_host_ = NULL; | 147 agent_host_ = NULL; |
142 } | 148 } |
143 | 149 |
144 ShellDevToolsFrontend::ShellDevToolsFrontend(Shell* frontend_shell, | 150 ShellDevToolsFrontend::ShellDevToolsFrontend(Shell* frontend_shell, |
145 DevToolsAgentHost* agent_host) | 151 DevToolsAgentHost* agent_host) |
146 : WebContentsObserver(frontend_shell->web_contents()), | 152 : WebContentsObserver(frontend_shell->web_contents()), |
147 frontend_shell_(frontend_shell), | 153 frontend_shell_(frontend_shell), |
148 agent_host_(agent_host) { | 154 agent_host_(agent_host), |
155 weak_factory_(this) { | |
149 } | 156 } |
150 | 157 |
151 ShellDevToolsFrontend::~ShellDevToolsFrontend() { | 158 ShellDevToolsFrontend::~ShellDevToolsFrontend() { |
152 for (const auto& pair : pending_requests_) | 159 for (const auto& pair : pending_requests_) |
153 delete pair.first; | 160 delete pair.first; |
154 } | 161 } |
155 | 162 |
156 void ShellDevToolsFrontend::RenderViewCreated( | 163 void ShellDevToolsFrontend::RenderViewCreated( |
157 RenderViewHost* render_view_host) { | 164 RenderViewHost* render_view_host) { |
158 if (!frontend_host_) { | 165 if (!frontend_host_) { |
(...skipping 21 matching lines...) Expand all Loading... | |
180 return; | 187 return; |
181 std::string method; | 188 std::string method; |
182 base::ListValue* params = NULL; | 189 base::ListValue* params = NULL; |
183 base::DictionaryValue* dict = NULL; | 190 base::DictionaryValue* dict = NULL; |
184 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); | 191 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); |
185 if (!parsed_message || | 192 if (!parsed_message || |
186 !parsed_message->GetAsDictionary(&dict) || | 193 !parsed_message->GetAsDictionary(&dict) || |
187 !dict->GetString("method", &method)) { | 194 !dict->GetString("method", &method)) { |
188 return; | 195 return; |
189 } | 196 } |
190 int id = 0; | 197 int request_id = 0; |
191 dict->GetInteger("id", &id); | 198 dict->GetInteger("id", &request_id); |
192 dict->GetList("params", ¶ms); | 199 dict->GetList("params", ¶ms); |
193 | 200 |
194 std::string browser_message; | 201 std::string browser_message; |
195 if (method == "sendMessageToBrowser" && params && | 202 if (method == "sendMessageToBrowser" && params && |
196 params->GetSize() == 1 && params->GetString(0, &browser_message)) { | 203 params->GetSize() == 1 && params->GetString(0, &browser_message)) { |
197 agent_host_->DispatchProtocolMessage(browser_message); | 204 agent_host_->DispatchProtocolMessage(browser_message); |
198 } else if (method == "loadCompleted") { | 205 } else if (method == "loadCompleted") { |
199 web_contents()->GetMainFrame()->ExecuteJavaScript( | 206 web_contents()->GetMainFrame()->ExecuteJavaScript( |
dgozman
2015/02/28 18:12:05
Use CallClientFunction.
pfeldman
2015/02/28 18:38:13
I'd need to wrap true into fundamental value, whic
| |
200 base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);")); | 207 base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);")); |
201 } else if (method == "loadNetworkResource" && params->GetSize() == 3) { | 208 } else if (method == "loadNetworkResource" && params->GetSize() == 3) { |
202 // TODO(pfeldman): handle some of the embedder messages in content. | 209 // TODO(pfeldman): handle some of the embedder messages in content. |
203 std::string url; | 210 std::string url; |
204 std::string headers; | 211 std::string headers; |
205 int stream_id; | 212 int stream_id; |
206 if (!params->GetString(0, &url) || | 213 if (!params->GetString(0, &url) || |
207 !params->GetString(1, &headers) || | 214 !params->GetString(1, &headers) || |
208 !params->GetInteger(2, &stream_id)) { | 215 !params->GetInteger(2, &stream_id)) { |
209 return; | 216 return; |
210 } | 217 } |
218 | |
211 GURL gurl(url); | 219 GURL gurl(url); |
212 if (!gurl.is_valid()) { | 220 if (!gurl.is_valid()) { |
213 std::string code = base::StringPrintf( | 221 base::DictionaryValue response; |
214 "DevToolsAPI.embedderMessageAck(%d, { statusCode: 404 });", id); | 222 response.SetInteger("statusCode", 404); |
215 web_contents()->GetMainFrame()->ExecuteJavaScript( | 223 SendMessageAck(request_id, &response); |
216 base::UTF8ToUTF16(code)); | |
217 return; | 224 return; |
218 } | 225 } |
219 | 226 |
220 net::URLFetcher* fetcher = | 227 net::URLFetcher* fetcher = |
221 net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); | 228 net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); |
222 pending_requests_[fetcher] = id; | 229 pending_requests_[fetcher] = request_id; |
223 fetcher->SetRequestContext(web_contents()->GetBrowserContext()-> | 230 fetcher->SetRequestContext(web_contents()->GetBrowserContext()-> |
224 GetRequestContext()); | 231 GetRequestContext()); |
225 fetcher->SetExtraRequestHeaders(headers); | 232 fetcher->SetExtraRequestHeaders(headers); |
226 fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( | 233 fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( |
227 new ResponseWriter(frontend_shell(), stream_id))); | 234 new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id))); |
228 fetcher->Start(); | 235 fetcher->Start(); |
229 return; | 236 return; |
230 } else { | 237 } else { |
231 return; | 238 return; |
232 } | 239 } |
233 | 240 |
234 if (id) { | 241 if (request_id) |
235 std::string code = "DevToolsAPI.embedderMessageAck(" + | 242 SendMessageAck(request_id, nullptr); |
236 base::IntToString(id) + ",\"\");"; | |
237 base::string16 javascript = base::UTF8ToUTF16(code); | |
238 web_contents()->GetMainFrame()->ExecuteJavaScript(javascript); | |
239 } | |
240 } | 243 } |
241 | 244 |
242 void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( | 245 void ShellDevToolsFrontend::HandleMessageFromDevToolsFrontendToBackend( |
243 const std::string& message) { | 246 const std::string& message) { |
244 if (agent_host_) | 247 if (agent_host_) |
245 agent_host_->DispatchProtocolMessage(message); | 248 agent_host_->DispatchProtocolMessage(message); |
246 } | 249 } |
247 | 250 |
248 void ShellDevToolsFrontend::DispatchProtocolMessage( | 251 void ShellDevToolsFrontend::DispatchProtocolMessage( |
249 DevToolsAgentHost* agent_host, const std::string& message) { | 252 DevToolsAgentHost* agent_host, const std::string& message) { |
(...skipping 28 matching lines...) Expand all Loading... | |
278 net::HttpResponseHeaders* rh = source->GetResponseHeaders(); | 281 net::HttpResponseHeaders* rh = source->GetResponseHeaders(); |
279 response.SetInteger("statusCode", rh ? rh->response_code() : 200); | 282 response.SetInteger("statusCode", rh ? rh->response_code() : 200); |
280 response.Set("headers", headers); | 283 response.Set("headers", headers); |
281 | 284 |
282 void* iterator = NULL; | 285 void* iterator = NULL; |
283 std::string name; | 286 std::string name; |
284 std::string value; | 287 std::string value; |
285 while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) | 288 while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) |
286 headers->SetString(name, value); | 289 headers->SetString(name, value); |
287 | 290 |
288 std::string json; | 291 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); | 292 pending_requests_.erase(it); |
299 delete source; | 293 delete source; |
300 } | 294 } |
301 | 295 |
296 void ShellDevToolsFrontend::CallClientFunction( | |
297 const std::string& function_name, | |
298 const base::Value* arg1, | |
299 const base::Value* arg2, | |
300 const base::Value* arg3) { | |
301 std::string javascript = function_name + "("; | |
302 if (arg1) { | |
303 std::string json; | |
304 base::JSONWriter::Write(arg1, &json); | |
305 javascript.append(json); | |
306 if (arg2) { | |
307 base::JSONWriter::Write(arg2, &json); | |
308 javascript.append(", ").append(json); | |
309 if (arg3) { | |
310 base::JSONWriter::Write(arg3, &json); | |
311 javascript.append(", ").append(json); | |
312 } | |
313 } | |
314 } | |
315 javascript.append(");"); | |
316 web_contents()->GetMainFrame()->ExecuteJavaScript( | |
317 base::UTF8ToUTF16(javascript)); | |
318 } | |
319 | |
320 void ShellDevToolsFrontend::SendMessageAck(int request_id, | |
321 const base::Value* arg) { | |
322 base::FundamentalValue id_value(request_id); | |
323 CallClientFunction("DevToolsAPI.embedderMessageAck", | |
324 &id_value, arg, nullptr); | |
325 } | |
326 | |
302 void ShellDevToolsFrontend::AttachTo(WebContents* inspected_contents) { | 327 void ShellDevToolsFrontend::AttachTo(WebContents* inspected_contents) { |
303 DisconnectFromTarget(); | 328 DisconnectFromTarget(); |
304 agent_host_ = DevToolsAgentHost::GetOrCreateFor(inspected_contents); | 329 agent_host_ = DevToolsAgentHost::GetOrCreateFor(inspected_contents); |
305 } | 330 } |
306 | 331 |
307 void ShellDevToolsFrontend::AgentHostClosed( | 332 void ShellDevToolsFrontend::AgentHostClosed( |
308 DevToolsAgentHost* agent_host, bool replaced) { | 333 DevToolsAgentHost* agent_host, bool replaced) { |
309 frontend_shell_->Close(); | 334 frontend_shell_->Close(); |
310 } | 335 } |
311 | 336 |
312 } // namespace content | 337 } // namespace content |
OLD | NEW |