baa5efc2b0478e16fb473dd59618f29c20f850a4
[platform/framework/web/crosswalk.git] / src / xwalk / extensions / extension_process / xwalk_extension_process.cc
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.
4
5 #include "xwalk/extensions/extension_process/xwalk_extension_process.h"
6
7 #include <string>
8
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"
16
17 namespace xwalk {
18 namespace extensions {
19
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));
26
27   extensions_server_.set_permissions_delegate(this);
28   CreateBrowserProcessChannel(channel_handle);
29 }
30
31 XWalkExtensionProcess::~XWalkExtensionProcess() {
32   // FIXME(jeez): Move this to OnChannelClosing/Error/Disconnected when we have
33   // our MessageFilter set.
34   extensions_server_.Invalidate();
35
36   shutdown_event_.Signal();
37   io_thread_.Stop();
38 }
39
40 bool XWalkExtensionProcess::OnMessageReceived(const IPC::Message& message) {
41   bool handled = true;
42   IPC_BEGIN_MESSAGE_MAP(XWalkExtensionProcess, message)
43     IPC_MESSAGE_HANDLER(XWalkExtensionProcessMsg_RegisterExtensions,
44                         OnRegisterExtensions)
45     IPC_MESSAGE_UNHANDLED(handled = false)
46   IPC_END_MESSAGE_MAP()
47   return handled;
48 }
49
50 namespace {
51
52 void ToValueMap(base::ListValue* lv, base::ValueMap* vm) {
53   vm->clear();
54
55   for (base::ListValue::iterator it = lv->begin(); it != lv->end(); it++) {
56     base::DictionaryValue* dv;
57     if (!(*it)->GetAsDictionary(&dv))
58       continue;
59     for (base::DictionaryValue::Iterator dit(*dv);
60         !dit.IsAtEnd(); dit.Advance())
61       (*vm)[dit.key()] = dit.value().DeepCopy();
62   }
63 }
64
65 }  // namespace
66
67 void XWalkExtensionProcess::OnRegisterExtensions(
68     const base::FilePath& path, const base::ListValue& browser_variables_lv) {
69   if (!path.empty()) {
70     base::ValueMap browser_variables;
71
72     ToValueMap(&const_cast<base::ListValue&>(browser_variables_lv),
73           &browser_variables);
74
75     RegisterExternalExtensionsInDirectory(&extensions_server_, path,
76                                           browser_variables);
77   }
78   CreateRenderProcessChannel();
79 }
80
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_);
91   } else {
92     channel = new IPC::SyncChannel(
93         channel_handle, IPC::Channel::MODE_CLIENT, this,
94         io_thread_.message_loop_proxy(), true, &shutdown_event_);
95   }
96   browser_process_channel_.reset(channel);
97 }
98
99 void XWalkExtensionProcess::CreateRenderProcessChannel() {
100   IPC::ChannelHandle handle(IPC::Channel::GenerateVerifiedChannelID(
101       std::string()));
102   rp_channel_handle_ = handle;
103
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_));
107
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(),
114           true);
115 #endif
116
117   extensions_server_.Initialize(render_process_channel_.get());
118
119   browser_process_channel_->Send(
120       new XWalkExtensionProcessHostMsg_RenderProcessChannelCreated(
121           rp_channel_handle_));
122 }
123
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())
130     return iter->second;
131
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);
143   }
144
145   // Could be allow/deny once or undefined here.
146   return (result == ALLOW_ONCE);
147 }
148
149 bool XWalkExtensionProcess::RegisterPermissions(
150     const std::string& extension_name,
151     const std::string& perm_table) {
152   bool result;
153   browser_process_channel_->Send(
154       new XWalkExtensionProcessHostMsg_RegisterPermissions(
155           extension_name, perm_table, &result));
156   return result;
157 }
158
159 }  // namespace extensions
160 }  // namespace xwalk