Index: chrome/browser/debugger/extension_ports_remote_service.cc |
diff --git a/chrome/browser/debugger/extension_ports_remote_service.cc b/chrome/browser/debugger/extension_ports_remote_service.cc |
deleted file mode 100644 |
index 028b9a5d621fa56fc5e89e3a9a3f2ab1df8812e4..0000000000000000000000000000000000000000 |
--- a/chrome/browser/debugger/extension_ports_remote_service.cc |
+++ /dev/null |
@@ -1,380 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// Implementation of the ExtensionPortsRemoteService. |
- |
-// Inspired significantly from debugger_remote_service |
-// and ../automation/extension_port_container. |
- |
-#include "chrome/browser/debugger/extension_ports_remote_service.h" |
- |
-#include "base/json/json_reader.h" |
-#include "base/json/json_writer.h" |
-#include "base/message_loop.h" |
-#include "base/string_number_conversions.h" |
-#include "base/values.h" |
-#include "chrome/browser/browser_process.h" |
-#include "chrome/browser/debugger/devtools_protocol_handler.h" |
-#include "chrome/browser/debugger/devtools_remote_message.h" |
-#include "chrome/browser/debugger/inspectable_tab_proxy.h" |
-#include "chrome/browser/profiles/profile_manager.h" |
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
-#include "chrome/common/extensions/extension_messages.h" |
-#include "content/browser/debugger/devtools_manager.h" |
-#include "content/browser/tab_contents/tab_contents.h" |
-#include "content/common/devtools_messages.h" |
- |
-namespace { |
- |
-// Protocol is as follows: |
-// |
-// From external client: |
-// {"command": "connect", |
-// "data": { |
-// "extensionId": "<extension_id string>", |
-// "channelName": "<port name string>", (optional) |
-// "tabId": <numerical tab ID> (optional) |
-// } |
-// } |
-// To connect to a background page or tool strip, the tabId should be omitted. |
-// Tab IDs can be enumerated with the list_tabs DevToolsService command. |
-// |
-// Response: |
-// {"command": "connect", |
-// "result": 0, (assuming success) |
-// "data": { |
-// "portId": <numerical port ID> |
-// } |
-// } |
-// |
-// Posting a message from external client: |
-// Put the target message port ID in the devtools destination field. |
-// {"command": "postMessage", |
-// "data": <message body - arbitrary JSON> |
-// } |
-// Response: |
-// {"command": "postMessage", |
-// "result": 0 (Assuming success) |
-// } |
-// Note this is a confirmation from the devtools protocol layer, not |
-// a response from the extension. |
-// |
-// Message from an extension to the external client: |
-// The message port ID is in the devtools destination field. |
-// {"command": "onMessage", |
-// "result": 0, (Always 0) |
-// "data": <message body - arbitrary JSON> |
-// } |
-// |
-// The "disconnect" command from the external client, and |
-// "onDisconnect" notification from the ExtensionMessageService, are |
-// similar: with the message port ID in the destination field, but no |
-// "data" field in this case. |
- |
-// Commands: |
-const char kConnect[] = "connect"; |
-const char kDisconnect[] = "disconnect"; |
-const char kPostMessage[] = "postMessage"; |
-// Events: |
-const char kOnMessage[] = "onMessage"; |
-const char kOnDisconnect[] = "onDisconnect"; |
- |
-// Constants for the JSON message fields. |
-// The type is wstring because the constant is used to get a |
-// DictionaryValue field (which requires a wide string). |
- |
-// Mandatory. |
-const char kCommandKey[] = "command"; |
- |
-// Always present in messages sent to the external client. |
-const char kResultKey[] = "result"; |
- |
-// Field for command-specific parameters. Not strictly necessary, but |
-// makes it more similar to the remote debugger protocol, which should |
-// allow easier reuse of client code. |
-const char kDataKey[] = "data"; |
- |
-// Fields within the "data" dictionary: |
- |
-// Required for "connect": |
-const char kExtensionIdKey[] = "extensionId"; |
-// Optional in "connect": |
-const char kChannelNameKey[] = "channelName"; |
-const char kTabIdKey[] = "tabId"; |
- |
-// Present under "data" in replies to a successful "connect" . |
-const char kPortIdKey[] = "portId"; |
- |
-} // namespace |
- |
-const char ExtensionPortsRemoteService::kToolName[] = "ExtensionPorts"; |
- |
-ExtensionPortsRemoteService::ExtensionPortsRemoteService( |
- DevToolsProtocolHandler* delegate) |
- : delegate_(delegate), service_(NULL) { |
- // We need an ExtensionMessageService instance. It hangs off of |
- // |profile|. But we do not have a particular tab or RenderViewHost |
- // as context. I'll just use the first active profile not in |
- // incognito mode. But this is probably not the right way. |
- ProfileManager* profile_manager = g_browser_process->profile_manager(); |
- if (!profile_manager) { |
- LOG(WARNING) << "No profile manager for ExtensionPortsRemoteService"; |
- return; |
- } |
- |
- std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles()); |
- for (size_t i = 0; i < profiles.size(); ++i) { |
- if (!profiles[i]->IsOffTheRecord()) { |
- service_ = profiles[i]->GetExtensionMessageService(); |
- break; |
- } |
- } |
- if (!service_) |
- LOG(WARNING) << "No usable profile for ExtensionPortsRemoteService"; |
-} |
- |
-ExtensionPortsRemoteService::~ExtensionPortsRemoteService() { |
-} |
- |
-void ExtensionPortsRemoteService::HandleMessage( |
- const DevToolsRemoteMessage& message) { |
- DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); |
- const std::string destinationString = message.destination(); |
- scoped_ptr<Value> request(base::JSONReader::Read(message.content(), true)); |
- if (request.get() == NULL) { |
- // Bad JSON |
- NOTREACHED(); |
- return; |
- } |
- DictionaryValue* content; |
- if (!request->IsType(Value::TYPE_DICTIONARY)) { |
- NOTREACHED(); // Broken protocol :( |
- return; |
- } |
- content = static_cast<DictionaryValue*>(request.get()); |
- if (!content->HasKey(kCommandKey)) { |
- NOTREACHED(); // Broken protocol :( |
- return; |
- } |
- std::string command; |
- DictionaryValue response; |
- |
- content->GetString(kCommandKey, &command); |
- response.SetString(kCommandKey, command); |
- |
- if (!service_) { |
- // This happens if we failed to obtain an ExtensionMessageService |
- // during initialization. |
- NOTREACHED(); |
- response.SetInteger(kResultKey, RESULT_NO_SERVICE); |
- SendResponse(response, message.tool(), message.destination()); |
- return; |
- } |
- |
- int destination = -1; |
- if (!destinationString.empty()) |
- base::StringToInt(destinationString, &destination); |
- |
- if (command == kConnect) { |
- if (destination != -1) // destination should be empty for this command. |
- response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
- else |
- ConnectCommand(content, &response); |
- } else if (command == kDisconnect) { |
- if (destination == -1) // Destination required for this command. |
- response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
- else |
- DisconnectCommand(destination, &response); |
- } else if (command == kPostMessage) { |
- if (destination == -1) // Destination required for this command. |
- response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
- else |
- PostMessageCommand(destination, content, &response); |
- } else { |
- // Unknown command |
- NOTREACHED(); |
- response.SetInteger(kResultKey, RESULT_UNKNOWN_COMMAND); |
- } |
- SendResponse(response, message.tool(), message.destination()); |
-} |
- |
-void ExtensionPortsRemoteService::OnConnectionLost() { |
- VLOG(1) << "OnConnectionLost"; |
- DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); |
- DCHECK(service_); |
- for (PortIdSet::iterator it = openPortIds_.begin(); |
- it != openPortIds_.end(); |
- ++it) |
- service_->CloseChannel(*it); |
- openPortIds_.clear(); |
-} |
- |
-void ExtensionPortsRemoteService::SendResponse( |
- const Value& response, const std::string& tool, |
- const std::string& destination) { |
- std::string response_content; |
- base::JSONWriter::Write(&response, false, &response_content); |
- scoped_ptr<DevToolsRemoteMessage> response_message( |
- DevToolsRemoteMessageBuilder::instance().Create( |
- tool, destination, response_content)); |
- delegate_->Send(*response_message.get()); |
-} |
- |
-bool ExtensionPortsRemoteService::Send(IPC::Message *message) { |
- DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); |
- |
- IPC_BEGIN_MESSAGE_MAP(ExtensionPortsRemoteService, *message) |
- IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke) |
- IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage) |
- IPC_MESSAGE_UNHANDLED_ERROR() |
- IPC_END_MESSAGE_MAP() |
- |
- delete message; |
- return true; |
-} |
- |
-void ExtensionPortsRemoteService::OnExtensionMessageInvoke( |
- const std::string& extension_id, |
- const std::string& function_name, |
- const ListValue& args, |
- const GURL& event_url) { |
- if (function_name == ExtensionMessageService::kDispatchOnDisconnect) { |
- DCHECK_EQ(args.GetSize(), 1u); |
- int port_id; |
- if (args.GetInteger(0, &port_id)) |
- OnExtensionPortDisconnected(port_id); |
- } else if (function_name == ExtensionMessageService::kDispatchOnConnect) { |
- // There is no way for this service to be addressed and receive |
- // connections. |
- NOTREACHED() << function_name << " shouldn't be called."; |
- } else { |
- NOTREACHED() << function_name << " shouldn't be called."; |
- } |
-} |
- |
-void ExtensionPortsRemoteService::OnDeliverMessage( |
- int port_id, const std::string& message) { |
- VLOG(1) << "Message event: from port " << port_id << ", < " << message << ">"; |
- // Transpose the information into a JSON message for the external client. |
- DictionaryValue content; |
- content.SetString(kCommandKey, kOnMessage); |
- content.SetInteger(kResultKey, RESULT_OK); |
- // Turn the stringified message body back into JSON. |
- Value* data = base::JSONReader::Read(message, false); |
- if (!data) { |
- NOTREACHED(); |
- return; |
- } |
- content.Set(kDataKey, data); |
- SendResponse(content, kToolName, base::IntToString(port_id)); |
-} |
- |
-void ExtensionPortsRemoteService::OnExtensionPortDisconnected(int port_id) { |
- VLOG(1) << "Disconnect event for port " << port_id; |
- openPortIds_.erase(port_id); |
- DictionaryValue content; |
- content.SetString(kCommandKey, kOnDisconnect); |
- content.SetInteger(kResultKey, RESULT_OK); |
- SendResponse(content, kToolName, base::IntToString(port_id)); |
-} |
- |
-void ExtensionPortsRemoteService::ConnectCommand( |
- DictionaryValue* content, DictionaryValue* response) { |
- // Parse out the parameters. |
- DictionaryValue* data; |
- if (!content->GetDictionary(kDataKey, &data)) { |
- response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
- return; |
- } |
- std::string extension_id; |
- if (!data->GetString(kExtensionIdKey, &extension_id)) { |
- response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
- return; |
- } |
- std::string channel_name = ""; |
- data->GetString(kChannelNameKey, &channel_name); // optional. |
- int tab_id = -1; |
- data->GetInteger(kTabIdKey, &tab_id); // optional. |
- int port_id; |
- if (tab_id != -1) { // Resolve the tab ID. |
- const InspectableTabProxy::TabMap& tab_map = |
- delegate_->inspectable_tab_proxy()->tab_map(); |
- InspectableTabProxy::TabMap::const_iterator it = tab_map.find(tab_id); |
- TabContents* tab_contents = NULL; |
- if (it != tab_map.end()) |
- tab_contents = it->second->tab_contents(); |
- if (!tab_contents) { |
- VLOG(1) << "tab not found: " << tab_id; |
- response->SetInteger(kResultKey, RESULT_TAB_NOT_FOUND); |
- return; |
- } |
- // Ask the ExtensionMessageService to open the channel. |
- VLOG(1) << "Connect: extension_id <" << extension_id |
- << ">, channel_name <" << channel_name |
- << ">, tab " << tab_id; |
- DCHECK(service_); |
- port_id = service_->OpenSpecialChannelToTab( |
- extension_id, channel_name, tab_contents, this); |
- } else { // no tab: channel to an extension page. |
- // Ask the ExtensionMessageService to open the channel. |
- VLOG(1) << "Connect: extension_id <" << extension_id |
- << ">, channel_name <" << channel_name << ">"; |
- DCHECK(service_); |
- port_id = service_->OpenSpecialChannelToExtension( |
- extension_id, channel_name, "null", this); |
- } |
- if (port_id == -1) { |
- // Failure: probably the extension ID doesn't exist. |
- VLOG(1) << "Connect failed"; |
- response->SetInteger(kResultKey, RESULT_CONNECT_FAILED); |
- return; |
- } |
- VLOG(1) << "Connected: port " << port_id; |
- openPortIds_.insert(port_id); |
- // Reply to external client with the port ID assigned to the new channel. |
- DictionaryValue* reply_data = new DictionaryValue(); |
- reply_data->SetInteger(kPortIdKey, port_id); |
- response->Set(kDataKey, reply_data); |
- response->SetInteger(kResultKey, RESULT_OK); |
-} |
- |
-void ExtensionPortsRemoteService::DisconnectCommand( |
- int port_id, DictionaryValue* response) { |
- VLOG(1) << "Disconnect port " << port_id; |
- PortIdSet::iterator portEntry = openPortIds_.find(port_id); |
- if (portEntry == openPortIds_.end()) { // unknown port ID. |
- VLOG(1) << "unknown port: " << port_id; |
- response->SetInteger(kResultKey, RESULT_UNKNOWN_PORT); |
- return; |
- } |
- DCHECK(service_); |
- service_->CloseChannel(port_id); |
- openPortIds_.erase(portEntry); |
- response->SetInteger(kResultKey, RESULT_OK); |
-} |
- |
-void ExtensionPortsRemoteService::PostMessageCommand( |
- int port_id, DictionaryValue* content, DictionaryValue* response) { |
- Value* data; |
- if (!content->Get(kDataKey, &data)) { |
- response->SetInteger(kResultKey, RESULT_PARAMETER_ERROR); |
- return; |
- } |
- std::string message; |
- // Stringified the JSON message body. |
- base::JSONWriter::Write(data, false, &message); |
- VLOG(1) << "postMessage: port " << port_id |
- << ", message: <" << message << ">"; |
- PortIdSet::iterator portEntry = openPortIds_.find(port_id); |
- if (portEntry == openPortIds_.end()) { // Unknown port ID. |
- VLOG(1) << "unknown port: " << port_id; |
- response->SetInteger(kResultKey, RESULT_UNKNOWN_PORT); |
- return; |
- } |
- // Post the message through the ExtensionMessageService. |
- DCHECK(service_); |
- service_->PostMessageFromRenderer(port_id, message); |
- // Confirm to the external client that we sent its message. |
- response->SetInteger(kResultKey, RESULT_OK); |
-} |