| OLD | NEW |
| (Empty) |
| 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/workers_ui.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/json/json_writer.h" | |
| 10 #include "base/memory/ref_counted_memory.h" | |
| 11 #include "base/string_number_conversions.h" | |
| 12 #include "base/string_util.h" | |
| 13 #include "base/values.h" | |
| 14 #include "chrome/browser/debugger/devtools_window.h" | |
| 15 #include "chrome/browser/profiles/profile.h" | |
| 16 #include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" | |
| 17 #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" | |
| 18 #include "chrome/common/url_constants.h" | |
| 19 #include "content/public/browser/child_process_data.h" | |
| 20 #include "content/public/browser/devtools_agent_host_registry.h" | |
| 21 #include "content/public/browser/browser_thread.h" | |
| 22 #include "content/public/browser/web_contents.h" | |
| 23 #include "content/public/browser/web_ui.h" | |
| 24 #include "content/public/browser/worker_service.h" | |
| 25 #include "content/public/browser/worker_service_observer.h" | |
| 26 #include "content/public/browser/web_ui_message_handler.h" | |
| 27 #include "content/public/common/process_type.h" | |
| 28 #include "grit/generated_resources.h" | |
| 29 #include "grit/workers_resources.h" | |
| 30 #include "ui/base/resource/resource_bundle.h" | |
| 31 | |
| 32 using content::BrowserThread; | |
| 33 using content::ChildProcessData; | |
| 34 using content::DevToolsAgentHost; | |
| 35 using content::DevToolsAgentHostRegistry; | |
| 36 using content::WebContents; | |
| 37 using content::WebUIMessageHandler; | |
| 38 using content::WorkerService; | |
| 39 using content::WorkerServiceObserver; | |
| 40 | |
| 41 static const char kWorkersDataFile[] = "workers_data.json"; | |
| 42 | |
| 43 static const char kOpenDevToolsCommand[] = "openDevTools"; | |
| 44 static const char kTerminateWorkerCommand[] = "terminateWorker"; | |
| 45 | |
| 46 static const char kWorkerProcessHostIdField[] = "workerProcessHostId"; | |
| 47 static const char kWorkerRouteIdField[] = "workerRouteId"; | |
| 48 static const char kUrlField[] = "url"; | |
| 49 static const char kNameField[] = "name"; | |
| 50 static const char kPidField[] = "pid"; | |
| 51 | |
| 52 namespace { | |
| 53 | |
| 54 | |
| 55 DictionaryValue* BuildWorkerData( | |
| 56 const GURL& url, | |
| 57 const string16& name, | |
| 58 int process_id, | |
| 59 int route_id, | |
| 60 base::ProcessHandle handle) { | |
| 61 DictionaryValue* worker_data = new DictionaryValue(); | |
| 62 worker_data->SetInteger(kWorkerProcessHostIdField, process_id); | |
| 63 worker_data->SetInteger(kWorkerRouteIdField, route_id); | |
| 64 worker_data->SetString(kUrlField, url.spec()); | |
| 65 worker_data->SetString(kNameField, name); | |
| 66 worker_data->SetInteger(kPidField, base::GetProcId(handle)); | |
| 67 return worker_data; | |
| 68 } | |
| 69 | |
| 70 class WorkersUIHTMLSource : public ChromeWebUIDataSource { | |
| 71 public: | |
| 72 WorkersUIHTMLSource(); | |
| 73 | |
| 74 virtual void StartDataRequest(const std::string& path, | |
| 75 bool is_incognito, | |
| 76 int request_id); | |
| 77 private: | |
| 78 ~WorkersUIHTMLSource() {} | |
| 79 void SendSharedWorkersData(int request_id); | |
| 80 DISALLOW_COPY_AND_ASSIGN(WorkersUIHTMLSource); | |
| 81 }; | |
| 82 | |
| 83 WorkersUIHTMLSource::WorkersUIHTMLSource() | |
| 84 : ChromeWebUIDataSource(chrome::kChromeUIWorkersHost, NULL) { | |
| 85 add_resource_path("workers.js", IDR_WORKERS_INDEX_JS); | |
| 86 set_default_resource(IDR_WORKERS_INDEX_HTML); | |
| 87 } | |
| 88 | |
| 89 void WorkersUIHTMLSource::StartDataRequest(const std::string& path, | |
| 90 bool is_incognito, | |
| 91 int request_id) { | |
| 92 if (path == kWorkersDataFile) { | |
| 93 SendSharedWorkersData(request_id); | |
| 94 } else { | |
| 95 ChromeWebUIDataSource::StartDataRequest(path, is_incognito, request_id); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 void WorkersUIHTMLSource::SendSharedWorkersData(int request_id) { | |
| 100 ListValue workers_list; | |
| 101 std::vector<WorkerService::WorkerInfo> worker_info = | |
| 102 WorkerService::GetInstance()->GetWorkers(); | |
| 103 for (size_t i = 0; i < worker_info.size(); ++i) { | |
| 104 workers_list.Append(BuildWorkerData( | |
| 105 worker_info[i].url, worker_info[i].name, worker_info[i].process_id, | |
| 106 worker_info[i].route_id, worker_info[i].handle)); | |
| 107 } | |
| 108 | |
| 109 std::string json_string; | |
| 110 base::JSONWriter::Write(&workers_list, &json_string); | |
| 111 | |
| 112 SendResponse(request_id, base::RefCountedString::TakeString(&json_string)); | |
| 113 } | |
| 114 | |
| 115 class WorkersDOMHandler : public WebUIMessageHandler { | |
| 116 public: | |
| 117 WorkersDOMHandler() {} | |
| 118 virtual ~WorkersDOMHandler() {} | |
| 119 | |
| 120 private: | |
| 121 // WebUIMessageHandler implementation. | |
| 122 virtual void RegisterMessages() OVERRIDE; | |
| 123 | |
| 124 // Callback for "openDevTools" message. | |
| 125 void HandleOpenDevTools(const ListValue* args); | |
| 126 void HandleTerminateWorker(const ListValue* args); | |
| 127 | |
| 128 DISALLOW_COPY_AND_ASSIGN(WorkersDOMHandler); | |
| 129 }; | |
| 130 | |
| 131 void WorkersDOMHandler::RegisterMessages() { | |
| 132 web_ui()->RegisterMessageCallback(kOpenDevToolsCommand, | |
| 133 base::Bind(&WorkersDOMHandler::HandleOpenDevTools, | |
| 134 base::Unretained(this))); | |
| 135 web_ui()->RegisterMessageCallback(kTerminateWorkerCommand, | |
| 136 base::Bind(&WorkersDOMHandler::HandleTerminateWorker, | |
| 137 base::Unretained(this))); | |
| 138 } | |
| 139 | |
| 140 void WorkersDOMHandler::HandleOpenDevTools(const ListValue* args) { | |
| 141 std::string worker_process_host_id_str; | |
| 142 std::string worker_route_id_str; | |
| 143 int worker_process_host_id; | |
| 144 int worker_route_id; | |
| 145 CHECK(args->GetSize() == 2); | |
| 146 CHECK(args->GetString(0, &worker_process_host_id_str)); | |
| 147 CHECK(args->GetString(1, &worker_route_id_str)); | |
| 148 CHECK(base::StringToInt(worker_process_host_id_str, | |
| 149 &worker_process_host_id)); | |
| 150 CHECK(base::StringToInt(worker_route_id_str, &worker_route_id)); | |
| 151 | |
| 152 Profile* profile = Profile::FromWebUI(web_ui()); | |
| 153 if (!profile) | |
| 154 return; | |
| 155 DevToolsAgentHost* agent_host = | |
| 156 DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( | |
| 157 worker_process_host_id, | |
| 158 worker_route_id); | |
| 159 DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host); | |
| 160 } | |
| 161 | |
| 162 static void TerminateWorker(int process_id, int route_id) { | |
| 163 WorkerService::GetInstance()->TerminateWorker(process_id, route_id); | |
| 164 } | |
| 165 | |
| 166 void WorkersDOMHandler::HandleTerminateWorker(const ListValue* args) { | |
| 167 std::string worker_process_host_id_str; | |
| 168 std::string worker_route_id_str; | |
| 169 int worker_process_host_id; | |
| 170 int worker_route_id; | |
| 171 CHECK(args->GetSize() == 2); | |
| 172 CHECK(args->GetString(0, &worker_process_host_id_str)); | |
| 173 CHECK(args->GetString(1, &worker_route_id_str)); | |
| 174 CHECK(base::StringToInt(worker_process_host_id_str, | |
| 175 &worker_process_host_id)); | |
| 176 CHECK(base::StringToInt(worker_route_id_str, &worker_route_id)); | |
| 177 | |
| 178 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 179 base::Bind(&TerminateWorker, worker_process_host_id, worker_route_id)); | |
| 180 } | |
| 181 | |
| 182 } // namespace | |
| 183 | |
| 184 class WorkersUI::WorkerCreationDestructionListener | |
| 185 : public WorkerServiceObserver, | |
| 186 public base::RefCountedThreadSafe<WorkerCreationDestructionListener> { | |
| 187 public: | |
| 188 explicit WorkerCreationDestructionListener(WorkersUI* workers_ui) | |
| 189 : workers_ui_(workers_ui) { | |
| 190 BrowserThread::PostTask( | |
| 191 BrowserThread::IO, FROM_HERE, | |
| 192 base::Bind(&WorkerCreationDestructionListener::RegisterObserver, | |
| 193 this)); | |
| 194 } | |
| 195 | |
| 196 void WorkersUIDestroyed() { | |
| 197 workers_ui_ = NULL; | |
| 198 BrowserThread::PostTask( | |
| 199 BrowserThread::IO, FROM_HERE, | |
| 200 base::Bind(&WorkerCreationDestructionListener::UnregisterObserver, | |
| 201 this)); | |
| 202 } | |
| 203 | |
| 204 private: | |
| 205 friend class base::RefCountedThreadSafe<WorkerCreationDestructionListener>; | |
| 206 virtual ~WorkerCreationDestructionListener() { | |
| 207 } | |
| 208 | |
| 209 virtual void WorkerCreated( | |
| 210 const GURL& url, | |
| 211 const string16& name, | |
| 212 int process_id, | |
| 213 int route_id) OVERRIDE { | |
| 214 BrowserThread::PostTask( | |
| 215 BrowserThread::UI, FROM_HERE, | |
| 216 base::Bind(&WorkerCreationDestructionListener::NotifyWorkerCreated, | |
| 217 this, | |
| 218 base::Owned(BuildWorkerData(url, name, process_id, route_id, | |
| 219 base::kNullProcessHandle)))); | |
| 220 } | |
| 221 virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE { | |
| 222 DictionaryValue* worker_data = new DictionaryValue(); | |
| 223 worker_data->SetInteger(kWorkerProcessHostIdField, process_id); | |
| 224 worker_data->SetInteger(kWorkerRouteIdField, route_id); | |
| 225 | |
| 226 BrowserThread::PostTask( | |
| 227 BrowserThread::UI, FROM_HERE, | |
| 228 base::Bind(&WorkerCreationDestructionListener::NotifyWorkerDestroyed, | |
| 229 this, base::Owned(worker_data))); | |
| 230 } | |
| 231 | |
| 232 void NotifyWorkerCreated(DictionaryValue* worker_data) { | |
| 233 if (workers_ui_) { | |
| 234 workers_ui_->web_ui()->CallJavascriptFunction( | |
| 235 "workerCreated", *worker_data); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 void NotifyWorkerDestroyed(DictionaryValue* worker_data) { | |
| 240 if (workers_ui_) { | |
| 241 workers_ui_->web_ui()->CallJavascriptFunction( | |
| 242 "workerDestroyed", *worker_data); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 void RegisterObserver() { | |
| 247 WorkerService::GetInstance()->AddObserver(this); | |
| 248 } | |
| 249 void UnregisterObserver() { | |
| 250 WorkerService::GetInstance()->RemoveObserver(this); | |
| 251 } | |
| 252 | |
| 253 WorkersUI* workers_ui_; | |
| 254 }; | |
| 255 | |
| 256 WorkersUI::WorkersUI(content::WebUI* web_ui) | |
| 257 : WebUIController(web_ui), | |
| 258 observer_(new WorkerCreationDestructionListener(this)){ | |
| 259 web_ui->AddMessageHandler(new WorkersDOMHandler()); | |
| 260 | |
| 261 WorkersUIHTMLSource* html_source = new WorkersUIHTMLSource(); | |
| 262 | |
| 263 // Set up the chrome://workers/ source. | |
| 264 Profile* profile = Profile::FromWebUI(web_ui); | |
| 265 profile->GetChromeURLDataManager()->AddDataSource(html_source); | |
| 266 } | |
| 267 | |
| 268 WorkersUI::~WorkersUI() { | |
| 269 observer_->WorkersUIDestroyed(); | |
| 270 observer_ = NULL; | |
| 271 } | |
| OLD | NEW |