inspect_ui.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
1// Copyright (c) 2012 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. 4 5#include "chrome/browser/ui/webui/inspect_ui.h" 6 7#include <set> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "base/json/json_writer.h" 12#include "base/memory/ref_counted_memory.h" 13#include "base/prefs/pref_service.h" 14#include "base/stl_util.h" 15#include "base/strings/string_number_conversions.h" 16#include "base/strings/string_util.h" 17#include "base/strings/stringprintf.h" 18#include "base/strings/utf_string_conversions.h" 19#include "base/values.h" 20#include "chrome/browser/devtools/devtools_target_impl.h" 21#include "chrome/browser/devtools/port_forwarding_controller.h" 22#include "chrome/browser/profiles/profile.h" 23#include "chrome/browser/ui/browser_navigator.h" 24#include "chrome/browser/ui/singleton_tabs.h" 25#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 26#include "chrome/browser/ui/webui/theme_source.h" 27#include "chrome/common/pref_names.h" 28#include "chrome/common/url_constants.h" 29#include "content/public/browser/browser_child_process_observer.h" 30#include "content/public/browser/browser_thread.h" 31#include "content/public/browser/child_process_data.h" 32#include "content/public/browser/devtools_agent_host.h" 33#include "content/public/browser/devtools_client_host.h" 34#include "content/public/browser/devtools_manager.h" 35#include "content/public/browser/notification_service.h" 36#include "content/public/browser/notification_source.h" 37#include "content/public/browser/notification_types.h" 38#include "content/public/browser/render_process_host.h" 39#include "content/public/browser/render_view_host.h" 40#include "content/public/browser/user_metrics.h" 41#include "content/public/browser/web_contents.h" 42#include "content/public/browser/web_ui.h" 43#include "content/public/browser/web_ui_data_source.h" 44#include "content/public/browser/web_ui_message_handler.h" 45#include "content/public/browser/worker_service.h" 46#include "content/public/browser/worker_service_observer.h" 47#include "content/public/common/process_type.h" 48#include "grit/browser_resources.h" 49#include "grit/generated_resources.h" 50#include "net/base/escape.h" 51#include "net/base/net_errors.h" 52#include "ui/base/resource/resource_bundle.h" 53 54using content::BrowserThread; 55using content::ChildProcessData; 56using content::DevToolsAgentHost; 57using content::DevToolsClientHost; 58using content::DevToolsManager; 59using content::RenderProcessHost; 60using content::RenderViewHost; 61using content::RenderViewHostDelegate; 62using content::RenderWidgetHost; 63using content::WebContents; 64using content::WebUIMessageHandler; 65using content::WorkerService; 66using content::WorkerServiceObserver; 67 68namespace { 69 70const char kWorkerTargetType[] = "worker"; 71const char kAdbTargetType[] = "adb_page"; 72 73const char kInitUICommand[] = "init-ui"; 74const char kInspectCommand[] = "inspect"; 75const char kActivateCommand[] = "activate"; 76const char kCloseCommand[] = "close"; 77const char kReloadCommand[] = "reload"; 78const char kOpenCommand[] = "open"; 79 80const char kDiscoverUsbDevicesEnabledCommand[] = 81 "set-discover-usb-devices-enabled"; 82const char kPortForwardingEnabledCommand[] = 83 "set-port-forwarding-enabled"; 84const char kPortForwardingConfigCommand[] = "set-port-forwarding-config"; 85 86const char kPortForwardingDefaultPort[] = "8080"; 87const char kPortForwardingDefaultLocation[] = "localhost:8080"; 88 89const char kTargetIdField[] = "id"; 90const char kTargetTypeField[] = "type"; 91const char kAttachedField[] = "attached"; 92const char kUrlField[] = "url"; 93const char kNameField[] = "name"; 94const char kFaviconUrlField[] = "faviconUrl"; 95const char kDescription[] = "description"; 96const char kAdbConnectedField[] = "adbConnected"; 97const char kAdbModelField[] = "adbModel"; 98const char kAdbSerialField[] = "adbSerial"; 99const char kAdbBrowserProductField[] = "adbBrowserProduct"; 100const char kAdbBrowserPackageField[] = "adbBrowserPackage"; 101const char kAdbBrowserVersionField[] = "adbBrowserVersion"; 102const char kAdbGlobalIdField[] = "adbGlobalId"; 103const char kAdbBrowsersField[] = "browsers"; 104const char kAdbPagesField[] = "pages"; 105const char kAdbPortStatus[] = "adbPortStatus"; 106const char kAdbScreenWidthField[] = "adbScreenWidth"; 107const char kAdbScreenHeightField[] = "adbScreenHeight"; 108const char kAdbAttachedForeignField[] = "adbAttachedForeign"; 109const char kGuestList[] = "guests"; 110 111DictionaryValue* BuildTargetDescriptor( 112 const DevToolsTargetImpl& target) { 113 DictionaryValue* target_data = new DictionaryValue(); 114 target_data->SetString(kTargetIdField, target.GetId()); 115 target_data->SetString(kTargetTypeField, target.GetType()); 116 target_data->SetBoolean(kAttachedField, target.IsAttached()); 117 target_data->SetString(kUrlField, target.GetUrl().spec()); 118 target_data->SetString(kNameField, net::EscapeForHTML(target.GetTitle())); 119 target_data->SetString(kFaviconUrlField, target.GetFaviconUrl().spec()); 120 target_data->SetString(kDescription, target.GetDescription()); 121 122 return target_data; 123} 124 125class InspectMessageHandler : public WebUIMessageHandler { 126 public: 127 explicit InspectMessageHandler(InspectUI* inspect_ui) 128 : inspect_ui_(inspect_ui) {} 129 virtual ~InspectMessageHandler() {} 130 131 private: 132 // WebUIMessageHandler implementation. 133 virtual void RegisterMessages() OVERRIDE; 134 135 void HandleInitUICommand(const ListValue* args); 136 void HandleInspectCommand(const ListValue* args); 137 void HandleActivateCommand(const ListValue* args); 138 void HandleCloseCommand(const ListValue* args); 139 void HandleReloadCommand(const ListValue* args); 140 void HandleOpenCommand(const ListValue* args); 141 void HandleBooleanPrefChanged(const char* pref_name, 142 const ListValue* args); 143 void HandlePortForwardingConfigCommand(const ListValue* args); 144 145 DevToolsTargetImpl* FindTarget(const ListValue* args); 146 147 InspectUI* inspect_ui_; 148 149 DISALLOW_COPY_AND_ASSIGN(InspectMessageHandler); 150}; 151 152void InspectMessageHandler::RegisterMessages() { 153 web_ui()->RegisterMessageCallback(kInitUICommand, 154 base::Bind(&InspectMessageHandler::HandleInitUICommand, 155 base::Unretained(this))); 156 web_ui()->RegisterMessageCallback(kInspectCommand, 157 base::Bind(&InspectMessageHandler::HandleInspectCommand, 158 base::Unretained(this))); 159 web_ui()->RegisterMessageCallback(kActivateCommand, 160 base::Bind(&InspectMessageHandler::HandleActivateCommand, 161 base::Unretained(this))); 162 web_ui()->RegisterMessageCallback(kCloseCommand, 163 base::Bind(&InspectMessageHandler::HandleCloseCommand, 164 base::Unretained(this))); 165 web_ui()->RegisterMessageCallback(kDiscoverUsbDevicesEnabledCommand, 166 base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged, 167 base::Unretained(this), 168 &prefs::kDevToolsDiscoverUsbDevicesEnabled[0])); 169 web_ui()->RegisterMessageCallback(kPortForwardingEnabledCommand, 170 base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged, 171 base::Unretained(this), 172 &prefs::kDevToolsPortForwardingEnabled[0])); 173 web_ui()->RegisterMessageCallback(kPortForwardingConfigCommand, 174 base::Bind(&InspectMessageHandler::HandlePortForwardingConfigCommand, 175 base::Unretained(this))); 176 web_ui()->RegisterMessageCallback(kReloadCommand, 177 base::Bind(&InspectMessageHandler::HandleReloadCommand, 178 base::Unretained(this))); 179 web_ui()->RegisterMessageCallback(kOpenCommand, 180 base::Bind(&InspectMessageHandler::HandleOpenCommand, 181 base::Unretained(this))); 182} 183 184void InspectMessageHandler::HandleInitUICommand(const ListValue*) { 185 inspect_ui_->InitUI(); 186} 187 188void InspectMessageHandler::HandleInspectCommand(const ListValue* args) { 189 Profile* profile = Profile::FromWebUI(web_ui()); 190 if (!profile) 191 return; 192 DevToolsTargetImpl* target = FindTarget(args); 193 if (target) 194 target->Inspect(profile); 195} 196 197void InspectMessageHandler::HandleActivateCommand(const ListValue* args) { 198 DevToolsTargetImpl* target = FindTarget(args); 199 if (target) 200 target->Activate(); 201} 202 203void InspectMessageHandler::HandleCloseCommand(const ListValue* args) { 204 DevToolsTargetImpl* target = FindTarget(args); 205 if (target) 206 target->Close(); 207} 208 209void InspectMessageHandler::HandleReloadCommand(const ListValue* args) { 210 DevToolsTargetImpl* target = FindTarget(args); 211 if (target) 212 target->Reload(); 213} 214 215void InspectMessageHandler::HandleOpenCommand(const ListValue* args) { 216 if (args->GetSize() != 2) 217 return; 218 std::string browser_id; 219 if (!args->GetString(0, &browser_id)) 220 return; 221 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> remote_browser = 222 inspect_ui_->FindRemoteBrowser(browser_id); 223 if (!remote_browser) 224 return; 225 std::string url; 226 if (!args->GetString(1, &url)) 227 return; 228 GURL gurl(url); 229 if (!gurl.is_valid()) { 230 gurl = GURL("http://" + url); 231 if (!gurl.is_valid()) 232 return; 233 } 234 remote_browser->Open(gurl.spec()); 235} 236 237DevToolsTargetImpl* InspectMessageHandler::FindTarget(const ListValue* args) { 238 const DictionaryValue* data; 239 std::string type; 240 std::string id; 241 if (args->GetSize() == 1 && args->GetDictionary(0, &data) && 242 data->GetString(kTargetTypeField, &type) && 243 data->GetString(kTargetIdField, &id)) { 244 return inspect_ui_->FindTarget(type, id); 245 } 246 return NULL; 247} 248 249void InspectMessageHandler::HandleBooleanPrefChanged( 250 const char* pref_name, 251 const ListValue* args) { 252 Profile* profile = Profile::FromWebUI(web_ui()); 253 if (!profile) 254 return; 255 256 bool enabled; 257 if (args->GetSize() == 1 && args->GetBoolean(0, &enabled)) 258 profile->GetPrefs()->SetBoolean(pref_name, enabled); 259} 260 261void InspectMessageHandler::HandlePortForwardingConfigCommand( 262 const ListValue* args) { 263 Profile* profile = Profile::FromWebUI(web_ui()); 264 if (!profile) 265 return; 266 267 const DictionaryValue* dict_src; 268 if (args->GetSize() == 1 && args->GetDictionary(0, &dict_src)) 269 profile->GetPrefs()->Set(prefs::kDevToolsPortForwardingConfig, *dict_src); 270} 271 272} // namespace 273 274class InspectUI::WorkerCreationDestructionListener 275 : public WorkerServiceObserver, 276 public content::BrowserChildProcessObserver, 277 public base::RefCountedThreadSafe<WorkerCreationDestructionListener> { 278 public: 279 WorkerCreationDestructionListener() 280 : discovery_ui_(NULL) {} 281 282 void Init(InspectUI* workers_ui) { 283 DCHECK(workers_ui); 284 DCHECK(!discovery_ui_); 285 discovery_ui_ = workers_ui; 286 BrowserChildProcessObserver::Add(this); 287 BrowserThread::PostTask( 288 BrowserThread::IO, FROM_HERE, 289 base::Bind(&WorkerCreationDestructionListener::RegisterObserver, 290 this)); 291 } 292 293 void InspectUIDestroyed() { 294 DCHECK(discovery_ui_); 295 discovery_ui_ = NULL; 296 BrowserChildProcessObserver::Remove(this); 297 BrowserThread::PostTask( 298 BrowserThread::IO, FROM_HERE, 299 base::Bind(&WorkerCreationDestructionListener::UnregisterObserver, 300 this)); 301 } 302 303 void UpdateUI() { 304 BrowserThread::PostTask( 305 BrowserThread::IO, FROM_HERE, 306 base::Bind(&WorkerCreationDestructionListener::CollectWorkersData, 307 this)); 308 } 309 310 private: 311 friend class base::RefCountedThreadSafe<WorkerCreationDestructionListener>; 312 virtual ~WorkerCreationDestructionListener() {} 313 314 virtual void WorkerCreated( 315 const GURL& url, 316 const string16& name, 317 int process_id, 318 int route_id) OVERRIDE { 319 CollectWorkersData(); 320 } 321 322 virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { 323 CollectWorkersData(); 324 } 325 326 virtual void BrowserChildProcessHostConnected( 327 const content::ChildProcessData& data) OVERRIDE { 328 if (data.process_type == content::PROCESS_TYPE_WORKER) 329 UpdateUI(); 330 } 331 332 virtual void BrowserChildProcessHostDisconnected( 333 const content::ChildProcessData& data) OVERRIDE { 334 if (data.process_type == content::PROCESS_TYPE_WORKER) 335 UpdateUI(); 336 } 337 338 void CollectWorkersData() { 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 340 DevToolsTargetImpl::EnumerateWorkerTargets( 341 base::Bind( 342 &WorkerCreationDestructionListener::PopulateWorkersList, this)); 343 } 344 345 void RegisterObserver() { 346 WorkerService::GetInstance()->AddObserver(this); 347 } 348 349 void UnregisterObserver() { 350 WorkerService::GetInstance()->RemoveObserver(this); 351 } 352 353 void PopulateWorkersList(const DevToolsTargetImpl::List& targets) { 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 355 if (discovery_ui_) 356 discovery_ui_->PopulateWorkerTargets(targets); 357 } 358 359 InspectUI* discovery_ui_; 360}; 361 362InspectUI::InspectUI(content::WebUI* web_ui) 363 : WebUIController(web_ui) { 364 web_ui->AddMessageHandler(new InspectMessageHandler(this)); 365 Profile* profile = Profile::FromWebUI(web_ui); 366 content::WebUIDataSource::Add(profile, CreateInspectUIHTMLSource()); 367 368 // Set up the chrome://theme/ source. 369 ThemeSource* theme = new ThemeSource(profile); 370 content::URLDataSource::Add(profile, theme); 371} 372 373InspectUI::~InspectUI() { 374 StopListeningNotifications(); 375 STLDeleteValues(&render_view_host_targets_); 376} 377 378void InspectUI::InitUI() { 379 SetPortForwardingDefaults(); 380 StartListeningNotifications(); 381 PopulateWebContentsTargets(); 382 UpdateDiscoverUsbDevicesEnabled(); 383 UpdatePortForwardingEnabled(); 384 UpdatePortForwardingConfig(); 385 observer_->UpdateUI(); 386} 387 388DevToolsTargetImpl* InspectUI::FindTarget(const std::string& type, 389 const std::string& id) { 390 if (type == kWorkerTargetType) { 391 TargetMap::iterator it = worker_targets_.find(id); 392 return it == worker_targets_.end() ? NULL : it->second; 393 } else if (type == kAdbTargetType) { 394 TargetMap::iterator it = remote_targets_.find(id); 395 return it == remote_targets_.end() ? NULL : it->second; 396 } else { 397 TargetMap::iterator it = render_view_host_targets_.find(id); 398 return it == render_view_host_targets_.end() ? NULL : it->second; 399 } 400} 401 402scoped_refptr<DevToolsAdbBridge::RemoteBrowser> 403InspectUI::FindRemoteBrowser(const std::string& id) { 404 RemoteBrowsers::iterator it = remote_browsers_.find(id); 405 return it == remote_browsers_.end() ? NULL : it->second; 406} 407 408void InspectUI::InspectDevices(Browser* browser) { 409 content::RecordAction(content::UserMetricsAction("InspectDevices")); 410 chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams( 411 browser, GURL(chrome::kChromeUIInspectURL))); 412 params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE; 413 ShowSingletonTabOverwritingNTP(browser, params); 414} 415 416void InspectUI::PopulateWebContentsTargets() { 417 ListValue list_value; 418 419 std::map<WebContents*, DictionaryValue*> web_contents_to_descriptor_; 420 std::vector<DevToolsTargetImpl*> guest_targets; 421 422 DevToolsTargetImpl::List targets = 423 DevToolsTargetImpl::EnumerateRenderViewHostTargets(); 424 425 STLDeleteValues(&render_view_host_targets_); 426 for (DevToolsTargetImpl::List::iterator it = targets.begin(); 427 it != targets.end(); ++it) { 428 scoped_ptr<DevToolsTargetImpl> target(*it); 429 RenderViewHost* rvh = target->GetRenderViewHost(); 430 if (!rvh) 431 continue; 432 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 433 if (!web_contents) 434 continue; 435 436 DevToolsTargetImpl* target_ptr = target.get(); 437 render_view_host_targets_[target_ptr->GetId()] = target.release(); 438 if (rvh->GetProcess()->IsGuest()) { 439 guest_targets.push_back(target_ptr); 440 } else { 441 DictionaryValue* descriptor = BuildTargetDescriptor(*target_ptr); 442 list_value.Append(descriptor); 443 web_contents_to_descriptor_[web_contents] = descriptor; 444 } 445 } 446 447 // Add the list of guest-views to each of its embedders. 448 for (std::vector<DevToolsTargetImpl*>::iterator it(guest_targets.begin()); 449 it != guest_targets.end(); ++it) { 450 DevToolsTargetImpl* guest = (*it); 451 WebContents* guest_web_contents = 452 WebContents::FromRenderViewHost(guest->GetRenderViewHost()); 453 WebContents* embedder = guest_web_contents->GetEmbedderWebContents(); 454 if (embedder && web_contents_to_descriptor_.count(embedder) > 0) { 455 DictionaryValue* parent = web_contents_to_descriptor_[embedder]; 456 ListValue* guests = NULL; 457 if (!parent->GetList(kGuestList, &guests)) { 458 guests = new ListValue(); 459 parent->Set(kGuestList, guests); 460 } 461 guests->Append(BuildTargetDescriptor(*guest)); 462 } 463 } 464 465 web_ui()->CallJavascriptFunction("populateWebContentsTargets", list_value); 466} 467 468void InspectUI::PopulateWorkerTargets(const DevToolsTargetImpl::List& targets) { 469 ListValue list_value; 470 471 STLDeleteValues(&worker_targets_); 472 for (DevToolsTargetImpl::List::const_iterator it = targets.begin(); 473 it != targets.end(); ++it) { 474 DevToolsTargetImpl* target = *it; 475 list_value.Append(BuildTargetDescriptor(*target)); 476 worker_targets_[target->GetId()] = target; 477 } 478 479 web_ui()->CallJavascriptFunction("populateWorkerTargets", list_value); 480} 481 482void InspectUI::Observe(int type, 483 const content::NotificationSource& source, 484 const content::NotificationDetails& details) { 485 if (source != content::Source<WebContents>(web_ui()->GetWebContents())) 486 PopulateWebContentsTargets(); 487 else if (type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED) 488 StopListeningNotifications(); 489} 490 491void InspectUI::StartListeningNotifications() { 492 if (observer_) 493 return; 494 495 observer_ = new WorkerCreationDestructionListener(); 496 observer_->Init(this); 497 498 Profile* profile = Profile::FromWebUI(web_ui()); 499 DevToolsAdbBridge* adb_bridge = 500 DevToolsAdbBridge::Factory::GetForProfile(profile); 501 if (adb_bridge) 502 adb_bridge->AddListener(this); 503 504 notification_registrar_.Add(this, 505 content::NOTIFICATION_WEB_CONTENTS_CONNECTED, 506 content::NotificationService::AllSources()); 507 notification_registrar_.Add(this, 508 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 509 content::NotificationService::AllSources()); 510 notification_registrar_.Add(this, 511 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 512 content::NotificationService::AllSources()); 513 514 pref_change_registrar_.Init(profile->GetPrefs()); 515 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, 516 base::Bind(&InspectUI::UpdateDiscoverUsbDevicesEnabled, 517 base::Unretained(this))); 518 pref_change_registrar_.Add(prefs::kDevToolsPortForwardingEnabled, 519 base::Bind(&InspectUI::UpdatePortForwardingEnabled, 520 base::Unretained(this))); 521 pref_change_registrar_.Add(prefs::kDevToolsPortForwardingConfig, 522 base::Bind(&InspectUI::UpdatePortForwardingConfig, 523 base::Unretained(this))); 524} 525 526void InspectUI::StopListeningNotifications() 527{ 528 if (!observer_.get()) 529 return; 530 Profile* profile = Profile::FromWebUI(web_ui()); 531 DevToolsAdbBridge* adb_bridge = 532 DevToolsAdbBridge::Factory::GetForProfile(profile); 533 if (adb_bridge) 534 adb_bridge->RemoveListener(this); 535 observer_->InspectUIDestroyed(); 536 observer_ = NULL; 537 notification_registrar_.RemoveAll(); 538 pref_change_registrar_.RemoveAll(); 539} 540 541content::WebUIDataSource* InspectUI::CreateInspectUIHTMLSource() { 542 content::WebUIDataSource* source = 543 content::WebUIDataSource::Create(chrome::kChromeUIInspectHost); 544 source->AddResourcePath("inspect.css", IDR_INSPECT_CSS); 545 source->AddResourcePath("inspect.js", IDR_INSPECT_JS); 546 source->SetDefaultResource(IDR_INSPECT_HTML); 547 return source; 548} 549 550void InspectUI::RemoteDevicesChanged( 551 DevToolsAdbBridge::RemoteDevices* devices) { 552 Profile* profile = Profile::FromWebUI(web_ui()); 553 PortForwardingController* port_forwarding_controller = 554 PortForwardingController::Factory::GetForProfile(profile); 555 PortForwardingController::DevicesStatus port_forwarding_status; 556 if (port_forwarding_controller) 557 port_forwarding_status = 558 port_forwarding_controller->UpdateDeviceList(*devices); 559 560 remote_browsers_.clear(); 561 STLDeleteValues(&remote_targets_); 562 ListValue device_list; 563 for (DevToolsAdbBridge::RemoteDevices::iterator dit = devices->begin(); 564 dit != devices->end(); ++dit) { 565 DevToolsAdbBridge::RemoteDevice* device = dit->get(); 566 DictionaryValue* device_data = new DictionaryValue(); 567 device_data->SetString(kAdbModelField, device->GetModel()); 568 device_data->SetString(kAdbSerialField, device->GetSerial()); 569 device_data->SetBoolean(kAdbConnectedField, device->IsConnected()); 570 std::string device_id = base::StringPrintf( 571 "device:%s", 572 device->GetSerial().c_str()); 573 device_data->SetString(kAdbGlobalIdField, device_id); 574 ListValue* browser_list = new ListValue(); 575 device_data->Set(kAdbBrowsersField, browser_list); 576 577 DevToolsAdbBridge::RemoteBrowsers& browsers = device->browsers(); 578 for (DevToolsAdbBridge::RemoteBrowsers::iterator bit = 579 browsers.begin(); bit != browsers.end(); ++bit) { 580 DevToolsAdbBridge::RemoteBrowser* browser = bit->get(); 581 DictionaryValue* browser_data = new DictionaryValue(); 582 browser_data->SetString(kAdbBrowserProductField, browser->product()); 583 browser_data->SetString(kAdbBrowserPackageField, browser->package()); 584 browser_data->SetString(kAdbBrowserVersionField, browser->version()); 585 std::string browser_id = base::StringPrintf( 586 "browser:%s:%s:%s", 587 device->GetSerial().c_str(), 588 browser->product().c_str(), // Force sorting by product name. 589 browser->socket().c_str()); 590 browser_data->SetString(kAdbGlobalIdField, browser_id); 591 remote_browsers_[browser_id] = browser; 592 ListValue* page_list = new ListValue(); 593 browser_data->Set(kAdbPagesField, page_list); 594 595 DevToolsTargetImpl::List pages = browser->CreatePageTargets(); 596 for (DevToolsTargetImpl::List::iterator it = 597 pages.begin(); it != pages.end(); ++it) { 598 DevToolsTargetImpl* page = *it; 599 DictionaryValue* page_data = BuildTargetDescriptor(*page); 600 page_data->SetBoolean( 601 kAdbAttachedForeignField, 602 page->IsAttached() && 603 !DevToolsAdbBridge::HasDevToolsWindow(page->GetId())); 604 // Pass the screen size in the page object to make sure that 605 // the caching logic does not prevent the page item from updating 606 // when the screen size changes. 607 gfx::Size screen_size = device->screen_size(); 608 page_data->SetInteger(kAdbScreenWidthField, screen_size.width()); 609 page_data->SetInteger(kAdbScreenHeightField, screen_size.height()); 610 remote_targets_[page->GetId()] = page; 611 page_list->Append(page_data); 612 } 613 browser_list->Append(browser_data); 614 } 615 616 if (port_forwarding_controller) { 617 PortForwardingController::DevicesStatus::iterator sit = 618 port_forwarding_status.find(device->GetSerial()); 619 if (sit != port_forwarding_status.end()) { 620 DictionaryValue* port_status_dict = new DictionaryValue(); 621 typedef PortForwardingController::PortStatusMap StatusMap; 622 const StatusMap& port_status = sit->second; 623 for (StatusMap::const_iterator it = port_status.begin(); 624 it != port_status.end(); ++it) { 625 port_status_dict->SetInteger( 626 base::StringPrintf("%d", it->first), it->second); 627 } 628 device_data->Set(kAdbPortStatus, port_status_dict); 629 } 630 } 631 632 device_list.Append(device_data); 633 } 634 web_ui()->CallJavascriptFunction("populateRemoteTargets", device_list); 635} 636 637void InspectUI::UpdateDiscoverUsbDevicesEnabled() { 638 const Value* value = GetPrefValue(prefs::kDevToolsDiscoverUsbDevicesEnabled); 639 web_ui()->CallJavascriptFunction("updateDiscoverUsbDevicesEnabled", *value); 640 641 // Configure adb bridge. 642 Profile* profile = Profile::FromWebUI(web_ui()); 643 DevToolsAdbBridge* adb_bridge = 644 DevToolsAdbBridge::Factory::GetForProfile(profile); 645 if (adb_bridge) { 646 bool enabled = false; 647 value->GetAsBoolean(&enabled); 648 649 DevToolsAdbBridge::DeviceProviders device_providers; 650 device_providers.push_back(AndroidDeviceProvider::GetAdbDeviceProvider()); 651 652 if (enabled) { 653 device_providers.push_back( 654 AndroidDeviceProvider::GetUsbDeviceProvider(profile)); 655 } 656 657 adb_bridge->set_device_providers(device_providers); 658 } 659} 660 661void InspectUI::UpdatePortForwardingEnabled() { 662 web_ui()->CallJavascriptFunction("updatePortForwardingEnabled", 663 *GetPrefValue(prefs::kDevToolsPortForwardingEnabled)); 664 665} 666 667void InspectUI::UpdatePortForwardingConfig() { 668 web_ui()->CallJavascriptFunction("updatePortForwardingConfig", 669 *GetPrefValue(prefs::kDevToolsPortForwardingConfig)); 670} 671 672void InspectUI::SetPortForwardingDefaults() { 673 Profile* profile = Profile::FromWebUI(web_ui()); 674 PrefService* prefs = profile->GetPrefs(); 675 676 bool default_set; 677 if (!GetPrefValue(prefs::kDevToolsPortForwardingDefaultSet)-> 678 GetAsBoolean(&default_set) || default_set) { 679 return; 680 } 681 682 // This is the first chrome://inspect invocation on a fresh profile or after 683 // upgrade from a version that did not have kDevToolsPortForwardingDefaultSet. 684 prefs->SetBoolean(prefs::kDevToolsPortForwardingDefaultSet, true); 685 686 bool enabled; 687 const base::DictionaryValue* config; 688 if (!GetPrefValue(prefs::kDevToolsPortForwardingEnabled)-> 689 GetAsBoolean(&enabled) || 690 !GetPrefValue(prefs::kDevToolsPortForwardingConfig)-> 691 GetAsDictionary(&config)) { 692 return; 693 } 694 695 // Do nothing if user already took explicit action. 696 if (enabled || config->size() != 0) 697 return; 698 699 base::DictionaryValue default_config; 700 default_config.SetString( 701 kPortForwardingDefaultPort, kPortForwardingDefaultLocation); 702 prefs->Set(prefs::kDevToolsPortForwardingConfig, default_config); 703} 704 705const base::Value* InspectUI::GetPrefValue(const char* name) { 706 Profile* profile = Profile::FromWebUI(web_ui()); 707 return profile->GetPrefs()->FindPreference(name)->GetValue(); 708} 709