inspect_ui.cc revision a3f7b4e666c476898878fa745f637129375cd889
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/inspect_ui.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/devtools/devtools_window.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/child_process_data.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_client_host.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_manager.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui_data_source.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui_message_handler.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/worker_service.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/worker_service_observer.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/process_type.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ChildProcessData;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsAgentHost;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsClientHost;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DevToolsManager;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderProcessHost;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHostDelegate;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebUIMessageHandler;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WorkerService;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WorkerServiceObserver;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kDataFile[] = "targets-data.json";
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kAdbPages[] = "adb-pages";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66a3f7b4e666c476898878fa745f637129375cd889Ben Murdochstatic const char kAppTargetType[] = "app";
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kExtensionTargetType[]  = "extension";
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kPageTargetType[]  = "page";
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kWorkerTargetType[]  = "worker";
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kAdbTargetType[]  = "adb_page";
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kInspectCommand[]  = "inspect";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kTerminateCommand[]  = "terminate";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kTargetTypeField[]  = "type";
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kAttachedField[]  = "attached";
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kProcessIdField[]  = "processId";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kRouteIdField[]  = "routeId";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUrlField[]  = "url";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kNameField[]  = "name";
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kFaviconUrlField[] = "faviconUrl";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kPidField[]  = "pid";
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kAdbSerialField[] = "adbSerial";
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kAdbModelField[] = "adbModel";
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kAdbPackageField[] = "adbPackage";
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kAdbSocketField[] = "adbSocket";
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kAdbDebugUrlField[] = "adbDebugUrl";
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kAdbFrontendUrlField[] = "adbFrontendUrl";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* BuildTargetDescriptor(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& target_type,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool attached,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& favicon_url,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int process_id,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle handle = base::kNullProcessHandle) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* target_data = new DictionaryValue();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetString(kTargetTypeField, target_type);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetBoolean(kAttachedField, attached);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetInteger(kProcessIdField, process_id);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetInteger(kRouteIdField, route_id);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetString(kUrlField, url.spec());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetString(kNameField, net::EscapeForHTML(name));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetInteger(kPidField, base::GetProcId(handle));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_data->SetString(kFaviconUrlField, favicon_url.spec());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target_data;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasClientHost(RenderViewHost* rvh) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!DevToolsAgentHost::HasFor(rvh))
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsAgentHost::GetOrCreateFor(rvh));
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return agent->IsAttached();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* BuildTargetDescriptor(RenderViewHost* rvh, bool is_tab) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string title;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string target_type = is_tab ? kPageTargetType : "";
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL favicon_url;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (web_contents) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url = web_contents->GetURL();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title = UTF16ToUTF8(web_contents->GetTitle());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NavigationController& controller = web_contents->GetController();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NavigationEntry* entry = controller.GetActiveEntry();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry != NULL && entry->GetURL().is_valid())
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_url = entry->GetFavicon().url;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile = Profile::FromBrowserContext(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        web_contents->GetBrowserContext());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (profile) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionService* extension_service = profile->GetExtensionService();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const extensions::Extension* extension = extension_service->
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extensions()->GetByID(url.host());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension) {
142a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        if (extension->is_hosted_app()
143a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch            || extension->is_legacy_packaged_app()
144a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch            || extension->is_platform_app())
145a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          target_type = kAppTargetType;
146a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        else
147a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          target_type = kExtensionTargetType;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title = extension->name();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BuildTargetDescriptor(target_type,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               HasClientHost(rvh),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               url,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               title,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               favicon_url,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               rvh->GetProcess()->GetID(),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               rvh->GetRoutingID());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Appends the inspectable workers to the list of RenderViews, and sends the
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// response back to the webui system.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SendDescriptors(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ListValue* rvh_list,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::WebUIDataSource::GotDataCallback& callback) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<WorkerService::WorkerInfo> worker_info =
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WorkerService::GetInstance()->GetWorkers();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < worker_info.size(); ++i) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rvh_list->Append(BuildTargetDescriptor(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kWorkerTargetType,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        false,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_info[i].url,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UTF16ToUTF8(worker_info[i].name),
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GURL(),
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_info[i].process_id,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_info[i].route_id,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_info[i].handle));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string json_string;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONWriter::Write(rvh_list, &json_string);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(base::RefCountedString::TakeString(&json_string));
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HandleDataRequestCallback(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::WebUIDataSource::GotDataCallback& callback) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<RenderViewHost*> tab_rvhs;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (TabContentsIterator it; !it.done(); it.Next())
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tab_rvhs.insert(it->GetRenderViewHost());
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ListValue> rvh_list(new ListValue());
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<RenderViewHost*> rvh_vector =
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsAgentHost::GetValidRenderViewHosts();
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<RenderViewHost*>::iterator it(rvh_vector.begin());
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != rvh_vector.end(); it++) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_tab = tab_rvhs.find(*it) != tab_rvhs.end();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rvh_list->Append(BuildTargetDescriptor(*it, is_tab));
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::IO,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&SendDescriptors, base::Owned(rvh_list.release()), callback));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InspectMessageHandler : public WebUIMessageHandler {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit InspectMessageHandler(DevToolsAdbBridge* adb_bridge)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : adb_bridge_(adb_bridge) {}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InspectMessageHandler() {}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebUIMessageHandler implementation.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterMessages() OVERRIDE;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for "openDevTools" message.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleInspectCommand(const ListValue* args);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleTerminateCommand(const ListValue* args);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool GetProcessAndRouteId(const ListValue* args,
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int* process_id,
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            int* route_id);
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DevToolsAdbBridge* adb_bridge_;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InspectMessageHandler);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectMessageHandler::RegisterMessages() {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(kInspectCommand,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&InspectMessageHandler::HandleInspectCommand,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(kTerminateCommand,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&InspectMessageHandler::HandleTerminateCommand,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectMessageHandler::HandleInspectCommand(const ListValue* args) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id;
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GetProcessAndRouteId(args, &process_id, &route_id) || process_id == 0
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      || route_id == 0) {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check for ADB serial
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const DictionaryValue* data;
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string serial;
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string socket;
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string debug_url;
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string frontend_url;
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (args->GetSize() == 1 && args->GetDictionary(0, &data) &&
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        data->GetString(kAdbSerialField, &serial) &&
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        data->GetString(kAdbSocketField, &socket) &&
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        data->GetString(kAdbDebugUrlField, &debug_url) &&
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        data->GetString(kAdbFrontendUrlField, &frontend_url)) {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      adb_bridge_->Attach(serial, socket, debug_url, frontend_url);
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rvh) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DevToolsWindow::OpenDevToolsWindow(rvh);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui());
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile)
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<DevToolsAgentHost> agent_host(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DevToolsAgentHost::GetForWorker(process_id, route_id));
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!agent_host.get())
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host.get());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TerminateWorker(int process_id, int route_id) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkerService::GetInstance()->TerminateWorker(process_id, route_id);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectMessageHandler::HandleTerminateCommand(const ListValue* args) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GetProcessAndRouteId(args, &process_id, &route_id))
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TerminateWorker, process_id, route_id));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool InspectMessageHandler::GetProcessAndRouteId(const ListValue* args,
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 int* process_id,
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 int* route_id) {
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const DictionaryValue* data;
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (args->GetSize() == 1 && args->GetDictionary(0, &data) &&
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      data->GetInteger(kProcessIdField, process_id) &&
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      data->GetInteger(kRouteIdField, route_id)) {
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InspectUI::WorkerCreationDestructionListener
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public WorkerServiceObserver,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public base::RefCountedThreadSafe<WorkerCreationDestructionListener> {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  WorkerCreationDestructionListener()
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      : discovery_ui_(NULL) {}
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Init(InspectUI* workers_ui) {
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(workers_ui);
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(!discovery_ui_);
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    discovery_ui_ = workers_ui;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&WorkerCreationDestructionListener::RegisterObserver,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   this));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InspectUIDestroyed() {
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(discovery_ui_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    discovery_ui_ = NULL;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&WorkerCreationDestructionListener::UnregisterObserver,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   this));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<WorkerCreationDestructionListener>;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WorkerCreationDestructionListener() {}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WorkerCreated(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string16& name,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int process_id,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int route_id) OVERRIDE {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::UI, FROM_HERE,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&WorkerCreationDestructionListener::NotifyItemsChanged,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   this));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::UI, FROM_HERE,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&WorkerCreationDestructionListener::NotifyItemsChanged,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   this));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyItemsChanged() {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (discovery_ui_)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      discovery_ui_->RefreshUI();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterObserver() {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WorkerService::GetInstance()->AddObserver(this);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnregisterObserver() {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WorkerService::GetInstance()->RemoveObserver(this);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InspectUI* discovery_ui_;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectUI::InspectUI(content::WebUI* web_ui)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : WebUIController(web_ui),
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      observer_(new WorkerCreationDestructionListener()),
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  observer_->Init(this);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui);
3797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  adb_bridge_ = DevToolsAdbBridge::Factory::GetForProfile(profile);
3809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  adb_bridge_->AddListener(this);
3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  web_ui->AddMessageHandler(new InspectMessageHandler(adb_bridge_));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource::Add(profile, CreateInspectUIHTMLSource());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InspectUI::~InspectUI() {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopListeningNotifications();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectUI::RefreshUI() {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("populateLists");
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InspectUI::WeakHandleRequestCallback(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::WeakPtr<InspectUI>& inspect_ui,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path,
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::WebUIDataSource::GotDataCallback& callback) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!inspect_ui.get())
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return inspect_ui->HandleRequestCallback(path, callback);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectUI::Observe(int type,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source != content::Source<WebContents>(web_ui()->GetWebContents()))
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RefreshUI();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopListeningNotifications();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InspectUI::StopListeningNotifications()
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!observer_.get())
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  adb_bridge_->RemoveListener(this);
4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  adb_bridge_ = NULL;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->InspectUIDestroyed();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_ = NULL;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.RemoveAll();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebUIDataSource* InspectUI::CreateInspectUIHTMLSource() {
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource* source =
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::WebUIDataSource::Create(chrome::kChromeUIInspectHost);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("inspect.css", IDR_INSPECT_CSS);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("inspect.js", IDR_INSPECT_JS);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetDefaultResource(IDR_INSPECT_HTML);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetRequestFilter(base::Bind(&InspectUI::WeakHandleRequestCallback,
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      weak_factory_.GetWeakPtr()));
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return source;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InspectUI::HandleRequestCallback(
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::WebUIDataSource::GotDataCallback& callback) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (path == kDataFile)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HandleDataRequestCallback(path, callback);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid InspectUI::RemotePagesChanged(DevToolsAdbBridge::RemotePages* pages) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ListValue targets;
4549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  for (DevToolsAdbBridge::RemotePages::iterator it = pages->begin();
4559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch       it != pages->end(); ++it) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DevToolsAdbBridge::RemotePage* page = it->get();
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DictionaryValue* target_data = BuildTargetDescriptor(kAdbTargetType,
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        false, GURL(page->url()), page->title(), GURL(page->favicon_url()), 0,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        0);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    target_data->SetString(kAdbSerialField, page->serial());
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    target_data->SetString(kAdbModelField, page->model());
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    target_data->SetString(kAdbPackageField, page->package());
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    target_data->SetString(kAdbSocketField, page->socket());
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    target_data->SetString(kAdbDebugUrlField, page->debug_url());
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    target_data->SetString(kAdbFrontendUrlField, page->frontend_url());
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    targets.Append(target_data);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  web_ui()->CallJavascriptFunction("populateDeviceLists", targets);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
470