1 // Copyright (c) 2013 Intel Corporation. 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.
5 #include "xwalk/extensions/renderer/xwalk_extension_client.h"
7 #include "base/values.h"
8 #include "base/stl_util.h"
9 #include "ipc/ipc_sender.h"
10 #include "xwalk/extensions/common/xwalk_extension_messages.h"
13 namespace extensions {
15 XWalkExtensionClient::XWalkExtensionClient()
17 next_instance_id_(1) { // Zero is never used for a valid instance.
20 XWalkExtensionClient::~XWalkExtensionClient() {
21 STLDeleteValues(&extension_apis_);
24 bool XWalkExtensionClient::Send(IPC::Message* msg) {
27 return sender_->Send(msg);
30 int64_t XWalkExtensionClient::CreateInstance(
31 const std::string& extension_name,
32 InstanceHandler* handler) {
34 if (!Send(new XWalkExtensionServerMsg_CreateInstance(next_instance_id_,
38 handlers_[next_instance_id_] = handler;
39 return next_instance_id_++;
42 bool XWalkExtensionClient::OnMessageReceived(const IPC::Message& message) {
44 IPC_BEGIN_MESSAGE_MAP(XWalkExtensionClient, message)
45 IPC_MESSAGE_HANDLER(XWalkExtensionClientMsg_PostMessageToJS,
47 IPC_MESSAGE_HANDLER(XWalkExtensionClientMsg_PostOutOfLineMessageToJS,
48 OnPostOutOfLineMessageToJS)
49 IPC_MESSAGE_HANDLER(XWalkExtensionClientMsg_InstanceDestroyed,
51 IPC_MESSAGE_UNHANDLED(handled = false)
57 XWalkExtensionClient::ExtensionCodePoints::ExtensionCodePoints() {
60 XWalkExtensionClient::ExtensionCodePoints::~ExtensionCodePoints() {
63 void XWalkExtensionClient::OnPostMessageToJS(int64_t instance_id,
64 const base::ListValue& msg) {
65 HandlerMap::const_iterator it = handlers_.find(instance_id);
66 if (it == handlers_.end()) {
67 LOG(WARNING) << "Can't PostMessage to invalid Extension instance id: "
72 // See comment in DestroyInstance() about two step destruction.
76 const base::Value* value;
78 it->second->HandleMessageFromNative(*value);
81 void XWalkExtensionClient::OnPostOutOfLineMessageToJS(
82 base::SharedMemoryHandle handle, size_t size) {
83 CHECK(base::SharedMemory::IsHandleValid(handle));
85 base::SharedMemory shared_memory(handle, true);
86 shared_memory.Map(size);
88 IPC::Message message(static_cast<char*>(shared_memory.memory()), size);
89 OnMessageReceived(message);
92 void XWalkExtensionClient::DestroyInstance(int64_t instance_id) {
93 HandlerMap::iterator it = handlers_.find(instance_id);
94 if (it == handlers_.end() || !it->second) {
95 LOG(WARNING) << "Can't Destroy invalid instance id: " << instance_id;
98 Send(new XWalkExtensionServerMsg_DestroyInstance(instance_id));
100 // Destruction happens in two steps, first we nullify the handler in our map,
101 // to indicate that destruction message was sent. If we get a new message from
102 // this instance, we can silently ignore. Later, we get a confirmation message
103 // from the server, only then we remove the entry from the map.
107 void XWalkExtensionClient::OnInstanceDestroyed(int64_t instance_id) {
108 HandlerMap::iterator it = handlers_.find(instance_id);
109 if (it == handlers_.end()) {
110 LOG(WARNING) << "Got InstanceDestroyed msg for invalid instance id: "
115 // Second part of the two step destruction. See DestroyInstance() for details.
116 // The system currently assumes that we always control the destruction of
124 // Regular base::Value doesn't have param traits, so can't be passed as is
125 // through IPC. We wrap it in a base::ListValue that have traits before
128 // Implementing param traits for base::Value is not a viable option at the
129 // moment (would require fork base::Value and create a new empty type).
130 scoped_ptr<base::ListValue> WrapValueInList(scoped_ptr<base::Value> value) {
132 return scoped_ptr<base::ListValue>();
133 scoped_ptr<base::ListValue> list_value(new base::ListValue);
134 list_value->Append(value.release());
135 return list_value.Pass();
140 void XWalkExtensionClient::PostMessageToNative(int64_t instance_id,
141 scoped_ptr<base::Value> msg) {
142 scoped_ptr<base::ListValue> list_msg = WrapValueInList(msg.Pass());
143 Send(new XWalkExtensionServerMsg_PostMessageToNative(instance_id, *list_msg));
146 scoped_ptr<base::Value> XWalkExtensionClient::SendSyncMessageToNative(
147 int64_t instance_id, scoped_ptr<base::Value> msg) {
148 scoped_ptr<base::ListValue> wrapped_msg = WrapValueInList(msg.Pass());
149 base::ListValue* wrapped_reply = new base::ListValue;
150 Send(new XWalkExtensionServerMsg_SendSyncMessageToNative(instance_id,
151 *wrapped_msg, wrapped_reply));
153 scoped_ptr<base::Value> reply;
154 wrapped_reply->Remove(0, &reply);
158 void XWalkExtensionClient::Initialize(IPC::Sender* sender) {
161 std::vector<XWalkExtensionServerMsg_ExtensionRegisterParams> extensions;
162 Send(new XWalkExtensionServerMsg_GetExtensions(&extensions));
164 if (extensions.empty())
167 std::vector<XWalkExtensionServerMsg_ExtensionRegisterParams>::iterator it =
169 for (; it != extensions.end(); ++it) {
170 ExtensionCodePoints* codepoint = new ExtensionCodePoints;
171 codepoint->api = (*it).js_api;
173 codepoint->entry_points = (*it).entry_points;
175 std::string name = (*it).name;
176 extension_apis_[name] = codepoint;
180 } // namespace extensions