[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / devtools / devtools_ui_bindings.cc
blobbde3a141ad1469c72d0ba2a69ca3258358a06243
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
3 // found in the LICENSE file.
5 #include "chrome/browser/devtools/devtools_ui_bindings.h"
7 #include "base/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chrome_page_zoom.h"
17 #include "chrome/browser/devtools/devtools_target_impl.h"
18 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
21 #include "chrome/browser/infobars/infobar_service.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/themes/theme_properties.h"
24 #include "chrome/browser/themes/theme_service.h"
25 #include "chrome/browser/themes/theme_service_factory.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_iterator.h"
28 #include "chrome/browser/ui/browser_list.h"
29 #include "chrome/browser/ui/browser_window.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/extensions/manifest_url_handler.h"
33 #include "chrome/common/url_constants.h"
34 #include "components/infobars/core/infobar.h"
35 #include "content/public/browser/devtools_client_host.h"
36 #include "content/public/browser/devtools_manager.h"
37 #include "content/public/browser/favicon_status.h"
38 #include "content/public/browser/invalidate_type.h"
39 #include "content/public/browser/navigation_controller.h"
40 #include "content/public/browser/navigation_entry.h"
41 #include "content/public/browser/notification_source.h"
42 #include "content/public/browser/render_frame_host.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/browser/user_metrics.h"
45 #include "content/public/browser/web_contents.h"
46 #include "content/public/browser/web_contents_observer.h"
47 #include "content/public/common/page_transition_types.h"
48 #include "content/public/common/renderer_preferences.h"
49 #include "content/public/common/url_constants.h"
50 #include "extensions/browser/extension_system.h"
51 #include "extensions/common/extension_set.h"
52 #include "grit/generated_resources.h"
53 #include "ui/base/l10n/l10n_util.h"
55 using base::DictionaryValue;
56 using content::BrowserThread;
58 namespace {
60 typedef std::vector<DevToolsUIBindings*> DevToolsUIBindingsList;
61 base::LazyInstance<DevToolsUIBindingsList>::Leaky g_instances =
62 LAZY_INSTANCE_INITIALIZER;
64 static const char kFrontendHostId[] = "id";
65 static const char kFrontendHostMethod[] = "method";
66 static const char kFrontendHostParams[] = "params";
67 static const char kTitleFormat[] = "Developer Tools - %s";
69 static const char kDevicesChanged[] = "DevicesChanged";
70 static const char kDeviceCountChanged[] = "DeviceCountChanged";
72 std::string SkColorToRGBAString(SkColor color) {
73 // We avoid StringPrintf because it will use locale specific formatters for
74 // the double (e.g. ',' instead of '.' in German).
75 return "rgba(" + base::IntToString(SkColorGetR(color)) + "," +
76 base::IntToString(SkColorGetG(color)) + "," +
77 base::IntToString(SkColorGetB(color)) + "," +
78 base::DoubleToString(SkColorGetA(color) / 255.0) + ")";
81 base::DictionaryValue* CreateFileSystemValue(
82 DevToolsFileHelper::FileSystem file_system) {
83 base::DictionaryValue* file_system_value = new base::DictionaryValue();
84 file_system_value->SetString("fileSystemName", file_system.file_system_name);
85 file_system_value->SetString("rootURL", file_system.root_url);
86 file_system_value->SetString("fileSystemPath", file_system.file_system_path);
87 return file_system_value;
90 Browser* FindBrowser(content::WebContents* web_contents) {
91 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
92 int tab_index = it->tab_strip_model()->GetIndexOfWebContents(
93 web_contents);
94 if (tab_index != TabStripModel::kNoTab)
95 return *it;
97 return NULL;
100 // DevToolsConfirmInfoBarDelegate ---------------------------------------------
102 typedef base::Callback<void(bool)> InfoBarCallback;
104 class DevToolsConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
105 public:
106 // If |infobar_service| is NULL, runs |callback| with a single argument with
107 // value "false". Otherwise, creates a dev tools confirm infobar and delegate
108 // and adds the infobar to |infobar_service|.
109 static void Create(InfoBarService* infobar_service,
110 const InfoBarCallback& callback,
111 const base::string16& message);
113 private:
114 DevToolsConfirmInfoBarDelegate(
115 const InfoBarCallback& callback,
116 const base::string16& message);
117 virtual ~DevToolsConfirmInfoBarDelegate();
119 virtual base::string16 GetMessageText() const OVERRIDE;
120 virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
121 virtual bool Accept() OVERRIDE;
122 virtual bool Cancel() OVERRIDE;
124 InfoBarCallback callback_;
125 const base::string16 message_;
127 DISALLOW_COPY_AND_ASSIGN(DevToolsConfirmInfoBarDelegate);
130 void DevToolsConfirmInfoBarDelegate::Create(
131 InfoBarService* infobar_service,
132 const InfoBarCallback& callback,
133 const base::string16& message) {
134 if (!infobar_service) {
135 callback.Run(false);
136 return;
139 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
140 scoped_ptr<ConfirmInfoBarDelegate>(
141 new DevToolsConfirmInfoBarDelegate(callback, message))));
144 DevToolsConfirmInfoBarDelegate::DevToolsConfirmInfoBarDelegate(
145 const InfoBarCallback& callback,
146 const base::string16& message)
147 : ConfirmInfoBarDelegate(),
148 callback_(callback),
149 message_(message) {
152 DevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() {
153 if (!callback_.is_null())
154 callback_.Run(false);
157 base::string16 DevToolsConfirmInfoBarDelegate::GetMessageText() const {
158 return message_;
161 base::string16 DevToolsConfirmInfoBarDelegate::GetButtonLabel(
162 InfoBarButton button) const {
163 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
164 IDS_DEV_TOOLS_CONFIRM_ALLOW_BUTTON : IDS_DEV_TOOLS_CONFIRM_DENY_BUTTON);
167 bool DevToolsConfirmInfoBarDelegate::Accept() {
168 callback_.Run(true);
169 callback_.Reset();
170 return true;
173 bool DevToolsConfirmInfoBarDelegate::Cancel() {
174 callback_.Run(false);
175 callback_.Reset();
176 return true;
179 // DevToolsUIDefaultDelegate --------------------------------------------------
181 class DefaultBindingsDelegate : public DevToolsUIBindings::Delegate {
182 public:
183 explicit DefaultBindingsDelegate(content::WebContents* web_contents)
184 : web_contents_(web_contents) {}
186 private:
187 virtual ~DefaultBindingsDelegate() {}
189 virtual void ActivateWindow() OVERRIDE;
190 virtual void CloseWindow() OVERRIDE {}
191 virtual void SetInspectedPageBounds(const gfx::Rect& rect) OVERRIDE {}
192 virtual void SetContentsResizingStrategy(
193 const gfx::Insets& insets, const gfx::Size& min_size) OVERRIDE {}
194 virtual void InspectElementCompleted() OVERRIDE {}
195 virtual void MoveWindow(int x, int y) OVERRIDE {}
196 virtual void SetIsDocked(bool is_docked) OVERRIDE {}
197 virtual void OpenInNewTab(const std::string& url) OVERRIDE;
198 virtual void SetWhitelistedShortcuts(const std::string& message) OVERRIDE {}
200 virtual void InspectedContentsClosing() OVERRIDE;
201 virtual void OnLoadCompleted() OVERRIDE {}
202 virtual InfoBarService* GetInfoBarService() OVERRIDE;
203 virtual void RenderProcessGone() OVERRIDE {}
205 content::WebContents* web_contents_;
206 DISALLOW_COPY_AND_ASSIGN(DefaultBindingsDelegate);
209 void DefaultBindingsDelegate::ActivateWindow() {
210 web_contents_->GetDelegate()->ActivateContents(web_contents_);
211 web_contents_->Focus();
214 void DefaultBindingsDelegate::OpenInNewTab(const std::string& url) {
215 content::OpenURLParams params(
216 GURL(url), content::Referrer(), NEW_FOREGROUND_TAB,
217 content::PAGE_TRANSITION_LINK, false);
218 Browser* browser = FindBrowser(web_contents_);
219 browser->OpenURL(params);
222 void DefaultBindingsDelegate::InspectedContentsClosing() {
223 web_contents_->GetRenderViewHost()->ClosePage();
226 InfoBarService* DefaultBindingsDelegate::GetInfoBarService() {
227 return InfoBarService::FromWebContents(web_contents_);
230 } // namespace
232 // DevToolsUIBindings::FrontendWebContentsObserver ----------------------------
234 class DevToolsUIBindings::FrontendWebContentsObserver
235 : public content::WebContentsObserver {
236 public:
237 explicit FrontendWebContentsObserver(DevToolsUIBindings* ui_bindings);
238 virtual ~FrontendWebContentsObserver();
240 private:
241 // contents::WebContentsObserver:
242 virtual void WebContentsDestroyed() OVERRIDE;
243 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
244 virtual void AboutToNavigateRenderView(
245 content::RenderViewHost* render_view_host) OVERRIDE;
246 virtual void DocumentOnLoadCompletedInMainFrame() OVERRIDE;
248 DevToolsUIBindings* devtools_bindings_;
249 DISALLOW_COPY_AND_ASSIGN(FrontendWebContentsObserver);
252 DevToolsUIBindings::FrontendWebContentsObserver::FrontendWebContentsObserver(
253 DevToolsUIBindings* devtools_ui_bindings)
254 : WebContentsObserver(devtools_ui_bindings->web_contents()),
255 devtools_bindings_(devtools_ui_bindings) {
258 DevToolsUIBindings::FrontendWebContentsObserver::
259 ~FrontendWebContentsObserver() {
262 void DevToolsUIBindings::FrontendWebContentsObserver::WebContentsDestroyed() {
263 delete devtools_bindings_;
266 void DevToolsUIBindings::FrontendWebContentsObserver::RenderProcessGone(
267 base::TerminationStatus status) {
268 devtools_bindings_->delegate_->RenderProcessGone();
271 void DevToolsUIBindings::FrontendWebContentsObserver::AboutToNavigateRenderView(
272 content::RenderViewHost* render_view_host) {
273 content::DevToolsClientHost::SetupDevToolsFrontendClient(render_view_host);
276 void DevToolsUIBindings::FrontendWebContentsObserver::
277 DocumentOnLoadCompletedInMainFrame() {
278 devtools_bindings_->DocumentOnLoadCompletedInMainFrame();
281 // DevToolsUIBindings ---------------------------------------------------------
283 // static
284 DevToolsUIBindings* DevToolsUIBindings::GetOrCreateFor(
285 content::WebContents* web_contents) {
286 DevToolsUIBindingsList* instances = g_instances.Pointer();
287 for (DevToolsUIBindingsList::iterator it(instances->begin());
288 it != instances->end(); ++it) {
289 if ((*it)->web_contents() == web_contents)
290 return *it;
292 return new DevToolsUIBindings(web_contents);
295 // static
296 GURL DevToolsUIBindings::ApplyThemeToURL(Profile* profile,
297 const GURL& base_url) {
298 std::string frontend_url = base_url.spec();
299 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile);
300 DCHECK(tp);
301 std::string url_string(
302 frontend_url +
303 ((frontend_url.find("?") == std::string::npos) ? "?" : "&") +
304 "dockSide=undocked" + // TODO(dgozman): remove this support in M38.
305 "&toolbarColor=" +
306 SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) +
307 "&textColor=" +
308 SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)));
309 if (CommandLine::ForCurrentProcess()->HasSwitch(
310 switches::kEnableDevToolsExperiments))
311 url_string += "&experiments=true";
312 return GURL(url_string);
315 DevToolsUIBindings::DevToolsUIBindings(content::WebContents* web_contents)
316 : profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
317 web_contents_(web_contents),
318 delegate_(new DefaultBindingsDelegate(web_contents_)),
319 device_listener_enabled_(false),
320 weak_factory_(this) {
321 g_instances.Get().push_back(this);
322 frontend_contents_observer_.reset(new FrontendWebContentsObserver(this));
323 web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false;
325 frontend_host_.reset(content::DevToolsClientHost::CreateDevToolsFrontendHost(
326 web_contents_, this));
327 file_helper_.reset(new DevToolsFileHelper(web_contents_, profile_));
328 file_system_indexer_ = new DevToolsFileSystemIndexer();
329 extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
330 web_contents_);
332 // Wipe out page icon so that the default application icon is used.
333 content::NavigationEntry* entry =
334 web_contents_->GetController().GetActiveEntry();
335 entry->GetFavicon().image = gfx::Image();
336 entry->GetFavicon().valid = true;
338 // Register on-load actions.
339 registrar_.Add(
340 this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
341 content::Source<ThemeService>(
342 ThemeServiceFactory::GetForProfile(profile_)));
344 embedder_message_dispatcher_.reset(
345 DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(this));
348 DevToolsUIBindings::~DevToolsUIBindings() {
349 content::DevToolsManager::GetInstance()->ClientHostClosing(
350 frontend_host_.get());
352 for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin());
353 jobs_it != indexing_jobs_.end(); ++jobs_it) {
354 jobs_it->second->Stop();
356 indexing_jobs_.clear();
358 while (!subscribers_.empty())
359 Unsubscribe(*subscribers_.begin());
361 // Remove self from global list.
362 DevToolsUIBindingsList* instances = g_instances.Pointer();
363 DevToolsUIBindingsList::iterator it(
364 std::find(instances->begin(), instances->end(), this));
365 DCHECK(it != instances->end());
366 instances->erase(it);
369 void DevToolsUIBindings::InspectedContentsClosing() {
370 delegate_->InspectedContentsClosing();
373 void DevToolsUIBindings::Observe(int type,
374 const content::NotificationSource& source,
375 const content::NotificationDetails& details) {
376 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
377 UpdateTheme();
380 void DevToolsUIBindings::DispatchOnEmbedder(const std::string& message) {
381 std::string method;
382 base::ListValue empty_params;
383 base::ListValue* params = &empty_params;
385 base::DictionaryValue* dict = NULL;
386 scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
387 if (!parsed_message ||
388 !parsed_message->GetAsDictionary(&dict) ||
389 !dict->GetString(kFrontendHostMethod, &method) ||
390 (dict->HasKey(kFrontendHostParams) &&
391 !dict->GetList(kFrontendHostParams, &params))) {
392 LOG(ERROR) << "Invalid message was sent to embedder: " << message;
393 return;
396 int id = 0;
397 dict->GetInteger(kFrontendHostId, &id);
399 std::string error;
400 embedder_message_dispatcher_->Dispatch(method, params, &error);
401 if (id) {
402 scoped_ptr<base::Value> id_value(base::Value::CreateIntegerValue(id));
403 scoped_ptr<base::Value> error_value(base::Value::CreateStringValue(error));
404 CallClientFunction("InspectorFrontendAPI.embedderMessageAck",
405 id_value.get(), error_value.get(), NULL);
409 void DevToolsUIBindings::ActivateWindow() {
410 delegate_->ActivateWindow();
413 void DevToolsUIBindings::CloseWindow() {
414 delegate_->CloseWindow();
417 void DevToolsUIBindings::SetInspectedPageBounds(const gfx::Rect& rect) {
418 delegate_->SetInspectedPageBounds(rect);
421 void DevToolsUIBindings::SetContentsResizingStrategy(
422 const gfx::Insets& insets, const gfx::Size& min_size) {
423 delegate_->SetContentsResizingStrategy(insets, min_size);
426 void DevToolsUIBindings::MoveWindow(int x, int y) {
427 delegate_->MoveWindow(x, y);
430 void DevToolsUIBindings::SetIsDocked(bool dock_requested) {
431 delegate_->SetIsDocked(dock_requested);
434 void DevToolsUIBindings::InspectElementCompleted() {
435 delegate_->InspectElementCompleted();
438 void DevToolsUIBindings::InspectedURLChanged(const std::string& url) {
439 content::NavigationController& controller = web_contents()->GetController();
440 content::NavigationEntry* entry = controller.GetActiveEntry();
441 // DevTools UI is not localized.
442 entry->SetTitle(
443 base::UTF8ToUTF16(base::StringPrintf(kTitleFormat, url.c_str())));
444 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE);
447 void DevToolsUIBindings::OpenInNewTab(const std::string& url) {
448 delegate_->OpenInNewTab(url);
451 void DevToolsUIBindings::SaveToFile(const std::string& url,
452 const std::string& content,
453 bool save_as) {
454 file_helper_->Save(url, content, save_as,
455 base::Bind(&DevToolsUIBindings::FileSavedAs,
456 weak_factory_.GetWeakPtr(), url),
457 base::Bind(&DevToolsUIBindings::CanceledFileSaveAs,
458 weak_factory_.GetWeakPtr(), url));
461 void DevToolsUIBindings::AppendToFile(const std::string& url,
462 const std::string& content) {
463 file_helper_->Append(url, content,
464 base::Bind(&DevToolsUIBindings::AppendedTo,
465 weak_factory_.GetWeakPtr(), url));
468 void DevToolsUIBindings::RequestFileSystems() {
469 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
470 file_helper_->RequestFileSystems(base::Bind(
471 &DevToolsUIBindings::FileSystemsLoaded, weak_factory_.GetWeakPtr()));
474 void DevToolsUIBindings::AddFileSystem() {
475 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
476 file_helper_->AddFileSystem(
477 base::Bind(&DevToolsUIBindings::FileSystemAdded,
478 weak_factory_.GetWeakPtr()),
479 base::Bind(&DevToolsUIBindings::ShowDevToolsConfirmInfoBar,
480 weak_factory_.GetWeakPtr()));
483 void DevToolsUIBindings::RemoveFileSystem(
484 const std::string& file_system_path) {
485 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
486 file_helper_->RemoveFileSystem(file_system_path);
487 base::StringValue file_system_path_value(file_system_path);
488 CallClientFunction("InspectorFrontendAPI.fileSystemRemoved",
489 &file_system_path_value, NULL, NULL);
492 void DevToolsUIBindings::UpgradeDraggedFileSystemPermissions(
493 const std::string& file_system_url) {
494 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
495 file_helper_->UpgradeDraggedFileSystemPermissions(
496 file_system_url,
497 base::Bind(&DevToolsUIBindings::FileSystemAdded,
498 weak_factory_.GetWeakPtr()),
499 base::Bind(&DevToolsUIBindings::ShowDevToolsConfirmInfoBar,
500 weak_factory_.GetWeakPtr()));
503 void DevToolsUIBindings::IndexPath(int request_id,
504 const std::string& file_system_path) {
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
506 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
507 if (!file_helper_->IsFileSystemAdded(file_system_path)) {
508 IndexingDone(request_id, file_system_path);
509 return;
511 indexing_jobs_[request_id] =
512 scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
513 file_system_indexer_->IndexPath(
514 file_system_path,
515 Bind(&DevToolsUIBindings::IndexingTotalWorkCalculated,
516 weak_factory_.GetWeakPtr(),
517 request_id,
518 file_system_path),
519 Bind(&DevToolsUIBindings::IndexingWorked,
520 weak_factory_.GetWeakPtr(),
521 request_id,
522 file_system_path),
523 Bind(&DevToolsUIBindings::IndexingDone,
524 weak_factory_.GetWeakPtr(),
525 request_id,
526 file_system_path)));
529 void DevToolsUIBindings::StopIndexing(int request_id) {
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
531 IndexingJobsMap::iterator it = indexing_jobs_.find(request_id);
532 if (it == indexing_jobs_.end())
533 return;
534 it->second->Stop();
535 indexing_jobs_.erase(it);
538 void DevToolsUIBindings::SearchInPath(int request_id,
539 const std::string& file_system_path,
540 const std::string& query) {
541 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
542 CHECK(web_contents_->GetURL().SchemeIs(content::kChromeDevToolsScheme));
543 if (!file_helper_->IsFileSystemAdded(file_system_path)) {
544 SearchCompleted(request_id, file_system_path, std::vector<std::string>());
545 return;
547 file_system_indexer_->SearchInPath(file_system_path,
548 query,
549 Bind(&DevToolsUIBindings::SearchCompleted,
550 weak_factory_.GetWeakPtr(),
551 request_id,
552 file_system_path));
555 void DevToolsUIBindings::SetWhitelistedShortcuts(
556 const std::string& message) {
557 delegate_->SetWhitelistedShortcuts(message);
560 void DevToolsUIBindings::ZoomIn() {
561 chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_IN);
564 void DevToolsUIBindings::ZoomOut() {
565 chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_OUT);
568 void DevToolsUIBindings::ResetZoom() {
569 chrome_page_zoom::Zoom(web_contents(), content::PAGE_ZOOM_RESET);
572 static void InspectTarget(Profile* profile, DevToolsTargetImpl* target) {
573 if (target)
574 target->Inspect(profile);
577 void DevToolsUIBindings::OpenUrlOnRemoteDeviceAndInspect(
578 const std::string& browser_id,
579 const std::string& url) {
580 if (remote_targets_handler_) {
581 remote_targets_handler_->Open(browser_id, url,
582 base::Bind(&InspectTarget, profile_));
586 void DevToolsUIBindings::Subscribe(const std::string& event_type) {
587 if (subscribers_.find(event_type) != subscribers_.end()) {
588 LOG(ERROR) << "Already subscribed for [" << event_type << "].";
589 return;
592 subscribers_.insert(event_type);
594 if (event_type == kDevicesChanged) {
595 remote_targets_handler_ = DevToolsTargetsUIHandler::CreateForAdb(
596 base::Bind(&DevToolsUIBindings::PopulateRemoteDevices,
597 base::Unretained(this)),
598 profile_);
599 } else if (event_type == kDeviceCountChanged) {
600 EnableRemoteDeviceCounter(true);
601 } else {
602 LOG(ERROR) << "Attempt to start unknown event listener " << event_type;
606 void DevToolsUIBindings::Unsubscribe(const std::string& event_type) {
607 if (subscribers_.find(event_type) == subscribers_.end()) {
608 LOG(ERROR) << "Not yet subscribed for [" << event_type << "]";
609 return;
612 subscribers_.erase(event_type);
614 if (event_type == kDevicesChanged) {
615 remote_targets_handler_.reset();
616 } else if (event_type == kDeviceCountChanged) {
617 EnableRemoteDeviceCounter(false);
618 } else {
619 LOG(ERROR) << "Attempt to stop unknown event listener " << event_type;
623 void DevToolsUIBindings::EnableRemoteDeviceCounter(bool enable) {
624 DevToolsAndroidBridge* adb_bridge =
625 DevToolsAndroidBridge::Factory::GetForProfile(profile_);
626 if (!adb_bridge)
627 return;
629 DCHECK(device_listener_enabled_ != enable);
630 device_listener_enabled_ = enable;
631 if (enable)
632 adb_bridge->AddDeviceCountListener(this);
633 else
634 adb_bridge->RemoveDeviceCountListener(this);
637 void DevToolsUIBindings::DeviceCountChanged(int count) {
638 base::FundamentalValue value(count);
639 DispatchEventOnFrontend(kDeviceCountChanged, &value);
642 void DevToolsUIBindings::PopulateRemoteDevices(
643 const std::string& source,
644 scoped_ptr<base::ListValue> targets) {
645 DispatchEventOnFrontend(kDevicesChanged, targets.get());
648 void DevToolsUIBindings::FileSavedAs(const std::string& url) {
649 base::StringValue url_value(url);
650 CallClientFunction("InspectorFrontendAPI.savedURL", &url_value, NULL, NULL);
653 void DevToolsUIBindings::CanceledFileSaveAs(const std::string& url) {
654 base::StringValue url_value(url);
655 CallClientFunction("InspectorFrontendAPI.canceledSaveURL",
656 &url_value, NULL, NULL);
659 void DevToolsUIBindings::AppendedTo(const std::string& url) {
660 base::StringValue url_value(url);
661 CallClientFunction("InspectorFrontendAPI.appendedToURL", &url_value, NULL,
662 NULL);
665 void DevToolsUIBindings::FileSystemsLoaded(
666 const std::vector<DevToolsFileHelper::FileSystem>& file_systems) {
667 base::ListValue file_systems_value;
668 for (size_t i = 0; i < file_systems.size(); ++i)
669 file_systems_value.Append(CreateFileSystemValue(file_systems[i]));
670 CallClientFunction("InspectorFrontendAPI.fileSystemsLoaded",
671 &file_systems_value, NULL, NULL);
674 void DevToolsUIBindings::FileSystemAdded(
675 const DevToolsFileHelper::FileSystem& file_system) {
676 scoped_ptr<base::StringValue> error_string_value(
677 new base::StringValue(std::string()));
678 scoped_ptr<base::DictionaryValue> file_system_value;
679 if (!file_system.file_system_path.empty())
680 file_system_value.reset(CreateFileSystemValue(file_system));
681 CallClientFunction("InspectorFrontendAPI.fileSystemAdded",
682 error_string_value.get(), file_system_value.get(), NULL);
685 void DevToolsUIBindings::IndexingTotalWorkCalculated(
686 int request_id,
687 const std::string& file_system_path,
688 int total_work) {
689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
690 base::FundamentalValue request_id_value(request_id);
691 base::StringValue file_system_path_value(file_system_path);
692 base::FundamentalValue total_work_value(total_work);
693 CallClientFunction("InspectorFrontendAPI.indexingTotalWorkCalculated",
694 &request_id_value, &file_system_path_value,
695 &total_work_value);
698 void DevToolsUIBindings::IndexingWorked(int request_id,
699 const std::string& file_system_path,
700 int worked) {
701 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
702 base::FundamentalValue request_id_value(request_id);
703 base::StringValue file_system_path_value(file_system_path);
704 base::FundamentalValue worked_value(worked);
705 CallClientFunction("InspectorFrontendAPI.indexingWorked", &request_id_value,
706 &file_system_path_value, &worked_value);
709 void DevToolsUIBindings::IndexingDone(int request_id,
710 const std::string& file_system_path) {
711 indexing_jobs_.erase(request_id);
712 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
713 base::FundamentalValue request_id_value(request_id);
714 base::StringValue file_system_path_value(file_system_path);
715 CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value,
716 &file_system_path_value, NULL);
719 void DevToolsUIBindings::SearchCompleted(
720 int request_id,
721 const std::string& file_system_path,
722 const std::vector<std::string>& file_paths) {
723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
724 base::ListValue file_paths_value;
725 for (std::vector<std::string>::const_iterator it(file_paths.begin());
726 it != file_paths.end(); ++it) {
727 file_paths_value.AppendString(*it);
729 base::FundamentalValue request_id_value(request_id);
730 base::StringValue file_system_path_value(file_system_path);
731 CallClientFunction("InspectorFrontendAPI.searchCompleted", &request_id_value,
732 &file_system_path_value, &file_paths_value);
735 void DevToolsUIBindings::ShowDevToolsConfirmInfoBar(
736 const base::string16& message,
737 const InfoBarCallback& callback) {
738 DevToolsConfirmInfoBarDelegate::Create(delegate_->GetInfoBarService(),
739 callback, message);
742 void DevToolsUIBindings::UpdateTheme() {
743 ThemeService* tp = ThemeServiceFactory::GetForProfile(profile_);
744 DCHECK(tp);
746 std::string command("InspectorFrontendAPI.setToolbarColors(\"" +
747 SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_TOOLBAR)) +
748 "\", \"" +
749 SkColorToRGBAString(tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)) +
750 "\")");
751 web_contents_->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(command));
754 void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
755 const ExtensionService* extension_service = extensions::ExtensionSystem::Get(
756 profile_->GetOriginalProfile())->extension_service();
757 if (!extension_service)
758 return;
759 const extensions::ExtensionSet* extensions = extension_service->extensions();
761 base::ListValue results;
762 for (extensions::ExtensionSet::const_iterator extension(extensions->begin());
763 extension != extensions->end(); ++extension) {
764 if (extensions::ManifestURL::GetDevToolsPage(extension->get()).is_empty())
765 continue;
766 base::DictionaryValue* extension_info = new base::DictionaryValue();
767 extension_info->Set(
768 "startPage",
769 new base::StringValue(
770 extensions::ManifestURL::GetDevToolsPage(
771 extension->get()).spec()));
772 extension_info->Set("name", new base::StringValue((*extension)->name()));
773 extension_info->Set(
774 "exposeExperimentalAPIs",
775 new base::FundamentalValue((*extension)->HasAPIPermission(
776 extensions::APIPermission::kExperimental)));
777 results.Append(extension_info);
779 CallClientFunction("WebInspector.addExtensions", &results, NULL, NULL);
782 void DevToolsUIBindings::SetDelegate(Delegate* delegate) {
783 delegate_.reset(delegate);
786 void DevToolsUIBindings::CallClientFunction(const std::string& function_name,
787 const base::Value* arg1,
788 const base::Value* arg2,
789 const base::Value* arg3) {
790 std::string params;
791 if (arg1) {
792 std::string json;
793 base::JSONWriter::Write(arg1, &json);
794 params.append(json);
795 if (arg2) {
796 base::JSONWriter::Write(arg2, &json);
797 params.append(", " + json);
798 if (arg3) {
799 base::JSONWriter::Write(arg3, &json);
800 params.append(", " + json);
804 base::string16 javascript =
805 base::UTF8ToUTF16(function_name + "(" + params + ");");
806 web_contents_->GetMainFrame()->ExecuteJavaScript(javascript);
809 void DevToolsUIBindings::DispatchEventOnFrontend(
810 const std::string& event_type,
811 const base::Value* event_data) {
812 if (subscribers_.find(event_type) == subscribers_.end())
813 return;
814 base::StringValue event_type_value = base::StringValue(event_type);
815 CallClientFunction("InspectorFrontendAPI.dispatchEventToListeners",
816 &event_type_value,
817 event_data,
818 NULL);
821 void DevToolsUIBindings::DocumentOnLoadCompletedInMainFrame() {
822 // Call delegate first - it seeds importants bit of information.
823 delegate_->OnLoadCompleted();
825 UpdateTheme();
826 AddDevToolsExtensionsToClient();