Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / renderer_host / pepper / pepper_isolated_file_system_message_filter.cc
1 // Copyright 2013 The Chromium Authors. 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 "chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h"
6
7 #include "chrome/browser/browser_process.h"
8 #if defined(ENABLE_EXTENSIONS)
9 #include "chrome/browser/extensions/extension_service.h"
10 #endif
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/pepper_permission_util.h"
15 #include "content/public/browser/browser_ppapi_host.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/child_process_security_policy.h"
18 #include "content/public/browser/render_view_host.h"
19 #if defined(ENABLE_EXTENSIONS)
20 #include "extensions/browser/extension_system.h"
21 #include "extensions/common/constants.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/extension_set.h"
24 #endif
25 #include "ppapi/c/pp_errors.h"
26 #include "ppapi/host/dispatch_host_message.h"
27 #include "ppapi/host/host_message_context.h"
28 #include "ppapi/host/ppapi_host.h"
29 #include "ppapi/proxy/ppapi_messages.h"
30 #include "ppapi/shared_impl/file_system_util.h"
31 #include "storage/browser/fileapi/isolated_context.h"
32
33 namespace chrome {
34
35 namespace {
36
37 const char* kPredefinedAllowedCrxFsOrigins[] = {
38     "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F",  // see crbug.com/234789
39     "4EB74897CB187C7633357C2FE832E0AD6A44883A"   // see crbug.com/234789
40 };
41
42 }  // namespace
43
44 // static
45 PepperIsolatedFileSystemMessageFilter*
46 PepperIsolatedFileSystemMessageFilter::Create(PP_Instance instance,
47                                               content::BrowserPpapiHost* host) {
48   int render_process_id;
49   int unused_render_frame_id;
50   if (!host->GetRenderFrameIDsForInstance(
51           instance, &render_process_id, &unused_render_frame_id)) {
52     return NULL;
53   }
54   return new PepperIsolatedFileSystemMessageFilter(
55       render_process_id,
56       host->GetProfileDataDirectory(),
57       host->GetDocumentURLForInstance(instance),
58       host->GetPpapiHost());
59 }
60
61 PepperIsolatedFileSystemMessageFilter::PepperIsolatedFileSystemMessageFilter(
62     int render_process_id,
63     const base::FilePath& profile_directory,
64     const GURL& document_url,
65     ppapi::host::PpapiHost* ppapi_host)
66     : render_process_id_(render_process_id),
67       profile_directory_(profile_directory),
68       document_url_(document_url),
69       ppapi_host_(ppapi_host) {
70   for (size_t i = 0; i < arraysize(kPredefinedAllowedCrxFsOrigins); ++i)
71     allowed_crxfs_origins_.insert(kPredefinedAllowedCrxFsOrigins[i]);
72 }
73
74 PepperIsolatedFileSystemMessageFilter::
75     ~PepperIsolatedFileSystemMessageFilter() {}
76
77 scoped_refptr<base::TaskRunner>
78 PepperIsolatedFileSystemMessageFilter::OverrideTaskRunnerForMessage(
79     const IPC::Message& msg) {
80   // In order to reach ExtensionSystem, we need to get ProfileManager first.
81   // ProfileManager lives in UI thread, so we need to do this in UI thread.
82   return content::BrowserThread::GetMessageLoopProxyForThread(
83       content::BrowserThread::UI);
84 }
85
86 int32_t PepperIsolatedFileSystemMessageFilter::OnResourceMessageReceived(
87     const IPC::Message& msg,
88     ppapi::host::HostMessageContext* context) {
89   PPAPI_BEGIN_MESSAGE_MAP(PepperIsolatedFileSystemMessageFilter, msg)
90     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
91       PpapiHostMsg_IsolatedFileSystem_BrowserOpen,
92       OnOpenFileSystem)
93   PPAPI_END_MESSAGE_MAP()
94   return PP_ERROR_FAILED;
95 }
96
97 Profile* PepperIsolatedFileSystemMessageFilter::GetProfile() {
98   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
99   ProfileManager* profile_manager = g_browser_process->profile_manager();
100   return profile_manager->GetProfile(profile_directory_);
101 }
102
103 std::string PepperIsolatedFileSystemMessageFilter::CreateCrxFileSystem(
104     Profile* profile) {
105 #if defined(ENABLE_EXTENSIONS)
106   extensions::ExtensionSystem* extension_system =
107       extensions::ExtensionSystem::Get(profile);
108   if (!extension_system)
109     return std::string();
110
111   const ExtensionService* extension_service =
112       extension_system->extension_service();
113   if (!extension_service)
114     return std::string();
115
116   const extensions::Extension* extension =
117       extension_service->GetExtensionById(document_url_.host(), false);
118   if (!extension)
119     return std::string();
120
121   // First level directory for isolated filesystem to lookup.
122   std::string kFirstLevelDirectory("crxfs");
123   return storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath(
124       storage::kFileSystemTypeNativeLocal,
125       std::string(),
126       extension->path(),
127       &kFirstLevelDirectory);
128 #else
129   return std::string();
130 #endif
131 }
132
133 int32_t PepperIsolatedFileSystemMessageFilter::OnOpenFileSystem(
134     ppapi::host::HostMessageContext* context,
135     PP_IsolatedFileSystemType_Private type) {
136   switch (type) {
137     case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_INVALID:
138       break;
139     case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_CRX:
140       return OpenCrxFileSystem(context);
141     case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE:
142       return OpenPluginPrivateFileSystem(context);
143   }
144   NOTREACHED();
145   context->reply_msg =
146       PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(std::string());
147   return PP_ERROR_FAILED;
148 }
149
150 int32_t PepperIsolatedFileSystemMessageFilter::OpenCrxFileSystem(
151     ppapi::host::HostMessageContext* context) {
152 #if defined(ENABLE_EXTENSIONS)
153   Profile* profile = GetProfile();
154   const extensions::ExtensionSet* extension_set = NULL;
155   if (profile) {
156     extension_set = extensions::ExtensionSystem::Get(profile)
157                         ->extension_service()
158                         ->extensions();
159   }
160   if (!IsExtensionOrSharedModuleWhitelisted(
161           document_url_, extension_set, allowed_crxfs_origins_) &&
162       !IsHostAllowedByCommandLine(
163           document_url_, extension_set, switches::kAllowNaClCrxFsAPI)) {
164     LOG(ERROR) << "Host " << document_url_.host() << " cannot use CrxFs API.";
165     return PP_ERROR_NOACCESS;
166   }
167
168   // TODO(raymes): When we remove FileSystem from the renderer, we should create
169   // a pending PepperFileSystemBrowserHost here with the fsid and send the
170   // pending host ID back to the plugin.
171   const std::string fsid = CreateCrxFileSystem(profile);
172   if (fsid.empty()) {
173     context->reply_msg =
174         PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(std::string());
175     return PP_ERROR_NOTSUPPORTED;
176   }
177
178   // Grant readonly access of isolated filesystem to renderer process.
179   content::ChildProcessSecurityPolicy* policy =
180       content::ChildProcessSecurityPolicy::GetInstance();
181   policy->GrantReadFileSystem(render_process_id_, fsid);
182
183   context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(fsid);
184   return PP_OK;
185 #else
186   return PP_ERROR_NOTSUPPORTED;
187 #endif
188 }
189
190 int32_t PepperIsolatedFileSystemMessageFilter::OpenPluginPrivateFileSystem(
191     ppapi::host::HostMessageContext* context) {
192   DCHECK(ppapi_host_);
193   // Only plugins with private permission can open the filesystem.
194   if (!ppapi_host_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
195     return PP_ERROR_NOACCESS;
196
197   const std::string& root_name = ppapi::IsolatedFileSystemTypeToRootName(
198       PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE);
199   const std::string& fsid =
200       storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
201           storage::kFileSystemTypePluginPrivate, root_name, base::FilePath());
202
203   // Grant full access of isolated filesystem to renderer process.
204   content::ChildProcessSecurityPolicy* policy =
205       content::ChildProcessSecurityPolicy::GetInstance();
206   policy->GrantCreateReadWriteFileSystem(render_process_id_, fsid);
207
208   context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(fsid);
209   return PP_OK;
210 }
211
212 }  // namespace chrome