OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/devtools/devtools_ui_bindings.h" | 5 #include "chrome/browser/devtools/devtools_ui_bindings.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/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 #include "content/public/browser/notification_source.h" | 40 #include "content/public/browser/notification_source.h" |
41 #include "content/public/browser/render_frame_host.h" | 41 #include "content/public/browser/render_frame_host.h" |
42 #include "content/public/browser/render_view_host.h" | 42 #include "content/public/browser/render_view_host.h" |
43 #include "content/public/browser/user_metrics.h" | 43 #include "content/public/browser/user_metrics.h" |
44 #include "content/public/browser/web_contents.h" | 44 #include "content/public/browser/web_contents.h" |
45 #include "content/public/browser/web_contents_observer.h" | 45 #include "content/public/browser/web_contents_observer.h" |
46 #include "content/public/common/renderer_preferences.h" | 46 #include "content/public/common/renderer_preferences.h" |
47 #include "content/public/common/url_constants.h" | 47 #include "content/public/common/url_constants.h" |
48 #include "extensions/browser/extension_registry.h" | 48 #include "extensions/browser/extension_registry.h" |
49 #include "extensions/common/permissions/permissions_data.h" | 49 #include "extensions/common/permissions/permissions_data.h" |
| 50 #include "net/base/io_buffer.h" |
| 51 #include "net/base/net_errors.h" |
| 52 #include "net/http/http_response_headers.h" |
| 53 #include "net/url_request/url_fetcher.h" |
| 54 #include "net/url_request/url_fetcher_response_writer.h" |
50 #include "ui/base/l10n/l10n_util.h" | 55 #include "ui/base/l10n/l10n_util.h" |
51 #include "ui/base/page_transition_types.h" | 56 #include "ui/base/page_transition_types.h" |
52 | 57 |
53 using base::DictionaryValue; | 58 using base::DictionaryValue; |
54 using content::BrowserThread; | 59 using content::BrowserThread; |
55 | 60 |
56 namespace content { | 61 namespace content { |
57 struct LoadCommittedDetails; | 62 struct LoadCommittedDetails; |
58 struct FrameNavigateParams; | 63 struct FrameNavigateParams; |
59 } | 64 } |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 } | 231 } |
227 | 232 |
228 void DefaultBindingsDelegate::InspectedContentsClosing() { | 233 void DefaultBindingsDelegate::InspectedContentsClosing() { |
229 web_contents_->GetRenderViewHost()->ClosePage(); | 234 web_contents_->GetRenderViewHost()->ClosePage(); |
230 } | 235 } |
231 | 236 |
232 InfoBarService* DefaultBindingsDelegate::GetInfoBarService() { | 237 InfoBarService* DefaultBindingsDelegate::GetInfoBarService() { |
233 return InfoBarService::FromWebContents(web_contents_); | 238 return InfoBarService::FromWebContents(web_contents_); |
234 } | 239 } |
235 | 240 |
| 241 // ResponseWriter ------------------------------------------------------------- |
| 242 |
| 243 class ResponseWriter : public net::URLFetcherResponseWriter { |
| 244 public: |
| 245 ResponseWriter(DevToolsUIBindings* bindings, int stream_id); |
| 246 ~ResponseWriter() override; |
| 247 |
| 248 // URLFetcherResponseWriter overrides: |
| 249 int Initialize(const net::CompletionCallback& callback) override; |
| 250 int Write(net::IOBuffer* buffer, |
| 251 int num_bytes, |
| 252 const net::CompletionCallback& callback) override; |
| 253 int Finish(const net::CompletionCallback& callback) override; |
| 254 |
| 255 private: |
| 256 DevToolsUIBindings* bindings_; |
| 257 int stream_id_; |
| 258 |
| 259 DISALLOW_COPY_AND_ASSIGN(ResponseWriter); |
| 260 }; |
| 261 |
| 262 ResponseWriter::ResponseWriter(DevToolsUIBindings* bindings, |
| 263 int stream_id) |
| 264 : bindings_(bindings), |
| 265 stream_id_(stream_id) { |
| 266 } |
| 267 |
| 268 ResponseWriter::~ResponseWriter() { |
| 269 } |
| 270 |
| 271 int ResponseWriter::Initialize(const net::CompletionCallback& callback) { |
| 272 return net::OK; |
| 273 } |
| 274 |
| 275 int ResponseWriter::Write(net::IOBuffer* buffer, |
| 276 int num_bytes, |
| 277 const net::CompletionCallback& callback) { |
| 278 base::FundamentalValue id(stream_id_); |
| 279 base::StringValue chunk(std::string(buffer->data(), num_bytes)); |
| 280 bindings_->CallClientFunction( |
| 281 "DevToolsAPI.streamWrite", &id, &chunk, nullptr); |
| 282 return num_bytes; |
| 283 } |
| 284 |
| 285 int ResponseWriter::Finish(const net::CompletionCallback& callback) { |
| 286 base::FundamentalValue id(stream_id_); |
| 287 bindings_->CallClientFunction( |
| 288 "DevToolsAPI.streamFinish", &id, nullptr, nullptr); |
| 289 return net::OK; |
| 290 } |
| 291 |
236 } // namespace | 292 } // namespace |
237 | 293 |
238 // DevToolsUIBindings::FrontendWebContentsObserver ---------------------------- | 294 // DevToolsUIBindings::FrontendWebContentsObserver ---------------------------- |
239 | 295 |
240 class DevToolsUIBindings::FrontendWebContentsObserver | 296 class DevToolsUIBindings::FrontendWebContentsObserver |
241 : public content::WebContentsObserver { | 297 : public content::WebContentsObserver { |
242 public: | 298 public: |
243 explicit FrontendWebContentsObserver(DevToolsUIBindings* ui_bindings); | 299 explicit FrontendWebContentsObserver(DevToolsUIBindings* ui_bindings); |
244 ~FrontendWebContentsObserver() override; | 300 ~FrontendWebContentsObserver() override; |
245 | 301 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 ThemeServiceFactory::GetForProfile(profile_))); | 432 ThemeServiceFactory::GetForProfile(profile_))); |
377 | 433 |
378 embedder_message_dispatcher_.reset( | 434 embedder_message_dispatcher_.reset( |
379 DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend(this)); | 435 DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend(this)); |
380 | 436 |
381 frontend_host_.reset(content::DevToolsFrontendHost::Create( | 437 frontend_host_.reset(content::DevToolsFrontendHost::Create( |
382 web_contents_->GetMainFrame(), this)); | 438 web_contents_->GetMainFrame(), this)); |
383 } | 439 } |
384 | 440 |
385 DevToolsUIBindings::~DevToolsUIBindings() { | 441 DevToolsUIBindings::~DevToolsUIBindings() { |
| 442 for (const auto& pair : pending_requests_) |
| 443 delete pair.first; |
| 444 |
386 if (agent_host_.get()) | 445 if (agent_host_.get()) |
387 agent_host_->DetachClient(); | 446 agent_host_->DetachClient(); |
388 | 447 |
389 for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin()); | 448 for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin()); |
390 jobs_it != indexing_jobs_.end(); ++jobs_it) { | 449 jobs_it != indexing_jobs_.end(); ++jobs_it) { |
391 jobs_it->second->Stop(); | 450 jobs_it->second->Stop(); |
392 } | 451 } |
393 indexing_jobs_.clear(); | 452 indexing_jobs_.clear(); |
394 SetDeviceCountUpdatesEnabled(0, false); | 453 SetDeviceCountUpdatesEnabled(0, false); |
395 SetDevicesUpdatesEnabled(0, false); | 454 SetDevicesUpdatesEnabled(0, false); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 518 } |
460 | 519 |
461 void DevToolsUIBindings::AgentHostClosed( | 520 void DevToolsUIBindings::AgentHostClosed( |
462 content::DevToolsAgentHost* agent_host, | 521 content::DevToolsAgentHost* agent_host, |
463 bool replaced_with_another_client) { | 522 bool replaced_with_another_client) { |
464 DCHECK(agent_host == agent_host_.get()); | 523 DCHECK(agent_host == agent_host_.get()); |
465 agent_host_ = NULL; | 524 agent_host_ = NULL; |
466 delegate_->InspectedContentsClosing(); | 525 delegate_->InspectedContentsClosing(); |
467 } | 526 } |
468 | 527 |
469 void DevToolsUIBindings::SendMessageAck(int request_id) { | 528 void DevToolsUIBindings::SendMessageAck(int request_id, |
| 529 const base::Value* arg) { |
470 base::FundamentalValue id_value(request_id); | 530 base::FundamentalValue id_value(request_id); |
471 CallClientFunction("DevToolsAPI.embedderMessageAck", | 531 CallClientFunction("DevToolsAPI.embedderMessageAck", |
472 &id_value, nullptr, nullptr); | 532 &id_value, arg, nullptr); |
473 } | 533 } |
474 | 534 |
475 // DevToolsEmbedderMessageDispatcher::Delegate implementation ----------------- | 535 // DevToolsEmbedderMessageDispatcher::Delegate implementation ----------------- |
476 void DevToolsUIBindings::ActivateWindow(int request_id) { | 536 void DevToolsUIBindings::ActivateWindow(int request_id) { |
477 delegate_->ActivateWindow(); | 537 delegate_->ActivateWindow(); |
478 } | 538 } |
479 | 539 |
480 void DevToolsUIBindings::CloseWindow(int request_id) { | 540 void DevToolsUIBindings::CloseWindow(int request_id) { |
481 delegate_->CloseWindow(); | 541 delegate_->CloseWindow(); |
482 } | 542 } |
483 | 543 |
484 void DevToolsUIBindings::LoadCompleted(int request_id) { | 544 void DevToolsUIBindings::LoadCompleted(int request_id) { |
485 FrontendLoaded(); | 545 FrontendLoaded(); |
486 } | 546 } |
487 | 547 |
488 void DevToolsUIBindings::SetInspectedPageBounds(int request_id, | 548 void DevToolsUIBindings::SetInspectedPageBounds(int request_id, |
489 const gfx::Rect& rect) { | 549 const gfx::Rect& rect) { |
490 delegate_->SetInspectedPageBounds(rect); | 550 delegate_->SetInspectedPageBounds(rect); |
491 } | 551 } |
492 | 552 |
493 void DevToolsUIBindings::SetIsDocked(int request_id, bool dock_requested) { | 553 void DevToolsUIBindings::SetIsDocked(int request_id, bool dock_requested) { |
494 delegate_->SetIsDocked(dock_requested); | 554 delegate_->SetIsDocked(dock_requested); |
495 SendMessageAck(request_id); | 555 SendMessageAck(request_id, nullptr); |
496 } | 556 } |
497 | 557 |
498 void DevToolsUIBindings::InspectElementCompleted(int request_id) { | 558 void DevToolsUIBindings::InspectElementCompleted(int request_id) { |
499 delegate_->InspectElementCompleted(); | 559 delegate_->InspectElementCompleted(); |
500 } | 560 } |
501 | 561 |
502 void DevToolsUIBindings::InspectedURLChanged(int request_id, | 562 void DevToolsUIBindings::InspectedURLChanged(int request_id, |
503 const std::string& url) { | 563 const std::string& url) { |
504 content::NavigationController& controller = web_contents()->GetController(); | 564 content::NavigationController& controller = web_contents()->GetController(); |
505 content::NavigationEntry* entry = controller.GetActiveEntry(); | 565 content::NavigationEntry* entry = controller.GetActiveEntry(); |
506 // DevTools UI is not localized. | 566 // DevTools UI is not localized. |
507 entry->SetTitle( | 567 entry->SetTitle( |
508 base::UTF8ToUTF16(base::StringPrintf(kTitleFormat, url.c_str()))); | 568 base::UTF8ToUTF16(base::StringPrintf(kTitleFormat, url.c_str()))); |
509 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE); | 569 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE); |
510 } | 570 } |
511 | 571 |
| 572 void DevToolsUIBindings::LoadNetworkResource(int request_id, |
| 573 const std::string& url, |
| 574 const std::string& headers, |
| 575 int stream_id) { |
| 576 GURL gurl(url); |
| 577 if (!gurl.is_valid()) { |
| 578 base::DictionaryValue response; |
| 579 response.SetInteger("statusCode", 404); |
| 580 SendMessageAck(request_id, &response); |
| 581 return; |
| 582 } |
| 583 |
| 584 net::URLFetcher* fetcher = |
| 585 net::URLFetcher::Create(gurl, net::URLFetcher::GET, this); |
| 586 pending_requests_[fetcher] = request_id; |
| 587 fetcher->SetRequestContext(profile_->GetRequestContext()); |
| 588 fetcher->SetExtraRequestHeaders(headers); |
| 589 fetcher->SaveResponseWithWriter(scoped_ptr<net::URLFetcherResponseWriter>( |
| 590 new ResponseWriter(this, stream_id))); |
| 591 fetcher->Start(); |
| 592 } |
| 593 |
512 void DevToolsUIBindings::OpenInNewTab(int request_id, const std::string& url) { | 594 void DevToolsUIBindings::OpenInNewTab(int request_id, const std::string& url) { |
513 delegate_->OpenInNewTab(url); | 595 delegate_->OpenInNewTab(url); |
514 } | 596 } |
515 | 597 |
516 void DevToolsUIBindings::SaveToFile(int request_id, | 598 void DevToolsUIBindings::SaveToFile(int request_id, |
517 const std::string& url, | 599 const std::string& url, |
518 const std::string& content, | 600 const std::string& content, |
519 bool save_as) { | 601 bool save_as) { |
520 file_helper_->Save(url, content, save_as, | 602 file_helper_->Save(url, content, save_as, |
521 base::Bind(&DevToolsUIBindings::FileSavedAs, | 603 base::Bind(&DevToolsUIBindings::FileSavedAs, |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 | 779 |
698 void DevToolsUIBindings::RecordActionUMA(int request_id, | 780 void DevToolsUIBindings::RecordActionUMA(int request_id, |
699 const std::string& name, | 781 const std::string& name, |
700 int action) { | 782 int action) { |
701 if (name == kDevToolsActionTakenHistogram) | 783 if (name == kDevToolsActionTakenHistogram) |
702 UMA_HISTOGRAM_ENUMERATION(name, action, kDevToolsActionTakenBoundary); | 784 UMA_HISTOGRAM_ENUMERATION(name, action, kDevToolsActionTakenBoundary); |
703 else if (name == kDevToolsPanelShownHistogram) | 785 else if (name == kDevToolsPanelShownHistogram) |
704 UMA_HISTOGRAM_ENUMERATION(name, action, kDevToolsPanelShownBoundary); | 786 UMA_HISTOGRAM_ENUMERATION(name, action, kDevToolsPanelShownBoundary); |
705 } | 787 } |
706 | 788 |
| 789 void DevToolsUIBindings::OnURLFetchComplete(const net::URLFetcher* source) { |
| 790 DCHECK(source); |
| 791 PendingRequestsMap::iterator it = pending_requests_.find(source); |
| 792 DCHECK(it != pending_requests_.end()); |
| 793 |
| 794 base::DictionaryValue response; |
| 795 base::DictionaryValue* headers = new base::DictionaryValue(); |
| 796 net::HttpResponseHeaders* rh = source->GetResponseHeaders(); |
| 797 response.SetInteger("statusCode", rh ? rh->response_code() : 200); |
| 798 response.Set("headers", headers); |
| 799 |
| 800 void* iterator = NULL; |
| 801 std::string name; |
| 802 std::string value; |
| 803 while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) |
| 804 headers->SetString(name, value); |
| 805 |
| 806 SendMessageAck(it->second, &response); |
| 807 pending_requests_.erase(it); |
| 808 delete source; |
| 809 } |
| 810 |
707 void DevToolsUIBindings::DeviceCountChanged(int count) { | 811 void DevToolsUIBindings::DeviceCountChanged(int count) { |
708 base::FundamentalValue value(count); | 812 base::FundamentalValue value(count); |
709 CallClientFunction("DevToolsAPI.deviceCountUpdated", &value, NULL, | 813 CallClientFunction("DevToolsAPI.deviceCountUpdated", &value, NULL, |
710 NULL); | 814 NULL); |
711 } | 815 } |
712 | 816 |
713 void DevToolsUIBindings::DevicesUpdated( | 817 void DevToolsUIBindings::DevicesUpdated( |
714 const std::string& source, | 818 const std::string& source, |
715 const base::ListValue& targets) { | 819 const base::ListValue& targets) { |
716 CallClientFunction("DevToolsAPI.devicesUpdated", &targets, NULL, | 820 CallClientFunction("DevToolsAPI.devicesUpdated", &targets, NULL, |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 if (frontend_loaded_) | 1023 if (frontend_loaded_) |
920 return; | 1024 return; |
921 frontend_loaded_ = true; | 1025 frontend_loaded_ = true; |
922 | 1026 |
923 // Call delegate first - it seeds importants bit of information. | 1027 // Call delegate first - it seeds importants bit of information. |
924 delegate_->OnLoadCompleted(); | 1028 delegate_->OnLoadCompleted(); |
925 | 1029 |
926 UpdateTheme(); | 1030 UpdateTheme(); |
927 AddDevToolsExtensionsToClient(); | 1031 AddDevToolsExtensionsToClient(); |
928 } | 1032 } |
OLD | NEW |