| 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 |