1 // Copyright (c) 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_crx_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/extensions/extension_system.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile_manager.h" 12 #include "chrome/common/chrome_switches.h" 13 #include "chrome/common/extensions/extension.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 #include "extensions/common/constants.h" 20 #include "ppapi/c/pp_errors.h" 21 #include "ppapi/host/dispatch_host_message.h" 22 #include "ppapi/host/host_message_context.h" 23 #include "ppapi/host/ppapi_host.h" 24 #include "ppapi/proxy/ppapi_messages.h" 25 #include "webkit/browser/fileapi/isolated_context.h" 26 27 namespace chrome { 28 29 namespace { 30 31 const char* kPredefinedAllowedCrxFsOrigins[] = { 32 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/234789 33 "4EB74897CB187C7633357C2FE832E0AD6A44883A" // see crbug.com/234789 34 }; 35 36 } // namespace 37 38 // static 39 PepperCrxFileSystemMessageFilter* PepperCrxFileSystemMessageFilter::Create( 40 PP_Instance instance, content::BrowserPpapiHost* host) { 41 int render_process_id; 42 int unused_render_view_id; 43 if (!host->GetRenderViewIDsForInstance(instance, 44 &render_process_id, 45 &unused_render_view_id)) { 46 return NULL; 47 } 48 return new PepperCrxFileSystemMessageFilter( 49 render_process_id, 50 host->GetProfileDataDirectory(), 51 host->GetDocumentURLForInstance(instance)); 52 } 53 54 PepperCrxFileSystemMessageFilter::PepperCrxFileSystemMessageFilter( 55 int render_process_id, 56 const base::FilePath& profile_directory, 57 const GURL& document_url) 58 : render_process_id_(render_process_id), 59 profile_directory_(profile_directory), 60 document_url_(document_url) { 61 for (size_t i = 0; i < arraysize(kPredefinedAllowedCrxFsOrigins); ++i) 62 allowed_crxfs_origins_.insert(kPredefinedAllowedCrxFsOrigins[i]); 63 } 64 65 PepperCrxFileSystemMessageFilter::~PepperCrxFileSystemMessageFilter() { 66 } 67 68 scoped_refptr<base::TaskRunner> 69 PepperCrxFileSystemMessageFilter::OverrideTaskRunnerForMessage( 70 const IPC::Message& msg) { 71 // In order to reach ExtensionSystem, we need to get ProfileManager first. 72 // ProfileManager lives in UI thread, so we need to do this in UI thread. 73 return content::BrowserThread::GetMessageLoopProxyForThread( 74 content::BrowserThread::UI); 75 } 76 77 int32_t PepperCrxFileSystemMessageFilter::OnResourceMessageReceived( 78 const IPC::Message& msg, 79 ppapi::host::HostMessageContext* context) { 80 IPC_BEGIN_MESSAGE_MAP(PepperCrxFileSystemMessageFilter, msg) 81 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 82 PpapiHostMsg_Ext_CrxFileSystem_BrowserOpen, OnOpenFileSystem); 83 IPC_END_MESSAGE_MAP() 84 return PP_ERROR_FAILED; 85 } 86 87 Profile* PepperCrxFileSystemMessageFilter::GetProfile() { 88 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 89 ProfileManager* profile_manager = g_browser_process->profile_manager(); 90 return profile_manager->GetProfile(profile_directory_); 91 } 92 93 std::string PepperCrxFileSystemMessageFilter::CreateIsolatedFileSystem( 94 Profile* profile) { 95 extensions::ExtensionSystem* extension_system = 96 extensions::ExtensionSystem::Get(profile); 97 if (!extension_system) 98 return std::string(); 99 100 const ExtensionService* extension_service = 101 extension_system->extension_service(); 102 if (!extension_service) 103 return std::string(); 104 105 const extensions::Extension* extension = 106 extension_service->GetExtensionById(document_url_.host(), false); 107 if (!extension) 108 return std::string(); 109 110 // First level directory for isolated filesystem to lookup. 111 std::string kFirstLevelDirectory("crxfs"); 112 return fileapi::IsolatedContext::GetInstance()-> 113 RegisterFileSystemForPath(fileapi::kFileSystemTypeNativeLocal, 114 extension->path(), 115 &kFirstLevelDirectory); 116 } 117 118 int32_t PepperCrxFileSystemMessageFilter::OnOpenFileSystem( 119 ppapi::host::HostMessageContext* context) { 120 Profile* profile = GetProfile(); 121 const ExtensionSet* extension_set = NULL; 122 if (profile) { 123 extension_set = extensions::ExtensionSystem::Get(profile)-> 124 extension_service()->extensions(); 125 } 126 if (!IsExtensionOrSharedModuleWhitelisted( 127 document_url_, extension_set, allowed_crxfs_origins_) && 128 !IsHostAllowedByCommandLine( 129 document_url_, extension_set, switches::kAllowNaClCrxFsAPI)) { 130 LOG(ERROR) << "Host " << document_url_.host() << " cannot use CrxFs API."; 131 return PP_ERROR_NOACCESS; 132 } 133 134 // TODO(raymes): When we remove FileSystem from the renderer, we should create 135 // a pending PepperFileSystemBrowserHost here with the fsid and send the 136 // pending host ID back to the plugin. 137 const std::string fsid = CreateIsolatedFileSystem(profile); 138 if (fsid.empty()) { 139 context->reply_msg = 140 PpapiPluginMsg_Ext_CrxFileSystem_BrowserOpenReply(std::string()); 141 return PP_ERROR_NOTSUPPORTED; 142 } 143 144 // Grant readonly access of isolated filesystem to renderer process. 145 content::ChildProcessSecurityPolicy* policy = 146 content::ChildProcessSecurityPolicy::GetInstance(); 147 policy->GrantReadFileSystem(render_process_id_, fsid); 148 149 context->reply_msg = PpapiPluginMsg_Ext_CrxFileSystem_BrowserOpenReply(fsid); 150 return PP_OK; 151 } 152 153 } // namespace chrome 154