| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // Implementation of the ExtensionPortsRemoteService. | 5 // Implementation of the ExtensionPortsRemoteService. |
| 6 | 6 |
| 7 // Inspired significantly from debugger_remote_service | 7 // Inspired significantly from debugger_remote_service |
| 8 // and ../automation/extension_port_container. | 8 // and ../automation/extension_port_container. |
| 9 | 9 |
| 10 #include "chrome/browser/debugger/extension_ports_remote_service.h" | 10 #include "chrome/browser/debugger/extension_ports_remote_service.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 // "result": 0, (Always 0) | 67 // "result": 0, (Always 0) |
| 68 // "data": <message body - arbitrary JSON> | 68 // "data": <message body - arbitrary JSON> |
| 69 // } | 69 // } |
| 70 // | 70 // |
| 71 // The "disconnect" command from the external client, and | 71 // The "disconnect" command from the external client, and |
| 72 // "onDisconnect" notification from the ExtensionMessageService, are | 72 // "onDisconnect" notification from the ExtensionMessageService, are |
| 73 // similar: with the message port ID in the destination field, but no | 73 // similar: with the message port ID in the destination field, but no |
| 74 // "data" field in this case. | 74 // "data" field in this case. |
| 75 | 75 |
| 76 // Commands: | 76 // Commands: |
| 77 static const std::string kConnect = "connect"; | 77 const char kConnect[] = "connect"; |
| 78 static const std::string kDisconnect = "disconnect"; | 78 const char kDisconnect[] = "disconnect"; |
| 79 static const std::string kPostMessage = "postMessage"; | 79 const char kPostMessage[] = "postMessage"; |
| 80 // Events: | 80 // Events: |
| 81 static const std::string kOnMessage = "onMessage"; | 81 const char kOnMessage[] = "onMessage"; |
| 82 static const std::string kOnDisconnect = "onDisconnect"; | 82 const char kOnDisconnect[] = "onDisconnect"; |
| 83 | 83 |
| 84 // Constants for the JSON message fields. | 84 // Constants for the JSON message fields. |
| 85 // The type is wstring because the constant is used to get a | 85 // The type is wstring because the constant is used to get a |
| 86 // DictionaryValue field (which requires a wide string). | 86 // DictionaryValue field (which requires a wide string). |
| 87 | 87 |
| 88 // Mandatory. | 88 // Mandatory. |
| 89 static const std::wstring kCommandWide = L"command"; | 89 const char kCommandKey[] = "command"; |
| 90 | 90 |
| 91 // Always present in messages sent to the external client. | 91 // Always present in messages sent to the external client. |
| 92 static const std::wstring kResultWide = L"result"; | 92 const char kResultKey[] = "result"; |
| 93 | 93 |
| 94 // Field for command-specific parameters. Not strictly necessary, but | 94 // Field for command-specific parameters. Not strictly necessary, but |
| 95 // makes it more similar to the remote debugger protocol, which should | 95 // makes it more similar to the remote debugger protocol, which should |
| 96 // allow easier reuse of client code. | 96 // allow easier reuse of client code. |
| 97 static const std::wstring kDataWide = L"data"; | 97 const char kDataKey[] = "data"; |
| 98 | 98 |
| 99 // Fields within the "data" dictionary: | 99 // Fields within the "data" dictionary: |
| 100 | 100 |
| 101 // Required for "connect": | 101 // Required for "connect": |
| 102 static const std::wstring kExtensionIdWide = L"extensionId"; | 102 const char kExtensionIdKey[] = "extensionId"; |
| 103 // Optional in "connect": | 103 // Optional in "connect": |
| 104 static const std::wstring kChannelNameWide = L"channelName"; | 104 const char kChannelNameKey[] = "channelName"; |
| 105 static const std::wstring kTabIdWide = L"tabId"; | 105 const char kTabIdKey[] = "tabId"; |
| 106 | 106 |
| 107 // Present under "data" in replies to a successful "connect" . | 107 // Present under "data" in replies to a successful "connect" . |
| 108 static const std::wstring kPortIdWide = L"portId"; | 108 const char kPortIdKey[] = "portId"; |
| 109 | 109 |
| 110 } // namespace | 110 } // namespace |
| 111 | 111 |
| 112 const std::string ExtensionPortsRemoteService::kToolName = "ExtensionPorts"; | 112 const std::string ExtensionPortsRemoteService::kToolName = "ExtensionPorts"; |
| 113 | 113 |
| 114 ExtensionPortsRemoteService::ExtensionPortsRemoteService( | 114 ExtensionPortsRemoteService::ExtensionPortsRemoteService( |
| 115 DevToolsProtocolHandler* delegate) | 115 DevToolsProtocolHandler* delegate) |
| 116 : delegate_(delegate), service_(NULL) { | 116 : delegate_(delegate), service_(NULL) { |
| 117 // We need an ExtensionMessageService instance. It hangs off of | 117 // We need an ExtensionMessageService instance. It hangs off of |
| 118 // |profile|. But we do not have a particular tab or RenderViewHost | 118 // |profile|. But we do not have a particular tab or RenderViewHost |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 // Bad JSON | 152 // Bad JSON |
| 153 NOTREACHED(); | 153 NOTREACHED(); |
| 154 return; | 154 return; |
| 155 } | 155 } |
| 156 DictionaryValue* content; | 156 DictionaryValue* content; |
| 157 if (!request->IsType(Value::TYPE_DICTIONARY)) { | 157 if (!request->IsType(Value::TYPE_DICTIONARY)) { |
| 158 NOTREACHED(); // Broken protocol :( | 158 NOTREACHED(); // Broken protocol :( |
| 159 return; | 159 return; |
| 160 } | 160 } |
| 161 content = static_cast<DictionaryValue*>(request.get()); | 161 content = static_cast<DictionaryValue*>(request.get()); |
| 162 if (!content->HasKey(kCommandWide)) { | 162 if (!content->HasKey(kCommandKey)) { |
| 163 NOTREACHED(); // Broken protocol :( | 163 NOTREACHED(); // Broken protocol :( |
| 164 return; | 164 return; |
| 165 } | 165 } |
| 166 std::string command; | 166 std::string command; |
| 167 DictionaryValue response; | 167 DictionaryValue response; |
| 168 | 168 |
| 169 content->GetString(kCommandWide, &command); | 169 content->GetString(kCommandKey, &command); |
| 170 response.SetString(kCommandWide, command); | 170 response.SetString(kCommandKey, command); |
| 171 | 171 |
| 172 if (!service_) { | 172 if (!service_) { |
| 173 // This happens if we failed to obtain an ExtensionMessageService | 173 // This happens if we failed to obtain an ExtensionMessageService |
| 174 // during initialization. | 174 // during initialization. |
| 175 NOTREACHED(); | 175 NOTREACHED(); |
| 176 response.SetInteger(kResultWide, RESULT_NO_SERVICE); | 176 response.SetInteger(kResultKey, RESULT_NO_SERVICE); |
| 177 SendResponse(response, message.tool(), message.destination()); | 177 SendResponse(response, message.tool(), message.destination()); |
| 178 return; | 178 return; |
| 179 } | 179 } |
| 180 | 180 |
| 181 int destination = -1; | 181 int destination = -1; |
| 182 if (destinationString.size() != 0) | 182 if (destinationString.size() != 0) |
| 183 base::StringToInt(destinationString, &destination); | 183 base::StringToInt(destinationString, &destination); |
| 184 | 184 |
| 185 if (command == kConnect) { | 185 if (command == kConnect) { |
| 186 if (destination != -1) // destination should be empty for this command. | 186 if (destination != -1) // destination should be empty for this command. |
| 187 response.SetInteger(kResultWide, RESULT_UNKNOWN_COMMAND); | 187 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
| 188 else | 188 else |
| 189 ConnectCommand(content, &response); | 189 ConnectCommand(content, &response); |
| 190 } else if (command == kDisconnect) { | 190 } else if (command == kDisconnect) { |
| 191 if (destination == -1) // Destination required for this command. | 191 if (destination == -1) // Destination required for this command. |
| 192 response.SetInteger(kResultWide, RESULT_UNKNOWN_COMMAND); | 192 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
| 193 else | 193 else |
| 194 DisconnectCommand(destination, &response); | 194 DisconnectCommand(destination, &response); |
| 195 } else if (command == kPostMessage) { | 195 } else if (command == kPostMessage) { |
| 196 if (destination == -1) // Destination required for this command. | 196 if (destination == -1) // Destination required for this command. |
| 197 response.SetInteger(kResultWide, RESULT_UNKNOWN_COMMAND); | 197 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
| 198 else | 198 else |
| 199 PostMessageCommand(destination, content, &response); | 199 PostMessageCommand(destination, content, &response); |
| 200 } else { | 200 } else { |
| 201 // Unknown command | 201 // Unknown command |
| 202 NOTREACHED(); | 202 NOTREACHED(); |
| 203 response.SetInteger(kResultWide, RESULT_UNKNOWN_COMMAND); | 203 response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
| 204 } | 204 } |
| 205 SendResponse(response, message.tool(), message.destination()); | 205 SendResponse(response, message.tool(), message.destination()); |
| 206 } | 206 } |
| 207 | 207 |
| 208 void ExtensionPortsRemoteService::OnConnectionLost() { | 208 void ExtensionPortsRemoteService::OnConnectionLost() { |
| 209 LOG(INFO) << "OnConnectionLost"; | 209 LOG(INFO) << "OnConnectionLost"; |
| 210 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | 210 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); |
| 211 DCHECK(service_); | 211 DCHECK(service_); |
| 212 for (PortIdSet::iterator it = openPortIds_.begin(); | 212 for (PortIdSet::iterator it = openPortIds_.begin(); |
| 213 it != openPortIds_.end(); | 213 it != openPortIds_.end(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 NOTREACHED() << function_name << " shouldn't be called."; | 264 NOTREACHED() << function_name << " shouldn't be called."; |
| 265 } | 265 } |
| 266 } | 266 } |
| 267 | 267 |
| 268 void ExtensionPortsRemoteService::OnExtensionMessage( | 268 void ExtensionPortsRemoteService::OnExtensionMessage( |
| 269 const std::string& message, int port_id) { | 269 const std::string& message, int port_id) { |
| 270 LOG(INFO) << "Message event: from port " << port_id | 270 LOG(INFO) << "Message event: from port " << port_id |
| 271 << ", < " << message << ">"; | 271 << ", < " << message << ">"; |
| 272 // Transpose the information into a JSON message for the external client. | 272 // Transpose the information into a JSON message for the external client. |
| 273 DictionaryValue content; | 273 DictionaryValue content; |
| 274 content.SetString(kCommandWide, kOnMessage); | 274 content.SetString(kCommandKey, kOnMessage); |
| 275 content.SetInteger(kResultWide, RESULT_OK); | 275 content.SetInteger(kResultKey, RESULT_OK); |
| 276 // Turn the stringified message body back into JSON. | 276 // Turn the stringified message body back into JSON. |
| 277 Value* data = base::JSONReader::Read(message, false); | 277 Value* data = base::JSONReader::Read(message, false); |
| 278 if (!data) { | 278 if (!data) { |
| 279 NOTREACHED(); | 279 NOTREACHED(); |
| 280 return; | 280 return; |
| 281 } | 281 } |
| 282 content.Set(kDataWide, data); | 282 content.Set(kDataKey, data); |
| 283 SendResponse(content, kToolName, base::IntToString(port_id)); | 283 SendResponse(content, kToolName, base::IntToString(port_id)); |
| 284 } | 284 } |
| 285 | 285 |
| 286 void ExtensionPortsRemoteService::OnExtensionPortDisconnected(int port_id) { | 286 void ExtensionPortsRemoteService::OnExtensionPortDisconnected(int port_id) { |
| 287 LOG(INFO) << "Disconnect event for port " << port_id; | 287 LOG(INFO) << "Disconnect event for port " << port_id; |
| 288 openPortIds_.erase(port_id); | 288 openPortIds_.erase(port_id); |
| 289 DictionaryValue content; | 289 DictionaryValue content; |
| 290 content.SetString(kCommandWide, kOnDisconnect); | 290 content.SetString(kCommandKey, kOnDisconnect); |
| 291 content.SetInteger(kResultWide, RESULT_OK); | 291 content.SetInteger(kResultKey, RESULT_OK); |
| 292 SendResponse(content, kToolName, base::IntToString(port_id)); | 292 SendResponse(content, kToolName, base::IntToString(port_id)); |
| 293 } | 293 } |
| 294 | 294 |
| 295 void ExtensionPortsRemoteService::ConnectCommand( | 295 void ExtensionPortsRemoteService::ConnectCommand( |
| 296 DictionaryValue* content, DictionaryValue* response) { | 296 DictionaryValue* content, DictionaryValue* response) { |
| 297 // Parse out the parameters. | 297 // Parse out the parameters. |
| 298 DictionaryValue* data; | 298 DictionaryValue* data; |
| 299 if (!content->GetDictionary(kDataWide, &data)) { | 299 if (!content->GetDictionary(kDataKey, &data)) { |
| 300 response->SetInteger(kResultWide, RESULT_PARAMETER_ERROR); | 300 response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
| 301 return; | 301 return; |
| 302 } | 302 } |
| 303 std::string extension_id; | 303 std::string extension_id; |
| 304 if (!data->GetString(kExtensionIdWide, &extension_id)) { | 304 if (!data->GetString(kExtensionIdKey, &extension_id)) { |
| 305 response->SetInteger(kResultWide, RESULT_PARAMETER_ERROR); | 305 response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
| 306 return; | 306 return; |
| 307 } | 307 } |
| 308 std::string channel_name = ""; | 308 std::string channel_name = ""; |
| 309 data->GetString(kChannelNameWide, &channel_name); // optional. | 309 data->GetString(kChannelNameKey, &channel_name); // optional. |
| 310 int tab_id = -1; | 310 int tab_id = -1; |
| 311 data->GetInteger(kTabIdWide, &tab_id); // optional. | 311 data->GetInteger(kTabIdKey, &tab_id); // optional. |
| 312 int port_id; | 312 int port_id; |
| 313 if (tab_id != -1) { // Resolve the tab ID. | 313 if (tab_id != -1) { // Resolve the tab ID. |
| 314 const InspectableTabProxy::ControllersMap& navcon_map = | 314 const InspectableTabProxy::ControllersMap& navcon_map = |
| 315 delegate_->inspectable_tab_proxy()->controllers_map(); | 315 delegate_->inspectable_tab_proxy()->controllers_map(); |
| 316 InspectableTabProxy::ControllersMap::const_iterator it = | 316 InspectableTabProxy::ControllersMap::const_iterator it = |
| 317 navcon_map.find(tab_id); | 317 navcon_map.find(tab_id); |
| 318 TabContents* tab_contents = NULL; | 318 TabContents* tab_contents = NULL; |
| 319 if (it != navcon_map.end()) | 319 if (it != navcon_map.end()) |
| 320 tab_contents = it->second->tab_contents(); | 320 tab_contents = it->second->tab_contents(); |
| 321 if (!tab_contents) { | 321 if (!tab_contents) { |
| 322 LOG(INFO) << "tab not found: " << tab_id; | 322 LOG(INFO) << "tab not found: " << tab_id; |
| 323 response->SetInteger(kResultWide, RESULT_TAB_NOT_FOUND); | 323 response->SetInteger(kResultKey, RESULT_TAB_NOT_FOUND); |
| 324 return; | 324 return; |
| 325 } | 325 } |
| 326 // Ask the ExtensionMessageService to open the channel. | 326 // Ask the ExtensionMessageService to open the channel. |
| 327 LOG(INFO) << "Connect: extension_id <" << extension_id | 327 LOG(INFO) << "Connect: extension_id <" << extension_id |
| 328 << ">, channel_name <" << channel_name << ">" | 328 << ">, channel_name <" << channel_name << ">" |
| 329 << ", tab " << tab_id; | 329 << ", tab " << tab_id; |
| 330 DCHECK(service_); | 330 DCHECK(service_); |
| 331 port_id = service_->OpenSpecialChannelToTab( | 331 port_id = service_->OpenSpecialChannelToTab( |
| 332 extension_id, channel_name, tab_contents, this); | 332 extension_id, channel_name, tab_contents, this); |
| 333 } else { // no tab: channel to an extension' background page / toolstrip. | 333 } else { // no tab: channel to an extension' background page / toolstrip. |
| 334 // Ask the ExtensionMessageService to open the channel. | 334 // Ask the ExtensionMessageService to open the channel. |
| 335 LOG(INFO) << "Connect: extension_id <" << extension_id | 335 LOG(INFO) << "Connect: extension_id <" << extension_id |
| 336 << ">, channel_name <" << channel_name << ">"; | 336 << ">, channel_name <" << channel_name << ">"; |
| 337 DCHECK(service_); | 337 DCHECK(service_); |
| 338 port_id = service_->OpenSpecialChannelToExtension( | 338 port_id = service_->OpenSpecialChannelToExtension( |
| 339 extension_id, channel_name, "null", this); | 339 extension_id, channel_name, "null", this); |
| 340 } | 340 } |
| 341 if (port_id == -1) { | 341 if (port_id == -1) { |
| 342 // Failure: probably the extension ID doesn't exist. | 342 // Failure: probably the extension ID doesn't exist. |
| 343 LOG(INFO) << "Connect failed"; | 343 LOG(INFO) << "Connect failed"; |
| 344 response->SetInteger(kResultWide, RESULT_CONNECT_FAILED); | 344 response->SetInteger(kResultKey, RESULT_CONNECT_FAILED); |
| 345 return; | 345 return; |
| 346 } | 346 } |
| 347 LOG(INFO) << "Connected: port " << port_id; | 347 LOG(INFO) << "Connected: port " << port_id; |
| 348 openPortIds_.insert(port_id); | 348 openPortIds_.insert(port_id); |
| 349 // Reply to external client with the port ID assigned to the new channel. | 349 // Reply to external client with the port ID assigned to the new channel. |
| 350 DictionaryValue* reply_data = new DictionaryValue(); | 350 DictionaryValue* reply_data = new DictionaryValue(); |
| 351 reply_data->SetInteger(kPortIdWide, port_id); | 351 reply_data->SetInteger(kPortIdKey, port_id); |
| 352 response->Set(kDataWide, reply_data); | 352 response->Set(kDataKey, reply_data); |
| 353 response->SetInteger(kResultWide, RESULT_OK); | 353 response->SetInteger(kResultKey, RESULT_OK); |
| 354 } | 354 } |
| 355 | 355 |
| 356 void ExtensionPortsRemoteService::DisconnectCommand( | 356 void ExtensionPortsRemoteService::DisconnectCommand( |
| 357 int port_id, DictionaryValue* response) { | 357 int port_id, DictionaryValue* response) { |
| 358 LOG(INFO) << "Disconnect port " << port_id; | 358 LOG(INFO) << "Disconnect port " << port_id; |
| 359 PortIdSet::iterator portEntry = openPortIds_.find(port_id); | 359 PortIdSet::iterator portEntry = openPortIds_.find(port_id); |
| 360 if (portEntry == openPortIds_.end()) { // unknown port ID. | 360 if (portEntry == openPortIds_.end()) { // unknown port ID. |
| 361 LOG(INFO) << "unknown port: " << port_id; | 361 LOG(INFO) << "unknown port: " << port_id; |
| 362 response->SetInteger(kResultWide, RESULT_UNKNOWN_PORT); | 362 response->SetInteger(kResultKey, RESULT_UNKNOWN_PORT); |
| 363 return; | 363 return; |
| 364 } | 364 } |
| 365 DCHECK(service_); | 365 DCHECK(service_); |
| 366 service_->CloseChannel(port_id); | 366 service_->CloseChannel(port_id); |
| 367 openPortIds_.erase(portEntry); | 367 openPortIds_.erase(portEntry); |
| 368 response->SetInteger(kResultWide, RESULT_OK); | 368 response->SetInteger(kResultKey, RESULT_OK); |
| 369 } | 369 } |
| 370 | 370 |
| 371 void ExtensionPortsRemoteService::PostMessageCommand( | 371 void ExtensionPortsRemoteService::PostMessageCommand( |
| 372 int port_id, DictionaryValue* content, DictionaryValue* response) { | 372 int port_id, DictionaryValue* content, DictionaryValue* response) { |
| 373 Value* data; | 373 Value* data; |
| 374 if (!content->Get(kDataWide, &data)) { | 374 if (!content->Get(kDataKey, &data)) { |
| 375 response->SetInteger(kResultWide, RESULT_PARAMETER_ERROR); | 375 response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
| 376 return; | 376 return; |
| 377 } | 377 } |
| 378 std::string message; | 378 std::string message; |
| 379 // Stringified the JSON message body. | 379 // Stringified the JSON message body. |
| 380 base::JSONWriter::Write(data, false, &message); | 380 base::JSONWriter::Write(data, false, &message); |
| 381 LOG(INFO) << "postMessage: port " << port_id | 381 LOG(INFO) << "postMessage: port " << port_id |
| 382 << ", message: <" << message << ">"; | 382 << ", message: <" << message << ">"; |
| 383 PortIdSet::iterator portEntry = openPortIds_.find(port_id); | 383 PortIdSet::iterator portEntry = openPortIds_.find(port_id); |
| 384 if (portEntry == openPortIds_.end()) { // Unknown port ID. | 384 if (portEntry == openPortIds_.end()) { // Unknown port ID. |
| 385 LOG(INFO) << "unknown port: " << port_id; | 385 LOG(INFO) << "unknown port: " << port_id; |
| 386 response->SetInteger(kResultWide, RESULT_UNKNOWN_PORT); | 386 response->SetInteger(kResultKey, RESULT_UNKNOWN_PORT); |
| 387 return; | 387 return; |
| 388 } | 388 } |
| 389 // Post the message through the ExtensionMessageService. | 389 // Post the message through the ExtensionMessageService. |
| 390 DCHECK(service_); | 390 DCHECK(service_); |
| 391 service_->PostMessageFromRenderer(port_id, message); | 391 service_->PostMessageFromRenderer(port_id, message); |
| 392 // Confirm to the external client that we sent its message. | 392 // Confirm to the external client that we sent its message. |
| 393 response->SetInteger(kResultWide, RESULT_OK); | 393 response->SetInteger(kResultKey, RESULT_OK); |
| 394 } | 394 } |
| OLD | NEW |