Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" | 5 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" |
| 6 | 6 |
| 7 #include <utility> | |
| 8 | |
| 7 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 9 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 10 #include "chrome/browser/devtools/device/android_device_manager.h" | 12 #include "chrome/browser/devtools/device/android_device_manager.h" |
| 11 #include "chrome/browser/devtools/device/tcp_device_provider.h" | 13 #include "chrome/browser/devtools/device/tcp_device_provider.h" |
| 12 #include "chrome/browser/devtools/devtools_network_protocol_handler.h" | 14 #include "chrome/browser/devtools/devtools_network_protocol_handler.h" |
| 13 #include "chrome/browser/devtools/devtools_protocol_constants.h" | 15 #include "chrome/browser/devtools/devtools_protocol_constants.h" |
| 14 #include "chrome/browser/devtools/devtools_window.h" | 16 #include "chrome/browser/devtools/devtools_window.h" |
| 15 #include "chrome/browser/extensions/extension_tab_util.h" | 17 #include "chrome/browser/extensions/extension_tab_util.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/profiles/profile_manager.h" | 19 #include "chrome/browser/profiles/profile_manager.h" |
| 18 #include "chrome/browser/ui/browser_navigator.h" | 20 #include "chrome/browser/ui/browser_navigator.h" |
| 19 #include "chrome/browser/ui/browser_navigator_params.h" | 21 #include "chrome/browser/ui/browser_navigator_params.h" |
| 22 #include "chrome/browser/ui/browser_window.h" | |
| 23 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" | |
| 20 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" | 24 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
| 25 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 21 #include "chrome/grit/browser_resources.h" | 26 #include "chrome/grit/browser_resources.h" |
| 22 #include "components/guest_view/browser/guest_view_base.h" | 27 #include "components/guest_view/browser/guest_view_base.h" |
| 23 #include "content/public/browser/devtools_agent_host.h" | 28 #include "content/public/browser/devtools_agent_host.h" |
| 24 #include "content/public/browser/render_frame_host.h" | 29 #include "content/public/browser/render_frame_host.h" |
| 25 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
| 26 #include "extensions/browser/extension_host.h" | 31 #include "extensions/browser/extension_host.h" |
| 27 #include "extensions/browser/extension_registry.h" | 32 #include "extensions/browser/extension_registry.h" |
| 28 #include "extensions/browser/process_manager.h" | 33 #include "extensions/browser/process_manager.h" |
| 29 #include "ui/base/resource/resource_bundle.h" | 34 #include "ui/base/resource/resource_bundle.h" |
| 30 | 35 |
| 31 using content::DevToolsAgentHost; | 36 using content::DevToolsAgentHost; |
| 32 | 37 |
| 33 char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; | 38 char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; |
| 34 char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = "background_page"; | 39 char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = "background_page"; |
| 35 char ChromeDevToolsManagerDelegate::kTypeWebView[] = "webview"; | 40 char ChromeDevToolsManagerDelegate::kTypeWebView[] = "webview"; |
| 36 | 41 |
| 37 char kLocationsParam[] = "locations"; | 42 char kLocationsParam[] = "locations"; |
| 38 char kHostParam[] = "host"; | 43 char kHostParam[] = "host"; |
| 39 char kPortParam[] = "port"; | 44 char kPortParam[] = "port"; |
| 40 | 45 |
| 46 namespace { | |
| 47 | |
| 48 BrowserWindow* GetBrowserWindow(int window_id) { | |
| 49 for (auto* b : *BrowserList::GetInstance()) { | |
| 50 if (b->session_id().id() == window_id) | |
| 51 return b->window(); | |
| 52 } | |
| 53 return nullptr; | |
| 54 } | |
| 55 | |
| 56 // Get the bounds and state of the browser window. The bounds is for the | |
| 57 // restored window when the window is minimized. Otherwise, it is for the actual | |
| 58 // window. | |
| 59 std::unique_ptr<base::DictionaryValue> GetBounds(BrowserWindow* window) { | |
| 60 gfx::Rect bounds; | |
| 61 if (window->IsMinimized()) | |
| 62 bounds = window->GetRestoredBounds(); | |
| 63 else | |
| 64 bounds = window->GetBounds(); | |
| 65 | |
| 66 auto bounds_object = base::MakeUnique<base::DictionaryValue>(); | |
| 67 | |
| 68 bounds_object->SetInteger("left", bounds.x()); | |
| 69 bounds_object->SetInteger("top", bounds.y()); | |
| 70 bounds_object->SetInteger("width", bounds.width()); | |
| 71 bounds_object->SetInteger("height", bounds.height()); | |
| 72 | |
| 73 std::string window_state = "normal"; | |
| 74 if (window->IsMinimized()) | |
| 75 window_state = "minimized"; | |
| 76 if (window->IsMaximized()) | |
| 77 window_state = "maximized"; | |
| 78 if (window->IsFullscreen()) | |
| 79 window_state = "fullscreen"; | |
| 80 bounds_object->SetString("windowState", window_state); | |
| 81 | |
| 82 return bounds_object; | |
| 83 } | |
| 84 | |
| 85 // Encapsulates waiting for the browser window to change state, then perform | |
| 86 // Maximize. For example, on Mac, window->Maximize is ignored when the browser | |
| 87 // window is exiting fullscreen. | |
| 88 void Maximize(BrowserWindow* window, int retry_attempts) { | |
| 89 if (window->IsMaximized() || retry_attempts <= 0) | |
|
dgozman
2017/04/05 17:57:23
Retrying is a bad practice. Let's ask for help fro
jzfeng
2017/04/06 01:36:13
Sure, will do. Windows also has such problem, if E
| |
| 90 return; | |
| 91 window->Maximize(); | |
| 92 content::BrowserThread::PostDelayedTask( | |
| 93 content::BrowserThread::UI, FROM_HERE, | |
| 94 base::Bind(&Maximize, window, retry_attempts - 1), | |
| 95 base::TimeDelta::FromMilliseconds(100)); | |
| 96 } | |
| 97 | |
| 98 // Encapsulates waiting for the browser window to change state, then perform | |
| 99 // Minimize. For example, on Mac, window->Minimize is ignored when the browser | |
| 100 // window is exiting fullscreen. | |
| 101 void Minimize(BrowserWindow* window, int retry_attempts) { | |
| 102 if (window->IsMinimized() || retry_attempts <= 0) | |
| 103 return; | |
| 104 window->Minimize(); | |
| 105 content::BrowserThread::PostDelayedTask( | |
| 106 content::BrowserThread::UI, FROM_HERE, | |
| 107 base::Bind(&Minimize, window, retry_attempts - 1), | |
| 108 base::TimeDelta::FromMilliseconds(100)); | |
| 109 } | |
| 110 | |
| 111 // Encapsulates waiting for the browser window to change state, then perform | |
| 112 // SetBounds. For example, on Mac and Windows, window->SetBounds is ignored when | |
| 113 // the browser window is exiting fullscreen. | |
| 114 void SetBounds(BrowserWindow* window, gfx::Rect bounds, int retry_attempts) { | |
| 115 if (window->GetBounds() == bounds || retry_attempts <= 0) | |
| 116 return; | |
| 117 window->SetBounds(bounds); | |
| 118 content::BrowserThread::PostDelayedTask( | |
| 119 content::BrowserThread::UI, FROM_HERE, | |
| 120 base::Bind(&SetBounds, window, bounds, retry_attempts - 1), | |
| 121 base::TimeDelta::FromMilliseconds(100)); | |
| 122 } | |
| 123 | |
| 124 } // namespace | |
| 125 | |
| 126 // static | |
| 127 std::unique_ptr<base::DictionaryValue> | |
| 128 ChromeDevToolsManagerDelegate::GetWindowForTarget( | |
| 129 int id, | |
| 130 base::DictionaryValue* params) { | |
| 131 std::string target_id; | |
| 132 if (!params->GetString("targetId", &target_id)) | |
| 133 return DevToolsProtocol::CreateInvalidParamsResponse(id, "targetId"); | |
| 134 | |
| 135 Browser* browser = nullptr; | |
| 136 scoped_refptr<DevToolsAgentHost> host = | |
| 137 DevToolsAgentHost::GetForId(target_id); | |
| 138 if (!host) | |
| 139 return DevToolsProtocol::CreateErrorResponse(id, "No target with given id"); | |
| 140 content::WebContents* web_contents = host->GetWebContents(); | |
| 141 if (!web_contents) { | |
| 142 return DevToolsProtocol::CreateErrorResponse( | |
| 143 id, "No web contents in the target"); | |
| 144 } | |
| 145 for (auto* b : *BrowserList::GetInstance()) { | |
| 146 int tab_index = b->tab_strip_model()->GetIndexOfWebContents(web_contents); | |
| 147 if (tab_index != TabStripModel::kNoTab) | |
| 148 browser = b; | |
| 149 } | |
| 150 if (!browser) { | |
| 151 return DevToolsProtocol::CreateErrorResponse(id, | |
| 152 "Browser window not found"); | |
| 153 } | |
| 154 | |
| 155 auto result = base::MakeUnique<base::DictionaryValue>(); | |
| 156 result->SetInteger("windowId", browser->session_id().id()); | |
| 157 result->Set("bounds", GetBounds(browser->window())); | |
| 158 return DevToolsProtocol::CreateSuccessResponse(id, std::move(result)); | |
| 159 } | |
| 160 | |
| 161 // static | |
| 162 std::unique_ptr<base::DictionaryValue> | |
| 163 ChromeDevToolsManagerDelegate::GetWindowBounds(int id, | |
| 164 base::DictionaryValue* params) { | |
| 165 int window_id; | |
| 166 if (!params->GetInteger("windowId", &window_id)) | |
| 167 return DevToolsProtocol::CreateInvalidParamsResponse(id, "windowId"); | |
| 168 BrowserWindow* window = GetBrowserWindow(window_id); | |
| 169 if (!window) { | |
| 170 return DevToolsProtocol::CreateErrorResponse(id, | |
| 171 "Browser window not found"); | |
| 172 } | |
| 173 | |
| 174 auto result = base::MakeUnique<base::DictionaryValue>(); | |
| 175 result->Set("bounds", GetBounds(window)); | |
| 176 return DevToolsProtocol::CreateSuccessResponse(id, std::move(result)); | |
| 177 } | |
| 178 | |
| 179 // static | |
| 180 std::unique_ptr<base::DictionaryValue> | |
| 181 ChromeDevToolsManagerDelegate::SetWindowBounds(int id, | |
| 182 base::DictionaryValue* params) { | |
| 183 int window_id; | |
| 184 if (!params->GetInteger("windowId", &window_id)) | |
| 185 return DevToolsProtocol::CreateInvalidParamsResponse(id, "windowId"); | |
| 186 BrowserWindow* window = GetBrowserWindow(window_id); | |
| 187 if (!window) { | |
| 188 return DevToolsProtocol::CreateErrorResponse(id, | |
| 189 "Browser window not found"); | |
| 190 } | |
| 191 | |
| 192 const base::Value* value = nullptr; | |
| 193 const base::DictionaryValue* bounds_dict = nullptr; | |
| 194 if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict)) | |
| 195 return DevToolsProtocol::CreateInvalidParamsResponse(id, "bounds"); | |
| 196 | |
| 197 // Get the bounds before manipulating window state for safe. | |
| 198 gfx::Rect bounds; | |
| 199 if (window->IsMinimized() || window->IsMaximized() || window->IsFullscreen()) | |
| 200 bounds = window->GetRestoredBounds(); | |
| 201 else | |
| 202 bounds = window->GetBounds(); | |
| 203 | |
| 204 std::string window_state; | |
| 205 if (!bounds_dict->GetString("windowState", &window_state)) | |
| 206 window_state = "normal"; | |
| 207 else if (window_state != "normal" && window_state != "minimized" && | |
| 208 window_state != "maximized" && window_state != "fullscreen") | |
| 209 return DevToolsProtocol::CreateInvalidParamsResponse(id, "windowState"); | |
| 210 | |
| 211 if (window_state != "fullscreen" && window->IsFullscreen()) | |
| 212 window->GetExclusiveAccessContext()->ExitFullscreen(); | |
| 213 if (window_state != "minimized" && window->IsMinimized()) | |
| 214 window->Show(); | |
| 215 | |
| 216 const int max_retry_attempts = 10; | |
| 217 if (window_state == "minimized") { | |
| 218 Minimize(window, max_retry_attempts); | |
| 219 } else if (window_state == "maximized") { | |
| 220 Maximize(window, max_retry_attempts); | |
| 221 } else if (window_state == "fullscreen") { | |
| 222 window->GetExclusiveAccessContext()->EnterFullscreen( | |
| 223 GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE); | |
| 224 } else if (window->IsMaximized() || window->IsMinimized()) { | |
| 225 window->Restore(); | |
| 226 #if defined(OS_MACOSX) | |
| 227 // GetRestoredBounds behave differently on Mac. Get the actual restored | |
|
dgozman
2017/04/05 17:57:23
What's the difference? Let's ask someone from chro
jzfeng
2017/04/06 01:36:13
In mac, GetRestoredBounds is always exactly the sa
| |
| 228 // bounds here. | |
| 229 bounds = window->GetBounds(); | |
| 230 #endif | |
| 231 } | |
| 232 | |
| 233 // Compute updated bounds when window state is normal. | |
| 234 bool set_bounds = false; | |
| 235 int left, top, width, height; | |
| 236 if (bounds_dict->GetInteger("left", &left)) { | |
| 237 bounds.set_x(left); | |
| 238 set_bounds = true; | |
| 239 } | |
| 240 if (bounds_dict->GetInteger("top", &top)) { | |
| 241 bounds.set_y(top); | |
| 242 set_bounds = true; | |
| 243 } | |
| 244 if (bounds_dict->GetInteger("width", &width)) { | |
| 245 if (width < 0) | |
| 246 return DevToolsProtocol::CreateInvalidParamsResponse(id, "width"); | |
| 247 bounds.set_width(width); | |
| 248 set_bounds = true; | |
| 249 } | |
| 250 if (bounds_dict->GetInteger("height", &height)) { | |
| 251 if (height < 0) | |
| 252 return DevToolsProtocol::CreateInvalidParamsResponse(id, "height"); | |
| 253 bounds.set_height(height); | |
| 254 set_bounds = true; | |
| 255 } | |
| 256 | |
| 257 if (set_bounds && window_state != "normal") { | |
| 258 return DevToolsProtocol::CreateErrorResponse( | |
| 259 id, | |
| 260 "The 'minimized', 'maximized' and 'fullscreen' states cannot be " | |
| 261 "combined with 'left', 'top', 'width' or 'height'"); | |
| 262 } | |
| 263 | |
| 264 if (set_bounds) | |
| 265 SetBounds(window, bounds, max_retry_attempts); | |
| 266 | |
| 267 return DevToolsProtocol::CreateSuccessResponse(id, nullptr); | |
| 268 } | |
| 269 | |
| 270 std::unique_ptr<base::DictionaryValue> | |
| 271 ChromeDevToolsManagerDelegate::HandleBrowserCommand( | |
| 272 int id, | |
| 273 std::string method, | |
| 274 base::DictionaryValue* params) { | |
| 275 if (method == chrome::devtools::Browser::getWindowForTarget::kName) | |
| 276 return GetWindowForTarget(id, params); | |
| 277 if (method == chrome::devtools::Browser::getWindowBounds::kName) | |
| 278 return GetWindowBounds(id, params); | |
| 279 if (method == chrome::devtools::Browser::setWindowBounds::kName) | |
| 280 return SetWindowBounds(id, params); | |
| 281 return nullptr; | |
| 282 } | |
| 283 | |
| 41 class ChromeDevToolsManagerDelegate::HostData { | 284 class ChromeDevToolsManagerDelegate::HostData { |
| 42 public: | 285 public: |
| 43 HostData() {} | 286 HostData() {} |
| 44 ~HostData() {} | 287 ~HostData() {} |
| 45 | 288 |
| 46 RemoteLocations& remote_locations() { return remote_locations_; } | 289 RemoteLocations& remote_locations() { return remote_locations_; } |
| 47 | 290 |
| 48 void set_remote_locations(RemoteLocations& locations) { | 291 void set_remote_locations(RemoteLocations& locations) { |
| 49 remote_locations_.swap(locations); | 292 remote_locations_.swap(locations); |
| 50 } | 293 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 70 base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( | 313 base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( |
| 71 DevToolsAgentHost* agent_host, | 314 DevToolsAgentHost* agent_host, |
| 72 base::DictionaryValue* command_dict) { | 315 base::DictionaryValue* command_dict) { |
| 73 | 316 |
| 74 int id = 0; | 317 int id = 0; |
| 75 std::string method; | 318 std::string method; |
| 76 base::DictionaryValue* params = nullptr; | 319 base::DictionaryValue* params = nullptr; |
| 77 if (!DevToolsProtocol::ParseCommand(command_dict, &id, &method, ¶ms)) | 320 if (!DevToolsProtocol::ParseCommand(command_dict, &id, &method, ¶ms)) |
| 78 return nullptr; | 321 return nullptr; |
| 79 | 322 |
| 323 if (agent_host->GetType() == DevToolsAgentHost::kTypeBrowser && | |
| 324 method.find("Browser.") == 0) | |
| 325 return HandleBrowserCommand(id, method, params).release(); | |
| 326 | |
| 80 if (method == chrome::devtools::Target::setRemoteLocations::kName) | 327 if (method == chrome::devtools::Target::setRemoteLocations::kName) |
| 81 return SetRemoteLocations(agent_host, id, params).release(); | 328 return SetRemoteLocations(agent_host, id, params).release(); |
| 82 | 329 |
| 83 return network_protocol_handler_->HandleCommand(agent_host, command_dict); | 330 return network_protocol_handler_->HandleCommand(agent_host, command_dict); |
| 84 } | 331 } |
| 85 | 332 |
| 86 std::string ChromeDevToolsManagerDelegate::GetTargetType( | 333 std::string ChromeDevToolsManagerDelegate::GetTargetType( |
| 87 content::RenderFrameHost* host) { | 334 content::RenderFrameHost* host) { |
| 88 content::WebContents* web_contents = | 335 content::WebContents* web_contents = |
| 89 content::WebContents::FromRenderFrameHost(host); | 336 content::WebContents::FromRenderFrameHost(host); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 if (!dictionary->GetIntegerWithoutPathExpansion(kPortParam, &port)) { | 516 if (!dictionary->GetIntegerWithoutPathExpansion(kPortParam, &port)) { |
| 270 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, | 517 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, |
| 271 kLocationsParam); | 518 kLocationsParam); |
| 272 } | 519 } |
| 273 tcp_locations.insert(net::HostPortPair(host, port)); | 520 tcp_locations.insert(net::HostPortPair(host, port)); |
| 274 } | 521 } |
| 275 | 522 |
| 276 host_data_[agent_host]->set_remote_locations(tcp_locations); | 523 host_data_[agent_host]->set_remote_locations(tcp_locations); |
| 277 UpdateDeviceDiscovery(); | 524 UpdateDeviceDiscovery(); |
| 278 | 525 |
| 279 std::unique_ptr<base::DictionaryValue> result( | 526 return DevToolsProtocol::CreateSuccessResponse(command_id, nullptr); |
| 280 base::MakeUnique<base::DictionaryValue>()); | |
| 281 return DevToolsProtocol::CreateSuccessResponse(command_id, std::move(result)); | |
| 282 } | 527 } |
| OLD | NEW |