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