Upstream version 5.34.97.0
[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     : shutdown_event_(false, false),
22       io_thread_("XWalkExtensionProcess_IOThread") {
23   io_thread_.StartWithOptions(
24       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
25
26   extensions_server_.set_permissions_delegate(this);
27   CreateBrowserProcessChannel();
28 }
29
30 XWalkExtensionProcess::~XWalkExtensionProcess() {
31   // FIXME(jeez): Move this to OnChannelClosing/Error/Disconnected when we have
32   // our MessageFilter set.
33   extensions_server_.Invalidate();
34
35   shutdown_event_.Signal();
36   io_thread_.Stop();
37 }
38
39 bool XWalkExtensionProcess::OnMessageReceived(const IPC::Message& message) {
40   bool handled = true;
41   IPC_BEGIN_MESSAGE_MAP(XWalkExtensionProcess, message)
42     IPC_MESSAGE_HANDLER(XWalkExtensionProcessMsg_RegisterExtensions,
43                         OnRegisterExtensions)
44     IPC_MESSAGE_UNHANDLED(handled = false)
45   IPC_END_MESSAGE_MAP()
46   return handled;
47 }
48
49 namespace {
50
51 void ToValueMap(base::ListValue* lv, base::ValueMap* vm) {
52   vm->clear();
53
54   for (base::ListValue::iterator it = lv->begin(); it != lv->end(); it++) {
55     base::DictionaryValue* dv;
56     if (!(*it)->GetAsDictionary(&dv))
57       continue;
58     for (base::DictionaryValue::Iterator dit(*dv);
59         !dit.IsAtEnd(); dit.Advance())
60       (*vm)[dit.key()] = dit.value().DeepCopy();
61   }
62 }
63
64 }  // namespace
65
66 void XWalkExtensionProcess::OnRegisterExtensions(
67     const base::FilePath& path, const base::ListValue& browser_variables_lv) {
68   if (!path.empty()) {
69     base::ValueMap browser_variables;
70
71     ToValueMap(&const_cast<base::ListValue&>(browser_variables_lv),
72           &browser_variables);
73
74     RegisterExternalExtensionsInDirectory(&extensions_server_, path,
75                                           browser_variables);
76   }
77   CreateRenderProcessChannel();
78 }
79
80 void XWalkExtensionProcess::CreateBrowserProcessChannel() {
81   std::string channel_id =
82       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
83           switches::kProcessChannelID);
84   browser_process_channel_.reset(new IPC::SyncChannel(channel_id,
85       IPC::Channel::MODE_CLIENT, this, io_thread_.message_loop_proxy(),
86       true, &shutdown_event_));
87 }
88
89 void XWalkExtensionProcess::CreateRenderProcessChannel() {
90   IPC::ChannelHandle handle(IPC::Channel::GenerateVerifiedChannelID(
91       std::string()));
92   rp_channel_handle_ = handle;
93
94   render_process_channel_.reset(new IPC::SyncChannel(rp_channel_handle_,
95       IPC::Channel::MODE_SERVER, &extensions_server_,
96       io_thread_.message_loop_proxy(), true, &shutdown_event_));
97
98 #if defined(OS_POSIX)
99     // On POSIX, pass the server-side file descriptor. We use
100     // TakeClientFileDescriptor() instead of GetClientFileDescriptor()
101     // since the client-side channel will take ownership of the fd.
102     rp_channel_handle_.socket =
103        base::FileDescriptor(render_process_channel_->TakeClientFileDescriptor(),
104           true);
105 #endif
106
107   extensions_server_.Initialize(render_process_channel_.get());
108
109   browser_process_channel_->Send(
110       new XWalkExtensionProcessHostMsg_RenderProcessChannelCreated(
111           rp_channel_handle_));
112 }
113
114 bool XWalkExtensionProcess::CheckAPIAccessControl(
115     const std::string& extension_name,
116     const std::string& api_name) {
117   PermissionCacheType::iterator iter =
118       permission_cache_.find(extension_name + api_name);
119   if (iter != permission_cache_.end())
120     return iter->second;
121
122   RuntimePermission result = UNDEFINED_RUNTIME_PERM;
123   browser_process_channel_->Send(
124       new XWalkExtensionProcessHostMsg_CheckAPIAccessControl(
125           extension_name, api_name, &result));
126   DLOG(INFO) << extension_name << "." << api_name << "() --> " << result;
127   if (result == ALLOW_SESSION ||
128       result == ALLOW_ALWAYS ||
129       result == DENY_SESSION ||
130       result == DENY_ALWAYS) {
131     permission_cache_[extension_name+api_name] = result;
132     return (result == ALLOW_SESSION || result == ALLOW_ALWAYS);
133   }
134
135   // Could be allow/deny once or undefined here.
136   return (result == ALLOW_ONCE);
137 }
138
139 bool XWalkExtensionProcess::RegisterPermissions(
140     const std::string& extension_name,
141     const std::string& perm_table) {
142   bool result;
143   browser_process_channel_->Send(
144       new XWalkExtensionProcessHostMsg_RegisterPermissions(
145           extension_name, perm_table, &result));
146   return result;
147 }
148
149 }  // namespace extensions
150 }  // namespace xwalk