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/extension_process/xwalk_extension_process.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/message_loop/message_loop.h"
12 #include "ipc/ipc_switches.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "ipc/ipc_sync_channel.h"
15 #include "xwalk/extensions/common/xwalk_extension_messages.h"
18 namespace extensions {
20 XWalkExtensionProcess::XWalkExtensionProcess(
21 const IPC::ChannelHandle& channel_handle)
22 : shutdown_event_(false, false),
23 io_thread_("XWalkExtensionProcess_IOThread") {
24 io_thread_.StartWithOptions(
25 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
27 extensions_server_.set_permissions_delegate(this);
28 CreateBrowserProcessChannel(channel_handle);
31 XWalkExtensionProcess::~XWalkExtensionProcess() {
32 // FIXME(jeez): Move this to OnChannelClosing/Error/Disconnected when we have
33 // our MessageFilter set.
34 extensions_server_.Invalidate();
36 shutdown_event_.Signal();
40 bool XWalkExtensionProcess::OnMessageReceived(const IPC::Message& message) {
42 IPC_BEGIN_MESSAGE_MAP(XWalkExtensionProcess, message)
43 IPC_MESSAGE_HANDLER(XWalkExtensionProcessMsg_RegisterExtensions,
45 IPC_MESSAGE_UNHANDLED(handled = false)
52 void ToValueMap(base::ListValue* lv, base::ValueMap* vm) {
55 for (base::ListValue::iterator it = lv->begin(); it != lv->end(); it++) {
56 base::DictionaryValue* dv;
57 if (!(*it)->GetAsDictionary(&dv))
59 for (base::DictionaryValue::Iterator dit(*dv);
60 !dit.IsAtEnd(); dit.Advance())
61 (*vm)[dit.key()] = dit.value().DeepCopy();
67 void XWalkExtensionProcess::OnRegisterExtensions(
68 const base::FilePath& path, const base::ListValue& browser_variables_lv) {
70 base::ValueMap browser_variables;
72 ToValueMap(&const_cast<base::ListValue&>(browser_variables_lv),
75 RegisterExternalExtensionsInDirectory(&extensions_server_, path,
78 CreateRenderProcessChannel();
81 void XWalkExtensionProcess::CreateBrowserProcessChannel(
82 const IPC::ChannelHandle& channel_handle) {
83 IPC::SyncChannel* channel;
84 if (channel_handle.name.empty()) {
85 std::string channel_id =
86 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
87 switches::kProcessChannelID);
88 channel = new IPC::SyncChannel(
89 channel_id, IPC::Channel::MODE_CLIENT, this,
90 io_thread_.message_loop_proxy(), true, &shutdown_event_);
92 channel = new IPC::SyncChannel(
93 channel_handle, IPC::Channel::MODE_CLIENT, this,
94 io_thread_.message_loop_proxy(), true, &shutdown_event_);
96 browser_process_channel_.reset(channel);
99 void XWalkExtensionProcess::CreateRenderProcessChannel() {
100 IPC::ChannelHandle handle(IPC::Channel::GenerateVerifiedChannelID(
102 rp_channel_handle_ = handle;
104 render_process_channel_.reset(new IPC::SyncChannel(rp_channel_handle_,
105 IPC::Channel::MODE_SERVER, &extensions_server_,
106 io_thread_.message_loop_proxy(), true, &shutdown_event_));
108 #if defined(OS_POSIX)
109 // On POSIX, pass the server-side file descriptor. We use
110 // TakeClientFileDescriptor() instead of GetClientFileDescriptor()
111 // since the client-side channel will take ownership of the fd.
112 rp_channel_handle_.socket =
113 base::FileDescriptor(render_process_channel_->TakeClientFileDescriptor(),
117 extensions_server_.Initialize(render_process_channel_.get());
119 browser_process_channel_->Send(
120 new XWalkExtensionProcessHostMsg_RenderProcessChannelCreated(
121 rp_channel_handle_));
124 bool XWalkExtensionProcess::CheckAPIAccessControl(
125 const std::string& extension_name,
126 const std::string& api_name) {
127 PermissionCacheType::iterator iter =
128 permission_cache_.find(extension_name + api_name);
129 if (iter != permission_cache_.end())
132 RuntimePermission result = UNDEFINED_RUNTIME_PERM;
133 browser_process_channel_->Send(
134 new XWalkExtensionProcessHostMsg_CheckAPIAccessControl(
135 extension_name, api_name, &result));
136 DLOG(INFO) << extension_name << "." << api_name << "() --> " << result;
137 if (result == ALLOW_SESSION ||
138 result == ALLOW_ALWAYS ||
139 result == DENY_SESSION ||
140 result == DENY_ALWAYS) {
141 permission_cache_[extension_name+api_name] = result;
142 return (result == ALLOW_SESSION || result == ALLOW_ALWAYS);
145 // Could be allow/deny once or undefined here.
146 return (result == ALLOW_ONCE);
149 bool XWalkExtensionProcess::RegisterPermissions(
150 const std::string& extension_name,
151 const std::string& perm_table) {
153 browser_process_channel_->Send(
154 new XWalkExtensionProcessHostMsg_RegisterPermissions(
155 extension_name, perm_table, &result));
159 } // namespace extensions