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 28using content::BrowserContext; 29using content::BrowserThread; 30using content::BrowserPpapiHost; 31 32namespace extensions { 33namespace { 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. 38void 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. 55void 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 67ShellNaClBrowserDelegate::ShellNaClBrowserDelegate(BrowserContext* context) 68 : browser_context_(context) { 69 DCHECK(browser_context_); 70} 71 72ShellNaClBrowserDelegate::~ShellNaClBrowserDelegate() { 73} 74 75void 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 81bool ShellNaClBrowserDelegate::DialogsAreSuppressed() { 82 return false; 83} 84 85bool 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 95bool 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 100bool 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 109bool 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 118std::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 124ppapi::host::HostFactory* ShellNaClBrowserDelegate::CreatePpapiHostFactory( 125 content::BrowserPpapiHost* ppapi_host) { 126 return NULL; 127} 128 129void ShellNaClBrowserDelegate::SetDebugPatterns(std::string debug_patterns) { 130 // No debugger support. Developers should use Chrome for debugging. 131} 132 133bool 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 143bool 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 184content::BrowserPpapiHost::OnKeepaliveCallback 185ShellNaClBrowserDelegate::GetOnKeepaliveCallback() { 186 return base::Bind(&OnKeepalive); 187} 188 189bool ShellNaClBrowserDelegate::IsNonSfiModeAllowed( 190 const base::FilePath& profile_directory, 191 const GURL& manifest_url) { 192 return false; 193} 194 195} // namespace extensions 196