Home | History | Annotate | Download | only in browser
      1 // Copyright 2014 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 "extensions/shell/browser/shell_nacl_browser_delegate.h"
      6 
      7 #include <string>
      8 
      9 #include "base/base_paths.h"
     10 #include "base/command_line.h"
     11 #include "base/path_service.h"
     12 #include "base/strings/string_split.h"
     13 #include "base/strings/string_util.h"
     14 #include "content/public/browser/browser_context.h"
     15 #include "content/public/browser/browser_thread.h"
     16 #include "content/public/browser/render_frame_host.h"
     17 #include "content/public/browser/site_instance.h"
     18 #include "extensions/browser/extension_system.h"
     19 #include "extensions/browser/info_map.h"
     20 #include "extensions/browser/process_manager.h"
     21 #include "extensions/common/constants.h"
     22 #include "extensions/common/extension.h"
     23 #include "extensions/common/url_pattern.h"
     24 #include "extensions/shell/common/version.h"  // Generated file.
     25 #include "ppapi/c/private/ppb_nacl_private.h"
     26 #include "url/gurl.h"
     27 
     28 using content::BrowserContext;
     29 using content::BrowserThread;
     30 using content::BrowserPpapiHost;
     31 
     32 namespace extensions {
     33 namespace {
     34 
     35 // Handles an extension's NaCl process transitioning in or out of idle state by
     36 // relaying the state to the extension's process manager. See Chrome's
     37 // NaClBrowserDelegateImpl for another example.
     38 void OnKeepaliveOnUIThread(
     39     const BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
     40     const base::FilePath& profile_data_directory) {
     41   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     42 
     43   // Only one instance will exist for NaCl embeds, even when more than one
     44   // embed of the same plugin exists on the same page.
     45   DCHECK(instance_data.size() == 1);
     46   if (instance_data.size() < 1)
     47     return;
     48 
     49   ProcessManager::OnKeepaliveFromPlugin(instance_data[0].render_process_id,
     50                                         instance_data[0].render_frame_id,
     51                                         instance_data[0].document_url.host());
     52 }
     53 
     54 // Calls OnKeepaliveOnUIThread on UI thread.
     55 void OnKeepalive(const BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
     56                  const base::FilePath& profile_data_directory) {
     57   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
     58   BrowserThread::PostTask(
     59       BrowserThread::UI,
     60       FROM_HERE,
     61       base::Bind(
     62           &OnKeepaliveOnUIThread, instance_data, profile_data_directory));
     63 }
     64 
     65 }  // namespace
     66 
     67 ShellNaClBrowserDelegate::ShellNaClBrowserDelegate(BrowserContext* context)
     68     : browser_context_(context) {
     69   DCHECK(browser_context_);
     70 }
     71 
     72 ShellNaClBrowserDelegate::~ShellNaClBrowserDelegate() {
     73 }
     74 
     75 void ShellNaClBrowserDelegate::ShowMissingArchInfobar(int render_process_id,
     76                                                       int render_view_id) {
     77   // app_shell does not have infobars.
     78   LOG(ERROR) << "Missing architecture for pid " << render_process_id;
     79 }
     80 
     81 bool ShellNaClBrowserDelegate::DialogsAreSuppressed() {
     82   return false;
     83 }
     84 
     85 bool ShellNaClBrowserDelegate::GetCacheDirectory(base::FilePath* cache_dir) {
     86   // Just use the general cache directory, not a subdirectory like Chrome does.
     87 #if defined(OS_POSIX)
     88   return PathService::Get(base::DIR_CACHE, cache_dir);
     89 #elif defined(OS_WIN)
     90   // TODO(yoz): Find an appropriate persistent directory to use here.
     91   return PathService::Get(base::DIR_TEMP, cache_dir);
     92 #endif
     93 }
     94 
     95 bool ShellNaClBrowserDelegate::GetPluginDirectory(base::FilePath* plugin_dir) {
     96   // On Posix, plugins are in the module directory.
     97   return PathService::Get(base::DIR_MODULE, plugin_dir);
     98 }
     99 
    100 bool ShellNaClBrowserDelegate::GetPnaclDirectory(base::FilePath* pnacl_dir) {
    101   // On Posix, the pnacl directory is inside the plugin directory.
    102   base::FilePath plugin_dir;
    103   if (!GetPluginDirectory(&plugin_dir))
    104     return false;
    105   *pnacl_dir = plugin_dir.Append(FILE_PATH_LITERAL("pnacl"));
    106   return true;
    107 }
    108 
    109 bool ShellNaClBrowserDelegate::GetUserDirectory(base::FilePath* user_dir) {
    110   base::FilePath path = browser_context_->GetPath();
    111   if (!path.empty()) {
    112     *user_dir = path;
    113     return true;
    114   }
    115   return false;
    116 }
    117 
    118 std::string ShellNaClBrowserDelegate::GetVersionString() const {
    119   // A version change triggers an update of the NaCl validation caches.
    120   // Example version: "39.0.2129.0 (290550)".
    121   return PRODUCT_VERSION " (" LAST_CHANGE ")";
    122 }
    123 
    124 ppapi::host::HostFactory* ShellNaClBrowserDelegate::CreatePpapiHostFactory(
    125     content::BrowserPpapiHost* ppapi_host) {
    126   return NULL;
    127 }
    128 
    129 void ShellNaClBrowserDelegate::SetDebugPatterns(std::string debug_patterns) {
    130   // No debugger support. Developers should use Chrome for debugging.
    131 }
    132 
    133 bool ShellNaClBrowserDelegate::URLMatchesDebugPatterns(
    134     const GURL& manifest_url) {
    135   // No debugger support. Developers should use Chrome for debugging.
    136   return false;
    137 }
    138 
    139 // This function is security sensitive.  Be sure to check with a security
    140 // person before you modify it.
    141 // TODO(jamescook): Refactor this code into the extensions module so it can
    142 // be shared with Chrome's NaClBrowserDelegateImpl. http://crbug.com/403017
    143 bool ShellNaClBrowserDelegate::MapUrlToLocalFilePath(
    144     const GURL& file_url,
    145     bool use_blocking_api,
    146     const base::FilePath& profile_directory,
    147     base::FilePath* file_path) {
    148   scoped_refptr<InfoMap> info_map =
    149       ExtensionSystem::Get(browser_context_)->info_map();
    150   // Check that the URL is recognized by the extension system.
    151   const Extension* extension =
    152       info_map->extensions().GetExtensionOrAppByURL(file_url);
    153   if (!extension)
    154     return false;
    155 
    156   // This is a short-cut which avoids calling a blocking file operation
    157   // (GetFilePath()), so that this can be called on the IO thread. It only
    158   // handles a subset of the urls.
    159   if (!use_blocking_api) {
    160     if (file_url.SchemeIs(kExtensionScheme)) {
    161       std::string path = file_url.path();
    162       base::TrimString(path, "/", &path);  // Remove first slash
    163       *file_path = extension->path().AppendASCII(path);
    164       return true;
    165     }
    166     return false;
    167   }
    168 
    169   // Check that the URL references a resource in the extension.
    170   // NOTE: app_shell does not support shared modules.
    171   ExtensionResource resource = extension->GetResource(file_url.path());
    172   if (resource.empty())
    173     return false;
    174 
    175   // GetFilePath is a blocking function call.
    176   const base::FilePath resource_file_path = resource.GetFilePath();
    177   if (resource_file_path.empty())
    178     return false;
    179 
    180   *file_path = resource_file_path;
    181   return true;
    182 }
    183 
    184 content::BrowserPpapiHost::OnKeepaliveCallback
    185 ShellNaClBrowserDelegate::GetOnKeepaliveCallback() {
    186   return base::Bind(&OnKeepalive);
    187 }
    188 
    189 bool ShellNaClBrowserDelegate::IsNonSfiModeAllowed(
    190     const base::FilePath& profile_directory,
    191     const GURL& manifest_url) {
    192   return false;
    193 }
    194 
    195 }  // namespace extensions
    196