inspect_ui.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi// Use of this source code is governed by a BSD-style license that can be
3d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi// found in the LICENSE file.
4d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
5d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/ui/webui/inspect_ui.h"
6d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
7d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "base/prefs/pref_service.h"
8d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "base/stl_util.h"
9d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/devtools/devtools_target_impl.h"
10d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/devtools/devtools_targets_ui.h"
11d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/devtools/devtools_ui_bindings.h"
12d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/profiles/profile.h"
13d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/ui/browser_navigator.h"
14d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/ui/singleton_tabs.h"
15d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/browser/ui/webui/theme_source.h"
16d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/common/pref_names.h"
17d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "chrome/common/url_constants.h"
18d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/devtools_agent_host.h"
19d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/navigation_entry.h"
20d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/notification_service.h"
21d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/notification_source.h"
22d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/notification_types.h"
23d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/user_metrics.h"
24d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/web_contents.h"
25d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/web_contents_delegate.h"
26d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/web_contents_observer.h"
27d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/web_ui.h"
28d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "content/public/browser/web_ui_data_source.h"
29dc549d60f98d809f626c99de614960409a847054Takeshi Aimi#include "content/public/browser/web_ui_message_handler.h"
30d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi#include "grit/browser_resources.h"
31d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
32d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiusing content::WebContents;
33dc549d60f98d809f626c99de614960409a847054Takeshi Aimiusing content::WebUIMessageHandler;
34d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
35d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshinamespace {
36d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
37dc549d60f98d809f626c99de614960409a847054Takeshi Aimiconst char kInitUICommand[]  = "init-ui";
38d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kInspectCommand[]  = "inspect";
39d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kActivateCommand[]  = "activate";
40d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kCloseCommand[]  = "close";
41d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kReloadCommand[]  = "reload";
42dc549d60f98d809f626c99de614960409a847054Takeshi Aimiconst char kOpenCommand[]  = "open";
43d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kInspectBrowser[] = "inspect-browser";
44dc549d60f98d809f626c99de614960409a847054Takeshi Aimiconst char kLocalHost[] = "localhost";
45dc549d60f98d809f626c99de614960409a847054Takeshi Aimi
46d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kDiscoverUsbDevicesEnabledCommand[] =
47dc549d60f98d809f626c99de614960409a847054Takeshi Aimi    "set-discover-usb-devices-enabled";
48d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kPortForwardingEnabledCommand[] =
49d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi    "set-port-forwarding-enabled";
50d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kPortForwardingConfigCommand[] = "set-port-forwarding-config";
51d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
52d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kPortForwardingDefaultPort[] = "8080";
53d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiconst char kPortForwardingDefaultLocation[] = "localhost:8080";
54d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
55d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi// InspectMessageHandler --------------------------------------------
56d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi
57d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshiclass InspectMessageHandler : public WebUIMessageHandler {
58d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi public:
59d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi  explicit InspectMessageHandler(InspectUI* inspect_ui)
60d074e30ce44b9e33da43b67a4515b8986ca72b26aimitakeshi      : inspect_ui_(inspect_ui) {}
61  virtual ~InspectMessageHandler() {}
62
63 private:
64  // WebUIMessageHandler implementation.
65  virtual void RegisterMessages() OVERRIDE;
66
67  void HandleInitUICommand(const base::ListValue* args);
68  void HandleInspectCommand(const base::ListValue* args);
69  void HandleActivateCommand(const base::ListValue* args);
70  void HandleCloseCommand(const base::ListValue* args);
71  void HandleReloadCommand(const base::ListValue* args);
72  void HandleOpenCommand(const base::ListValue* args);
73  void HandleInspectBrowserCommand(const base::ListValue* args);
74  void HandleBooleanPrefChanged(const char* pref_name,
75                                const base::ListValue* args);
76  void HandlePortForwardingConfigCommand(const base::ListValue* args);
77
78  InspectUI* inspect_ui_;
79
80  DISALLOW_COPY_AND_ASSIGN(InspectMessageHandler);
81};
82
83void InspectMessageHandler::RegisterMessages() {
84  web_ui()->RegisterMessageCallback(kInitUICommand,
85      base::Bind(&InspectMessageHandler::HandleInitUICommand,
86                 base::Unretained(this)));
87  web_ui()->RegisterMessageCallback(kInspectCommand,
88      base::Bind(&InspectMessageHandler::HandleInspectCommand,
89                 base::Unretained(this)));
90  web_ui()->RegisterMessageCallback(kActivateCommand,
91      base::Bind(&InspectMessageHandler::HandleActivateCommand,
92                 base::Unretained(this)));
93  web_ui()->RegisterMessageCallback(kCloseCommand,
94      base::Bind(&InspectMessageHandler::HandleCloseCommand,
95                 base::Unretained(this)));
96  web_ui()->RegisterMessageCallback(kDiscoverUsbDevicesEnabledCommand,
97      base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged,
98                  base::Unretained(this),
99                  &prefs::kDevToolsDiscoverUsbDevicesEnabled[0]));
100  web_ui()->RegisterMessageCallback(kPortForwardingEnabledCommand,
101      base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged,
102                 base::Unretained(this),
103                 &prefs::kDevToolsPortForwardingEnabled[0]));
104  web_ui()->RegisterMessageCallback(kPortForwardingConfigCommand,
105      base::Bind(&InspectMessageHandler::HandlePortForwardingConfigCommand,
106                 base::Unretained(this)));
107  web_ui()->RegisterMessageCallback(kReloadCommand,
108      base::Bind(&InspectMessageHandler::HandleReloadCommand,
109                 base::Unretained(this)));
110  web_ui()->RegisterMessageCallback(kOpenCommand,
111      base::Bind(&InspectMessageHandler::HandleOpenCommand,
112                 base::Unretained(this)));
113  web_ui()->RegisterMessageCallback(kInspectBrowser,
114      base::Bind(&InspectMessageHandler::HandleInspectBrowserCommand,
115                 base::Unretained(this)));
116}
117
118void InspectMessageHandler::HandleInitUICommand(const base::ListValue*) {
119  inspect_ui_->InitUI();
120}
121
122static bool ParseStringArgs(const base::ListValue* args,
123                            std::string* arg0,
124                            std::string* arg1,
125                            std::string* arg2 = 0) {
126  int arg_size = args->GetSize();
127  return (!arg0 || (arg_size > 0 && args->GetString(0, arg0))) &&
128         (!arg1 || (arg_size > 1 && args->GetString(1, arg1))) &&
129         (!arg2 || (arg_size > 2 && args->GetString(2, arg2)));
130}
131
132void InspectMessageHandler::HandleInspectCommand(const base::ListValue* args) {
133  std::string source;
134  std::string id;
135  if (ParseStringArgs(args, &source, &id))
136    inspect_ui_->Inspect(source, id);
137}
138
139void InspectMessageHandler::HandleActivateCommand(const base::ListValue* args) {
140  std::string source;
141  std::string id;
142  if (ParseStringArgs(args, &source, &id))
143    inspect_ui_->Activate(source, id);
144}
145
146void InspectMessageHandler::HandleCloseCommand(const base::ListValue* args) {
147  std::string source;
148  std::string id;
149  if (ParseStringArgs(args, &source, &id))
150    inspect_ui_->Close(source, id);
151}
152
153void InspectMessageHandler::HandleReloadCommand(const base::ListValue* args) {
154  std::string source;
155  std::string id;
156  if (ParseStringArgs(args, &source, &id))
157    inspect_ui_->Reload(source, id);
158}
159
160void InspectMessageHandler::HandleOpenCommand(const base::ListValue* args) {
161  std::string source_id;
162  std::string browser_id;
163  std::string url;
164  if (ParseStringArgs(args, &source_id, &browser_id, &url))
165    inspect_ui_->Open(source_id, browser_id, url);
166}
167
168void InspectMessageHandler::HandleInspectBrowserCommand(
169    const base::ListValue* args) {
170  std::string source_id;
171  std::string browser_id;
172  std::string front_end;
173  if (ParseStringArgs(args, &source_id, &browser_id, &front_end)) {
174    inspect_ui_->InspectBrowserWithCustomFrontend(
175        source_id, browser_id, GURL(front_end));
176  }
177}
178
179void InspectMessageHandler::HandleBooleanPrefChanged(
180    const char* pref_name,
181    const base::ListValue* args) {
182  Profile* profile = Profile::FromWebUI(web_ui());
183  if (!profile)
184    return;
185
186  bool enabled;
187  if (args->GetSize() == 1 && args->GetBoolean(0, &enabled))
188    profile->GetPrefs()->SetBoolean(pref_name, enabled);
189}
190
191void InspectMessageHandler::HandlePortForwardingConfigCommand(
192    const base::ListValue* args) {
193  Profile* profile = Profile::FromWebUI(web_ui());
194  if (!profile)
195    return;
196
197  const base::DictionaryValue* dict_src;
198  if (args->GetSize() == 1 && args->GetDictionary(0, &dict_src))
199    profile->GetPrefs()->Set(prefs::kDevToolsPortForwardingConfig, *dict_src);
200}
201
202// DevToolsUIBindingsEnabler ----------------------------------------
203
204class DevToolsUIBindingsEnabler
205    : public content::WebContentsObserver {
206 public:
207  DevToolsUIBindingsEnabler(WebContents* web_contents,
208                            const GURL& url);
209  virtual ~DevToolsUIBindingsEnabler() {}
210
211  DevToolsUIBindings* GetBindings();
212
213 private:
214  // contents::WebContentsObserver overrides.
215  virtual void WebContentsDestroyed() OVERRIDE;
216  virtual void AboutToNavigateRenderView(
217      content::RenderViewHost* render_view_host) OVERRIDE;
218
219  DevToolsUIBindings bindings_;
220  GURL url_;
221  DISALLOW_COPY_AND_ASSIGN(DevToolsUIBindingsEnabler);
222};
223
224DevToolsUIBindingsEnabler::DevToolsUIBindingsEnabler(
225    WebContents* web_contents,
226    const GURL& url)
227    : WebContentsObserver(web_contents),
228      bindings_(web_contents),
229      url_(url) {
230}
231
232DevToolsUIBindings* DevToolsUIBindingsEnabler::GetBindings() {
233  return &bindings_;
234}
235
236void DevToolsUIBindingsEnabler::WebContentsDestroyed() {
237  delete this;
238}
239
240void DevToolsUIBindingsEnabler::AboutToNavigateRenderView(
241    content::RenderViewHost* render_view_host) {
242   content::NavigationEntry* entry =
243       web_contents()->GetController().GetActiveEntry();
244   if (url_ != entry->GetURL())
245     delete this;
246}
247
248}  // namespace
249
250// InspectUI --------------------------------------------------------
251
252InspectUI::InspectUI(content::WebUI* web_ui)
253    : WebUIController(web_ui) {
254  web_ui->AddMessageHandler(new InspectMessageHandler(this));
255  Profile* profile = Profile::FromWebUI(web_ui);
256  content::WebUIDataSource::Add(profile, CreateInspectUIHTMLSource());
257
258  // Set up the chrome://theme/ source.
259  ThemeSource* theme = new ThemeSource(profile);
260  content::URLDataSource::Add(profile, theme);
261}
262
263InspectUI::~InspectUI() {
264  StopListeningNotifications();
265}
266
267void InspectUI::InitUI() {
268  SetPortForwardingDefaults();
269  StartListeningNotifications();
270  UpdateDiscoverUsbDevicesEnabled();
271  UpdatePortForwardingEnabled();
272  UpdatePortForwardingConfig();
273}
274
275void InspectUI::Inspect(const std::string& source_id,
276                        const std::string& target_id) {
277  DevToolsTargetImpl* target = FindTarget(source_id, target_id);
278  if (target) {
279    const std::string target_type = target->GetType();
280    target->Inspect(Profile::FromWebUI(web_ui()));
281    ForceUpdateIfNeeded(source_id, target_type);
282  }
283}
284
285void InspectUI::Activate(const std::string& source_id,
286                         const std::string& target_id) {
287  DevToolsTargetImpl* target = FindTarget(source_id, target_id);
288  if (target) {
289    const std::string target_type = target->GetType();
290    target->Activate();
291    ForceUpdateIfNeeded(source_id, target_type);
292  }
293}
294
295void InspectUI::Close(const std::string& source_id,
296                      const std::string& target_id) {
297  DevToolsTargetImpl* target = FindTarget(source_id, target_id);
298  if (target) {
299    const std::string target_type = target->GetType();
300    target->Close();
301    ForceUpdateIfNeeded(source_id, target_type);
302  }
303}
304
305void InspectUI::Reload(const std::string& source_id,
306                       const std::string& target_id) {
307  DevToolsTargetImpl* target = FindTarget(source_id, target_id);
308  if (target) {
309    const std::string target_type = target->GetType();
310    target->Reload();
311    ForceUpdateIfNeeded(source_id, target_type);
312  }
313}
314
315static void NoOp(DevToolsTargetImpl*) {}
316
317void InspectUI::Open(const std::string& source_id,
318                     const std::string& browser_id,
319                     const std::string& url) {
320  DevToolsTargetsUIHandler* handler = FindTargetHandler(source_id);
321  if (handler)
322    handler->Open(browser_id, url, base::Bind(&NoOp));
323}
324
325void InspectUI::InspectBrowserWithCustomFrontend(
326    const std::string& source_id,
327    const std::string& browser_id,
328    const GURL& frontend_url) {
329  if (!frontend_url.SchemeIs(content::kChromeUIScheme) &&
330      !frontend_url.SchemeIs(content::kChromeDevToolsScheme) &&
331      frontend_url.host() != kLocalHost) {
332    return;
333  }
334
335  DevToolsTargetsUIHandler* handler = FindTargetHandler(source_id);
336  if (!handler)
337    return;
338
339  // Fetch agent host from remote browser.
340  scoped_refptr<content::DevToolsAgentHost> agent_host =
341      handler->GetBrowserAgentHost(browser_id);
342  if (agent_host->IsAttached())
343    return;
344
345  // Create web contents for the front-end.
346  WebContents* inspect_ui = web_ui()->GetWebContents();
347  WebContents* front_end = inspect_ui->GetDelegate()->OpenURLFromTab(
348      inspect_ui,
349      content::OpenURLParams(frontend_url,
350                             content::Referrer(),
351                             NEW_FOREGROUND_TAB,
352                             ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
353                             false));
354
355  // Install devtools bindings.
356  DevToolsUIBindingsEnabler* bindings_enabler =
357      new DevToolsUIBindingsEnabler(front_end, frontend_url);
358  bindings_enabler->GetBindings()->AttachTo(agent_host);
359}
360
361void InspectUI::InspectDevices(Browser* browser) {
362  content::RecordAction(base::UserMetricsAction("InspectDevices"));
363  chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
364      browser, GURL(chrome::kChromeUIInspectURL)));
365  params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE;
366  ShowSingletonTabOverwritingNTP(browser, params);
367}
368
369void InspectUI::Observe(int type,
370    const content::NotificationSource& source,
371    const content::NotificationDetails& details) {
372  if (source == content::Source<WebContents>(web_ui()->GetWebContents()))
373    StopListeningNotifications();
374}
375
376void InspectUI::StartListeningNotifications() {
377  if (!target_handlers_.empty())  // Possible when reloading the page.
378    StopListeningNotifications();
379
380  Profile* profile = Profile::FromWebUI(web_ui());
381
382  DevToolsTargetsUIHandler::Callback callback =
383      base::Bind(&InspectUI::PopulateTargets, base::Unretained(this));
384
385  AddTargetUIHandler(
386      DevToolsTargetsUIHandler::CreateForLocal(callback));
387  if (profile->IsOffTheRecord()) {
388    ShowIncognitoWarning();
389  } else {
390    AddTargetUIHandler(
391        DevToolsTargetsUIHandler::CreateForAdb(callback, profile));
392  }
393
394  port_status_serializer_.reset(
395      new PortForwardingStatusSerializer(
396          base::Bind(&InspectUI::PopulatePortStatus, base::Unretained(this)),
397          profile));
398
399  notification_registrar_.Add(this,
400                              content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
401                              content::NotificationService::AllSources());
402
403  pref_change_registrar_.Init(profile->GetPrefs());
404  pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled,
405      base::Bind(&InspectUI::UpdateDiscoverUsbDevicesEnabled,
406                 base::Unretained(this)));
407  pref_change_registrar_.Add(prefs::kDevToolsPortForwardingEnabled,
408      base::Bind(&InspectUI::UpdatePortForwardingEnabled,
409                 base::Unretained(this)));
410  pref_change_registrar_.Add(prefs::kDevToolsPortForwardingConfig,
411      base::Bind(&InspectUI::UpdatePortForwardingConfig,
412                 base::Unretained(this)));
413}
414
415void InspectUI::StopListeningNotifications() {
416  if (target_handlers_.empty())
417    return;
418
419  STLDeleteValues(&target_handlers_);
420
421  port_status_serializer_.reset();
422
423  notification_registrar_.RemoveAll();
424  pref_change_registrar_.RemoveAll();
425}
426
427content::WebUIDataSource* InspectUI::CreateInspectUIHTMLSource() {
428  content::WebUIDataSource* source =
429      content::WebUIDataSource::Create(chrome::kChromeUIInspectHost);
430  source->AddResourcePath("inspect.css", IDR_INSPECT_CSS);
431  source->AddResourcePath("inspect.js", IDR_INSPECT_JS);
432  source->SetDefaultResource(IDR_INSPECT_HTML);
433  return source;
434}
435
436void InspectUI::UpdateDiscoverUsbDevicesEnabled() {
437  web_ui()->CallJavascriptFunction(
438      "updateDiscoverUsbDevicesEnabled",
439      *GetPrefValue(prefs::kDevToolsDiscoverUsbDevicesEnabled));
440}
441
442void InspectUI::UpdatePortForwardingEnabled() {
443  web_ui()->CallJavascriptFunction(
444      "updatePortForwardingEnabled",
445      *GetPrefValue(prefs::kDevToolsPortForwardingEnabled));
446}
447
448void InspectUI::UpdatePortForwardingConfig() {
449  web_ui()->CallJavascriptFunction(
450      "updatePortForwardingConfig",
451      *GetPrefValue(prefs::kDevToolsPortForwardingConfig));
452}
453
454void InspectUI::SetPortForwardingDefaults() {
455  Profile* profile = Profile::FromWebUI(web_ui());
456  PrefService* prefs = profile->GetPrefs();
457
458  bool default_set;
459  if (!GetPrefValue(prefs::kDevToolsPortForwardingDefaultSet)->
460      GetAsBoolean(&default_set) || default_set) {
461    return;
462  }
463
464  // This is the first chrome://inspect invocation on a fresh profile or after
465  // upgrade from a version that did not have kDevToolsPortForwardingDefaultSet.
466  prefs->SetBoolean(prefs::kDevToolsPortForwardingDefaultSet, true);
467
468  bool enabled;
469  const base::DictionaryValue* config;
470  if (!GetPrefValue(prefs::kDevToolsPortForwardingEnabled)->
471        GetAsBoolean(&enabled) ||
472      !GetPrefValue(prefs::kDevToolsPortForwardingConfig)->
473        GetAsDictionary(&config)) {
474    return;
475  }
476
477  // Do nothing if user already took explicit action.
478  if (enabled || config->size() != 0)
479    return;
480
481  base::DictionaryValue default_config;
482  default_config.SetString(
483      kPortForwardingDefaultPort, kPortForwardingDefaultLocation);
484  prefs->Set(prefs::kDevToolsPortForwardingConfig, default_config);
485}
486
487const base::Value* InspectUI::GetPrefValue(const char* name) {
488  Profile* profile = Profile::FromWebUI(web_ui());
489  return profile->GetPrefs()->FindPreference(name)->GetValue();
490}
491
492void InspectUI::AddTargetUIHandler(
493    scoped_ptr<DevToolsTargetsUIHandler> handler) {
494  DevToolsTargetsUIHandler* handler_ptr = handler.release();
495  target_handlers_[handler_ptr->source_id()] = handler_ptr;
496}
497
498DevToolsTargetsUIHandler* InspectUI::FindTargetHandler(
499    const std::string& source_id) {
500  TargetHandlerMap::iterator it = target_handlers_.find(source_id);
501     return it != target_handlers_.end() ? it->second : NULL;
502}
503
504DevToolsTargetImpl* InspectUI::FindTarget(
505    const std::string& source_id, const std::string& target_id) {
506  TargetHandlerMap::iterator it = target_handlers_.find(source_id);
507  return it != target_handlers_.end() ?
508         it->second->GetTarget(target_id) : NULL;
509}
510
511void InspectUI::PopulateTargets(const std::string& source,
512                                const base::ListValue& targets) {
513  web_ui()->CallJavascriptFunction("populateTargets",
514                                   base::StringValue(source),
515                                   targets);
516}
517
518void InspectUI::ForceUpdateIfNeeded(const std::string& source_id,
519                                    const std::string& target_type) {
520  // TODO(dgozman): remove this after moving discovery to protocol.
521  // See crbug.com/398049.
522  if (target_type != DevToolsTargetImpl::kTargetTypeServiceWorker)
523    return;
524  DevToolsTargetsUIHandler* handler = FindTargetHandler(source_id);
525  if (handler)
526    handler->ForceUpdate();
527}
528
529void InspectUI::PopulatePortStatus(const base::Value& status) {
530  web_ui()->CallJavascriptFunction("populatePortStatus", status);
531}
532
533void InspectUI::ShowIncognitoWarning() {
534  web_ui()->CallJavascriptFunction("showIncognitoWarning");
535}
536