103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file.
403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/shell/browser/shell_nacl_browser_delegate.h"
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <string>
803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/base_paths.h"
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/command_line.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/path_service.h"
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/strings/string_split.h"
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/strings/string_util.h"
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/browser_context.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/site_instance.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/extension_system.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/info_map.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/process_manager.h"
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/constants.h"
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/extension.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/url_pattern.h"
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/shell/common/version.h"  // Generated file.
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ppapi/c/private/ppb_nacl_private.h"
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "url/gurl.h"
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using content::BrowserContext;
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using content::BrowserThread;
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using content::BrowserPpapiHost;
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace extensions {
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Handles an extension's NaCl process transitioning in or out of idle state by
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// relaying the state to the extension's process manager. See Chrome's
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// NaClBrowserDelegateImpl for another example.
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void OnKeepaliveOnUIThread(
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const base::FilePath& profile_data_directory) {
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::UI);
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Only one instance will exist for NaCl embeds, even when more than one
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // embed of the same plugin exists on the same page.
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(instance_data.size() == 1);
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (instance_data.size() < 1)
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessManager::OnKeepaliveFromPlugin(instance_data[0].render_process_id,
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                        instance_data[0].render_frame_id,
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                        instance_data[0].document_url.host());
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Calls OnKeepaliveOnUIThread on UI thread.
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void OnKeepalive(const BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 const base::FilePath& profile_data_directory) {
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  BrowserThread::PostTask(
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      BrowserThread::UI,
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      FROM_HERE,
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          &OnKeepaliveOnUIThread, instance_data, profile_data_directory));
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ShellNaClBrowserDelegate::ShellNaClBrowserDelegate(BrowserContext* context)
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : browser_context_(context) {
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(browser_context_);
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ShellNaClBrowserDelegate::~ShellNaClBrowserDelegate() {
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ShellNaClBrowserDelegate::ShowMissingArchInfobar(int render_process_id,
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                      int render_view_id) {
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // app_shell does not have infobars.
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  LOG(ERROR) << "Missing architecture for pid " << render_process_id;
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::DialogsAreSuppressed() {
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::GetCacheDirectory(base::FilePath* cache_dir) {
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Just use the general cache directory, not a subdirectory like Chrome does.
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_POSIX)
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return PathService::Get(base::DIR_CACHE, cache_dir);
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#elif defined(OS_WIN)
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(yoz): Find an appropriate persistent directory to use here.
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return PathService::Get(base::DIR_TEMP, cache_dir);
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::GetPluginDirectory(base::FilePath* plugin_dir) {
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // On Posix, plugins are in the module directory.
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return PathService::Get(base::DIR_MODULE, plugin_dir);
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::GetPnaclDirectory(base::FilePath* pnacl_dir) {
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // On Posix, the pnacl directory is inside the plugin directory.
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::FilePath plugin_dir;
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!GetPluginDirectory(&plugin_dir))
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *pnacl_dir = plugin_dir.Append(FILE_PATH_LITERAL("pnacl"));
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::GetUserDirectory(base::FilePath* user_dir) {
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::FilePath path = browser_context_->GetPath();
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!path.empty()) {
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    *user_dir = path;
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return true;
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)std::string ShellNaClBrowserDelegate::GetVersionString() const {
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // A version change triggers an update of the NaCl validation caches.
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Example version: "39.0.2129.0 (290550)".
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return PRODUCT_VERSION " (" LAST_CHANGE ")";
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ppapi::host::HostFactory* ShellNaClBrowserDelegate::CreatePpapiHostFactory(
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    content::BrowserPpapiHost* ppapi_host) {
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return NULL;
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ShellNaClBrowserDelegate::SetDebugPatterns(std::string debug_patterns) {
13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // No debugger support. Developers should use Chrome for debugging.
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::URLMatchesDebugPatterns(
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const GURL& manifest_url) {
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // No debugger support. Developers should use Chrome for debugging.
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// This function is security sensitive.  Be sure to check with a security
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// person before you modify it.
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// TODO(jamescook): Refactor this code into the extensions module so it can
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// be shared with Chrome's NaClBrowserDelegateImpl. http://crbug.com/403017
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::MapUrlToLocalFilePath(
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const GURL& file_url,
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    bool use_blocking_api,
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const base::FilePath& profile_directory,
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::FilePath* file_path) {
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<InfoMap> info_map =
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionSystem::Get(browser_context_)->info_map();
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Check that the URL is recognized by the extension system.
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const Extension* extension =
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      info_map->extensions().GetExtensionOrAppByURL(file_url);
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!extension)
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // This is a short-cut which avoids calling a blocking file operation
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // (GetFilePath()), so that this can be called on the IO thread. It only
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // handles a subset of the urls.
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!use_blocking_api) {
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (file_url.SchemeIs(kExtensionScheme)) {
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      std::string path = file_url.path();
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::TrimString(path, "/", &path);  // Remove first slash
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      *file_path = extension->path().AppendASCII(path);
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return true;
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Check that the URL references a resource in the extension.
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // NOTE: app_shell does not support shared modules.
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtensionResource resource = extension->GetResource(file_url.path());
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (resource.empty())
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // GetFilePath is a blocking function call.
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const base::FilePath resource_file_path = resource.GetFilePath();
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (resource_file_path.empty())
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *file_path = resource_file_path;
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)content::BrowserPpapiHost::OnKeepaliveCallback
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ShellNaClBrowserDelegate::GetOnKeepaliveCallback() {
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return base::Bind(&OnKeepalive);
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ShellNaClBrowserDelegate::IsNonSfiModeAllowed(
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const base::FilePath& profile_directory,
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const GURL& manifest_url) {
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace extensions
196