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
;
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(
94 if (tab_index
!= TabStripModel::kNoTab
)
100 // DevToolsConfirmInfoBarDelegate ---------------------------------------------
102 typedef base::Callback
<void(bool)> InfoBarCallback
;
104 class DevToolsConfirmInfoBarDelegate
: public ConfirmInfoBarDelegate
{
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
);
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
) {
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(),
152 DevToolsConfirmInfoBarDelegate::~DevToolsConfirmInfoBarDelegate() {
153 if (!callback_
.is_null())
154 callback_
.Run(false);
157 base::string16
DevToolsConfirmInfoBarDelegate::GetMessageText() const {
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() {
173 bool DevToolsConfirmInfoBarDelegate::Cancel() {
174 callback_
.Run(false);
179 // DevToolsUIDefaultDelegate --------------------------------------------------
181 class DefaultBindingsDelegate
: public DevToolsUIBindings::Delegate
{
183 explicit DefaultBindingsDelegate(content::WebContents
* web_contents
)
184 : web_contents_(web_contents
) {}
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_
);
232 // DevToolsUIBindings::FrontendWebContentsObserver ----------------------------
234 class DevToolsUIBindings::FrontendWebContentsObserver
235 : public content::WebContentsObserver
{
237 explicit FrontendWebContentsObserver(DevToolsUIBindings
* ui_bindings
);
238 virtual ~FrontendWebContentsObserver();
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 ---------------------------------------------------------
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
)
292 return new DevToolsUIBindings(web_contents
);
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
);
301 std::string
url_string(
303 ((frontend_url
.find("?") == std::string::npos
) ? "?" : "&") +
304 "dockSide=undocked" + // TODO(dgozman): remove this support in M38.
306 SkColorToRGBAString(tp
->GetColor(ThemeProperties::COLOR_TOOLBAR
)) +
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(
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.
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
);
380 void DevToolsUIBindings::DispatchOnEmbedder(const std::string
& message
) {
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
, ¶ms
))) {
392 LOG(ERROR
) << "Invalid message was sent to embedder: " << message
;
397 dict
->GetInteger(kFrontendHostId
, &id
);
400 embedder_message_dispatcher_
->Dispatch(method
, params
, &error
);
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.
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
,
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(
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
);
511 indexing_jobs_
[request_id
] =
512 scoped_refptr
<DevToolsFileSystemIndexer::FileSystemIndexingJob
>(
513 file_system_indexer_
->IndexPath(
515 Bind(&DevToolsUIBindings::IndexingTotalWorkCalculated
,
516 weak_factory_
.GetWeakPtr(),
519 Bind(&DevToolsUIBindings::IndexingWorked
,
520 weak_factory_
.GetWeakPtr(),
523 Bind(&DevToolsUIBindings::IndexingDone
,
524 weak_factory_
.GetWeakPtr(),
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())
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
>());
547 file_system_indexer_
->SearchInPath(file_system_path
,
549 Bind(&DevToolsUIBindings::SearchCompleted
,
550 weak_factory_
.GetWeakPtr(),
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
) {
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
<< "].";
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)),
599 } else if (event_type
== kDeviceCountChanged
) {
600 EnableRemoteDeviceCounter(true);
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
<< "]";
612 subscribers_
.erase(event_type
);
614 if (event_type
== kDevicesChanged
) {
615 remote_targets_handler_
.reset();
616 } else if (event_type
== kDeviceCountChanged
) {
617 EnableRemoteDeviceCounter(false);
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_
);
629 DCHECK(device_listener_enabled_
!= enable
);
630 device_listener_enabled_
= enable
;
632 adb_bridge
->AddDeviceCountListener(this);
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
,
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(
687 const std::string
& file_system_path
,
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
,
698 void DevToolsUIBindings::IndexingWorked(int request_id
,
699 const std::string
& file_system_path
,
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(
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(),
742 void DevToolsUIBindings::UpdateTheme() {
743 ThemeService
* tp
= ThemeServiceFactory::GetForProfile(profile_
);
746 std::string
command("InspectorFrontendAPI.setToolbarColors(\"" +
747 SkColorToRGBAString(tp
->GetColor(ThemeProperties::COLOR_TOOLBAR
)) +
749 SkColorToRGBAString(tp
->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT
)) +
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
)
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())
766 base::DictionaryValue
* extension_info
= new base::DictionaryValue();
769 new base::StringValue(
770 extensions::ManifestURL::GetDevToolsPage(
771 extension
->get()).spec()));
772 extension_info
->Set("name", new base::StringValue((*extension
)->name()));
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
) {
793 base::JSONWriter::Write(arg1
, &json
);
796 base::JSONWriter::Write(arg2
, &json
);
797 params
.append(", " + json
);
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())
814 base::StringValue event_type_value
= base::StringValue(event_type
);
815 CallClientFunction("InspectorFrontendAPI.dispatchEventToListeners",
821 void DevToolsUIBindings::DocumentOnLoadCompletedInMainFrame() {
822 // Call delegate first - it seeds importants bit of information.
823 delegate_
->OnLoadCompleted();
826 AddDevToolsExtensionsToClient();