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

Side by Side Diff: content/shell/browser/shell_devtools_frontend.cc

Issue 969573002: DevTools: response writers need to post to the UI while sending into streams. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@loadNetwork
Patch Set: using weak ptrs. Created 5 years, 9 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
« no previous file with comments | « content/shell/browser/shell_devtools_frontend.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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
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
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", &params); 199 dict->GetList("params", &params);
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
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
OLDNEW
« no previous file with comments | « content/shell/browser/shell_devtools_frontend.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698