Home | History | Annotate | Download | only in pepper
      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