mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	Add support for loading extensions (issue #1947)
- Add CefRequestContext::LoadExtension, CefExtension, CefExtensionHandler and related methods/interfaces. - Add chrome://extensions-support that lists supported Chrome APIs. - Add CefBrowserHost::SetAutoResizeEnabled and CefDisplayHandler::OnAutoResize to support browser resize based on preferred web contents size. - views: Add support for custom CefMenuButton popups. - cefclient: Run with `--load-extension=set_page_color` command-line flag for an extension loading example. Add `--use-views` on Windows and Linux for an even better example.
This commit is contained in:
		@@ -1,21 +1,20 @@
 | 
			
		||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
// Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2012 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/api/tabs/tabs_api.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
#include "libcef/browser/browser_info_manager.h"
 | 
			
		||||
#include "libcef/browser/request_context_impl.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_web_contents_observer.h"
 | 
			
		||||
 | 
			
		||||
#include "base/strings/string_number_conversions.h"
 | 
			
		||||
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 | 
			
		||||
#include "chrome/browser/profiles/profile.h"
 | 
			
		||||
#include "chrome/browser/sessions/session_tab_helper.h"
 | 
			
		||||
#include "components/zoom/zoom_controller.h"
 | 
			
		||||
#include "content/public/browser/render_frame_host.h"
 | 
			
		||||
#include "content/public/common/page_zoom.h"
 | 
			
		||||
#include "extensions/browser/extension_api_frame_id_map.h"
 | 
			
		||||
#include "extensions/browser/extension_zoom_request_client.h"
 | 
			
		||||
#include "extensions/common/error_utils.h"
 | 
			
		||||
#include "extensions/common/manifest_constants.h"
 | 
			
		||||
#include "extensions/common/permissions/permissions_data.h"
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
@@ -24,83 +23,12 @@ namespace cef {
 | 
			
		||||
namespace keys = extensions::tabs_constants;
 | 
			
		||||
namespace tabs = api::tabs;
 | 
			
		||||
 | 
			
		||||
using api::extension_types::InjectDetails;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
const char kNotImplementedError[] = "Not implemented";
 | 
			
		||||
 | 
			
		||||
// Any out parameter (|browser|, |contents|, & |tab_index|) may be NULL and will
 | 
			
		||||
// not be set within the function.
 | 
			
		||||
// Based on ExtensionTabUtil::GetTabById().
 | 
			
		||||
bool GetTabById(int tab_id,
 | 
			
		||||
                content::BrowserContext* browser_context,
 | 
			
		||||
                bool include_incognito,
 | 
			
		||||
                CefRefPtr<CefBrowserHostImpl>* browser,
 | 
			
		||||
                content::WebContents** contents) {
 | 
			
		||||
  if (tab_id == api::tabs::TAB_ID_NONE)
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  // As an extra security check make sure we're operating in the same
 | 
			
		||||
  // BrowserContext.
 | 
			
		||||
  Profile* profile = Profile::FromBrowserContext(browser_context);
 | 
			
		||||
  Profile* incognito_profile =
 | 
			
		||||
      include_incognito && profile->HasOffTheRecordProfile()
 | 
			
		||||
          ? profile->GetOffTheRecordProfile()
 | 
			
		||||
          : NULL;
 | 
			
		||||
 | 
			
		||||
  CefBrowserInfoManager::BrowserInfoList list;
 | 
			
		||||
  CefBrowserInfoManager::GetInstance()->GetBrowserInfoList(list);
 | 
			
		||||
  for (auto browser_info : list) {
 | 
			
		||||
    CefRefPtr<CefBrowserHostImpl> cef_browser = browser_info->browser();
 | 
			
		||||
    if (!cef_browser)
 | 
			
		||||
      continue;
 | 
			
		||||
    CefRefPtr<CefRequestContext> request_context =
 | 
			
		||||
        cef_browser->GetRequestContext();
 | 
			
		||||
    if (!request_context)
 | 
			
		||||
      continue;
 | 
			
		||||
    CefRefPtr<CefRequestContextImpl> request_context_impl =
 | 
			
		||||
        CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
 | 
			
		||||
    if (!request_context_impl)
 | 
			
		||||
      continue;
 | 
			
		||||
    CefBrowserContext* browser_context =
 | 
			
		||||
        request_context_impl->GetBrowserContext();
 | 
			
		||||
    if (!browser_context)
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    if (browser_context == profile || browser_context == incognito_profile) {
 | 
			
		||||
      content::WebContents* web_contents = cef_browser->web_contents();
 | 
			
		||||
      if (SessionTabHelper::IdForTab(web_contents) == tab_id) {
 | 
			
		||||
        if (browser)
 | 
			
		||||
          *browser = cef_browser;
 | 
			
		||||
        if (contents)
 | 
			
		||||
          *contents = web_contents;
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// |error_message| can optionally be passed in and will be set with an
 | 
			
		||||
// appropriate message if the tab cannot be found by id.
 | 
			
		||||
bool GetTabById(int tab_id,
 | 
			
		||||
                content::BrowserContext* browser_context,
 | 
			
		||||
                bool include_incognito,
 | 
			
		||||
                CefRefPtr<CefBrowserHostImpl>* browser,
 | 
			
		||||
                content::WebContents** contents,
 | 
			
		||||
                std::string* error_message) {
 | 
			
		||||
  if (GetTabById(tab_id, browser_context, include_incognito, browser,
 | 
			
		||||
                 contents)) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (error_message) {
 | 
			
		||||
    *error_message = ErrorUtils::FormatErrorMessage(keys::kTabNotFoundError,
 | 
			
		||||
                                                    base::IntToString(tab_id));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ZoomModeToZoomSettings(zoom::ZoomController::ZoomMode zoom_mode,
 | 
			
		||||
                            api::tabs::ZoomSettings* zoom_settings) {
 | 
			
		||||
  DCHECK(zoom_settings);
 | 
			
		||||
@@ -130,18 +58,172 @@ ExtensionFunction::ResponseAction TabsGetFunction::Run() {
 | 
			
		||||
  return RespondNow(Error(kNotImplementedError));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
content::WebContents* ZoomAPIFunction::GetWebContents(int tab_id) {
 | 
			
		||||
  content::WebContents* web_contents = NULL;
 | 
			
		||||
  if (tab_id != -1) {
 | 
			
		||||
    // We assume this call leaves web_contents unchanged if it is unsuccessful.
 | 
			
		||||
    GetTabById(tab_id, context_, include_incognito(),
 | 
			
		||||
               NULL /* ignore CefBrowserHostImpl* output */, &web_contents,
 | 
			
		||||
               &error_);
 | 
			
		||||
  } else {
 | 
			
		||||
    // Use the sender as the default.
 | 
			
		||||
    web_contents = GetSenderWebContents();
 | 
			
		||||
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction()
 | 
			
		||||
    : cef_details_(this), execute_tab_id_(-1) {}
 | 
			
		||||
 | 
			
		||||
ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
 | 
			
		||||
 | 
			
		||||
bool ExecuteCodeInTabFunction::HasPermission() {
 | 
			
		||||
  if (Init() == SUCCESS &&
 | 
			
		||||
      // TODO(devlin/lazyboy): Consider removing the following check as it isn't
 | 
			
		||||
      // doing anything. The fallback to ExtensionFunction::HasPermission()
 | 
			
		||||
      // below dictates what this function returns.
 | 
			
		||||
      extension_->permissions_data()->HasAPIPermissionForTab(
 | 
			
		||||
          execute_tab_id_, APIPermission::kTab)) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return web_contents;
 | 
			
		||||
  return ExtensionFunction::HasPermission();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ExecuteCodeFunction::InitResult ExecuteCodeInTabFunction::Init() {
 | 
			
		||||
  if (init_result_)
 | 
			
		||||
    return init_result_.value();
 | 
			
		||||
 | 
			
		||||
  // |tab_id| is optional so it's ok if it's not there.
 | 
			
		||||
  int tab_id = -1;
 | 
			
		||||
  if (args_->GetInteger(0, &tab_id) && tab_id < 0)
 | 
			
		||||
    return set_init_result(VALIDATION_FAILURE);
 | 
			
		||||
 | 
			
		||||
  // |details| are not optional.
 | 
			
		||||
  base::DictionaryValue* details_value = NULL;
 | 
			
		||||
  if (!args_->GetDictionary(1, &details_value))
 | 
			
		||||
    return set_init_result(VALIDATION_FAILURE);
 | 
			
		||||
  std::unique_ptr<InjectDetails> details(new InjectDetails());
 | 
			
		||||
  if (!InjectDetails::Populate(*details_value, details.get()))
 | 
			
		||||
    return set_init_result(VALIDATION_FAILURE);
 | 
			
		||||
 | 
			
		||||
  // Find a browser that we can access, or fail with error.
 | 
			
		||||
  std::string error;
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error);
 | 
			
		||||
  if (!browser)
 | 
			
		||||
    return set_init_result_error(error);
 | 
			
		||||
 | 
			
		||||
  execute_tab_id_ = browser->GetIdentifier();
 | 
			
		||||
  details_ = std::move(details);
 | 
			
		||||
  set_host_id(HostID(HostID::EXTENSIONS, extension()->id()));
 | 
			
		||||
  return set_init_result(SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage() {
 | 
			
		||||
  CHECK_GE(execute_tab_id_, 0);
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      cef_details_.GetBrowserForTabIdAgain(execute_tab_id_, &error_);
 | 
			
		||||
  if (!browser)
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  int frame_id = details_->frame_id ? *details_->frame_id
 | 
			
		||||
                                    : ExtensionApiFrameIdMap::kTopFrameId;
 | 
			
		||||
  content::RenderFrameHost* rfh =
 | 
			
		||||
      ExtensionApiFrameIdMap::GetRenderFrameHostById(browser->web_contents(),
 | 
			
		||||
                                                     frame_id);
 | 
			
		||||
  if (!rfh) {
 | 
			
		||||
    error_ = ErrorUtils::FormatErrorMessage(keys::kFrameNotFoundError,
 | 
			
		||||
                                            base::IntToString(frame_id),
 | 
			
		||||
                                            base::IntToString(execute_tab_id_));
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Content scripts declared in manifest.json can access frames at about:-URLs
 | 
			
		||||
  // if the extension has permission to access the frame's origin, so also allow
 | 
			
		||||
  // programmatic content scripts at about:-URLs for allowed origins.
 | 
			
		||||
  GURL effective_document_url(rfh->GetLastCommittedURL());
 | 
			
		||||
  bool is_about_url = effective_document_url.SchemeIs(url::kAboutScheme);
 | 
			
		||||
  if (is_about_url && details_->match_about_blank &&
 | 
			
		||||
      *details_->match_about_blank) {
 | 
			
		||||
    effective_document_url = GURL(rfh->GetLastCommittedOrigin().Serialize());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!effective_document_url.is_valid()) {
 | 
			
		||||
    // Unknown URL, e.g. because no load was committed yet. Allow for now, the
 | 
			
		||||
    // renderer will check again and fail the injection if needed.
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // NOTE: This can give the wrong answer due to race conditions, but it is OK,
 | 
			
		||||
  // we check again in the renderer.
 | 
			
		||||
  if (!extension()->permissions_data()->CanAccessPage(
 | 
			
		||||
          extension(), effective_document_url, execute_tab_id_, &error_)) {
 | 
			
		||||
    if (is_about_url &&
 | 
			
		||||
        extension()->permissions_data()->active_permissions().HasAPIPermission(
 | 
			
		||||
            APIPermission::kTab)) {
 | 
			
		||||
      error_ = ErrorUtils::FormatErrorMessage(
 | 
			
		||||
          manifest_errors::kCannotAccessAboutUrl,
 | 
			
		||||
          rfh->GetLastCommittedURL().spec(),
 | 
			
		||||
          rfh->GetLastCommittedOrigin().Serialize());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScriptExecutor* ExecuteCodeInTabFunction::GetScriptExecutor() {
 | 
			
		||||
  CHECK_GE(execute_tab_id_, 0);
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      cef_details_.GetBrowserForTabIdAgain(execute_tab_id_, &error_);
 | 
			
		||||
  if (!browser)
 | 
			
		||||
    return nullptr;
 | 
			
		||||
 | 
			
		||||
  return CefExtensionWebContentsObserver::FromWebContents(
 | 
			
		||||
             browser->web_contents())
 | 
			
		||||
      ->script_executor();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ExecuteCodeInTabFunction::IsWebView() const {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const GURL& ExecuteCodeInTabFunction::GetWebViewSrc() const {
 | 
			
		||||
  return GURL::EmptyGURL();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ExecuteCodeInTabFunction::LoadFile(const std::string& file) {
 | 
			
		||||
  if (cef_details_.LoadFile(
 | 
			
		||||
          file, base::BindOnce(&ExecuteCodeInTabFunction::LoadFileComplete,
 | 
			
		||||
                               this, file))) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Default handling.
 | 
			
		||||
  return ExecuteCodeFunction::LoadFile(file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExecuteCodeInTabFunction::LoadFileComplete(
 | 
			
		||||
    const std::string& file,
 | 
			
		||||
    std::unique_ptr<std::string> data) {
 | 
			
		||||
  DidLoadAndLocalizeFile(file, !!data.get(), std::move(data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TabsExecuteScriptFunction::ShouldInsertCSS() const {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TabsExecuteScriptFunction::OnExecuteCodeFinished(
 | 
			
		||||
    const std::string& error,
 | 
			
		||||
    const GURL& on_url,
 | 
			
		||||
    const base::ListValue& result) {
 | 
			
		||||
  if (error.empty())
 | 
			
		||||
    SetResult(result.CreateDeepCopy());
 | 
			
		||||
  ExecuteCodeInTabFunction::OnExecuteCodeFinished(error, on_url, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TabsInsertCSSFunction::ShouldInsertCSS() const {
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ZoomAPIFunction::ZoomAPIFunction() : cef_details_(this) {}
 | 
			
		||||
 | 
			
		||||
content::WebContents* ZoomAPIFunction::GetWebContents(int tab_id) {
 | 
			
		||||
  // Find a browser that we can access, or set |error_| and return nullptr.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error_);
 | 
			
		||||
  if (!browser)
 | 
			
		||||
    return nullptr;
 | 
			
		||||
 | 
			
		||||
  return browser->web_contents();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TabsSetZoomFunction::RunAsync() {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,10 @@
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extension_function_details.h"
 | 
			
		||||
 | 
			
		||||
#include "chrome/common/extensions/api/tabs.h"
 | 
			
		||||
#include "extensions/browser/api/execute_code_function.h"
 | 
			
		||||
#include "extensions/browser/extension_function.h"
 | 
			
		||||
 | 
			
		||||
// The contents of this file are extracted from
 | 
			
		||||
@@ -26,17 +29,72 @@ class TabsGetFunction : public UIThreadExtensionFunction {
 | 
			
		||||
  DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implement API call tabs.executeScript and tabs.insertCSS.
 | 
			
		||||
class ExecuteCodeInTabFunction : public ExecuteCodeFunction {
 | 
			
		||||
 public:
 | 
			
		||||
  ExecuteCodeInTabFunction();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  ~ExecuteCodeInTabFunction() override;
 | 
			
		||||
 | 
			
		||||
  // ExtensionFunction:
 | 
			
		||||
  bool HasPermission() override;
 | 
			
		||||
 | 
			
		||||
  // Initializes |execute_tab_id_| and |details_|.
 | 
			
		||||
  InitResult Init() override;
 | 
			
		||||
  bool CanExecuteScriptOnPage() override;
 | 
			
		||||
  ScriptExecutor* GetScriptExecutor() override;
 | 
			
		||||
  bool IsWebView() const override;
 | 
			
		||||
  const GURL& GetWebViewSrc() const override;
 | 
			
		||||
  bool LoadFile(const std::string& file) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const CefExtensionFunctionDetails cef_details_;
 | 
			
		||||
 | 
			
		||||
  void LoadFileComplete(const std::string& file,
 | 
			
		||||
                        std::unique_ptr<std::string> data);
 | 
			
		||||
 | 
			
		||||
  // Id of tab which executes code.
 | 
			
		||||
  int execute_tab_id_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
 | 
			
		||||
 protected:
 | 
			
		||||
  bool ShouldInsertCSS() const override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  ~TabsExecuteScriptFunction() override {}
 | 
			
		||||
 | 
			
		||||
  void OnExecuteCodeFinished(const std::string& error,
 | 
			
		||||
                             const GURL& on_url,
 | 
			
		||||
                             const base::ListValue& script_result) override;
 | 
			
		||||
 | 
			
		||||
  DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TabsInsertCSSFunction : public ExecuteCodeInTabFunction {
 | 
			
		||||
 private:
 | 
			
		||||
  ~TabsInsertCSSFunction() override {}
 | 
			
		||||
 | 
			
		||||
  bool ShouldInsertCSS() const override;
 | 
			
		||||
 | 
			
		||||
  DECLARE_EXTENSION_FUNCTION("tabs.insertCSS", TABS_INSERTCSS)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ZoomAPIFunction : public AsyncExtensionFunction {
 | 
			
		||||
 public:
 | 
			
		||||
  ZoomAPIFunction();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  ~ZoomAPIFunction() override {}
 | 
			
		||||
 | 
			
		||||
  // Gets the WebContents for |tab_id| if it is specified. Otherwise get the
 | 
			
		||||
  // WebContents for the active tab in the current window. Calling this function
 | 
			
		||||
  // may set error_.
 | 
			
		||||
  //
 | 
			
		||||
  // TODO(...) many other tabs API functions use similar behavior. There should
 | 
			
		||||
  // be a way to share this implementation somehow.
 | 
			
		||||
  content::WebContents* GetWebContents(int tab_id);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const CefExtensionFunctionDetails cef_details_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TabsSetZoomFunction : public ZoomAPIFunction {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/browser_extensions_util.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_context_impl.h"
 | 
			
		||||
#include "libcef/browser/browser_info_manager.h"
 | 
			
		||||
#include "libcef/browser/thread_util.h"
 | 
			
		||||
#include "libcef/common/extensions/extensions_util.h"
 | 
			
		||||
@@ -13,6 +14,7 @@
 | 
			
		||||
#include "content/browser/web_contents/web_contents_impl.h"
 | 
			
		||||
#include "content/public/browser/browser_context.h"
 | 
			
		||||
#include "content/public/browser/browser_plugin_guest_manager.h"
 | 
			
		||||
#include "extensions/browser/extension_registry.h"
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
@@ -130,4 +132,45 @@ CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
 | 
			
		||||
  return browser;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
 | 
			
		||||
    int tab_id,
 | 
			
		||||
    content::BrowserContext* browser_context) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  DCHECK(browser_context);
 | 
			
		||||
  if (tab_id == -1 || !browser_context)
 | 
			
		||||
    return nullptr;
 | 
			
		||||
 | 
			
		||||
  CefBrowserContextImpl* browser_context_impl =
 | 
			
		||||
      CefBrowserContextImpl::GetForContext(browser_context);
 | 
			
		||||
 | 
			
		||||
  CefBrowserInfoManager::BrowserInfoList list;
 | 
			
		||||
  CefBrowserInfoManager::GetInstance()->GetBrowserInfoList(list);
 | 
			
		||||
  for (auto browser_info : list) {
 | 
			
		||||
    CefRefPtr<CefBrowserHostImpl> current_browser = browser_info->browser();
 | 
			
		||||
    if (current_browser && current_browser->GetIdentifier() == tab_id) {
 | 
			
		||||
      // Make sure we're operating in the same BrowserContextImpl.
 | 
			
		||||
      if (CefBrowserContextImpl::GetForContext(
 | 
			
		||||
              current_browser->GetBrowserContext()) == browser_context_impl) {
 | 
			
		||||
        return current_browser;
 | 
			
		||||
      } else {
 | 
			
		||||
        LOG(WARNING) << "Browser with tabId " << tab_id
 | 
			
		||||
                     << " cannot be accessed because is uses a different "
 | 
			
		||||
                        "CefRequestContext";
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Extension* GetExtensionForUrl(content::BrowserContext* browser_context,
 | 
			
		||||
                                    const GURL& url) {
 | 
			
		||||
  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context);
 | 
			
		||||
  if (!registry)
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  std::string extension_id = url.host();
 | 
			
		||||
  return registry->enabled_extensions().GetByID(extension_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 
 | 
			
		||||
@@ -9,13 +9,18 @@
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
 | 
			
		||||
#include "url/gurl.h"
 | 
			
		||||
 | 
			
		||||
namespace content {
 | 
			
		||||
class BrowserContext;
 | 
			
		||||
class RenderViewHost;
 | 
			
		||||
class WebContents;
 | 
			
		||||
}
 | 
			
		||||
}  // namespace content
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
class Extension;
 | 
			
		||||
 | 
			
		||||
// Returns the full-page guest WebContents for the specified |owner|, if any.
 | 
			
		||||
content::WebContents* GetFullPageGuestForOwnerContents(
 | 
			
		||||
    content::WebContents* owner);
 | 
			
		||||
@@ -47,6 +52,18 @@ CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
 | 
			
		||||
    content::RenderFrameHost* host,
 | 
			
		||||
    bool* is_guest_view);
 | 
			
		||||
 | 
			
		||||
// Returns the browser matching |tab_id| and |browser_context|. Returns false if
 | 
			
		||||
// |tab_id| is -1 or a matching browser cannot be found within
 | 
			
		||||
// |browser_context|. Similar in concept to ExtensionTabUtil::GetTabById.
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
 | 
			
		||||
    int tab_id,
 | 
			
		||||
    content::BrowserContext* browser_context);
 | 
			
		||||
 | 
			
		||||
// Returns the extension associated with |url| in |profile|. Returns nullptr
 | 
			
		||||
// if the extension does not exist.
 | 
			
		||||
const Extension* GetExtensionForUrl(content::BrowserContext* browser_context,
 | 
			
		||||
                                    const GURL& url);
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 | 
			
		||||
#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,153 @@
 | 
			
		||||
// Copyright 2017 The Chromium Embedded Framework Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/browser_platform_delegate_background.h"
 | 
			
		||||
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
#include "libcef/browser/thread_util.h"
 | 
			
		||||
 | 
			
		||||
#include "content/public/browser/render_view_host.h"
 | 
			
		||||
#include "content/public/browser/render_widget_host.h"
 | 
			
		||||
 | 
			
		||||
CefBrowserPlatformDelegateBackground::CefBrowserPlatformDelegateBackground(
 | 
			
		||||
    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
 | 
			
		||||
    : native_delegate_(std::move(native_delegate)) {
 | 
			
		||||
  native_delegate_->set_windowless_handler(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefBrowserPlatformDelegateBackground::CreateHostWindow() {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::CloseHostWindow() {
 | 
			
		||||
  // No host window, so continue browser destruction now. Do it asynchronously
 | 
			
		||||
  // so the call stack has a chance to unwind.
 | 
			
		||||
  CEF_POST_TASK(CEF_UIT,
 | 
			
		||||
                base::Bind(&CefBrowserHostImpl::WindowDestroyed, browser_));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefWindowHandle CefBrowserPlatformDelegateBackground::GetHostWindowHandle()
 | 
			
		||||
    const {
 | 
			
		||||
  return kNullWindowHandle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SkColor CefBrowserPlatformDelegateBackground::GetBackgroundColor() const {
 | 
			
		||||
  return native_delegate_->GetBackgroundColor();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::WasResized() {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::SendKeyEvent(
 | 
			
		||||
    const content::NativeWebKeyboardEvent& event) {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::SendMouseEvent(
 | 
			
		||||
    const blink::WebMouseEvent& event) {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::SendMouseWheelEvent(
 | 
			
		||||
    const blink::WebMouseWheelEvent& event) {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::SendFocusEvent(bool setFocus) {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gfx::Point CefBrowserPlatformDelegateBackground::GetScreenPoint(
 | 
			
		||||
    const gfx::Point& view_pt) const {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
  return view_pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::ViewText(const std::string& text) {
 | 
			
		||||
  native_delegate_->ViewText(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::HandleKeyboardEvent(
 | 
			
		||||
    const content::NativeWebKeyboardEvent& event) {
 | 
			
		||||
  // Nothing to do here.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::HandleExternalProtocol(
 | 
			
		||||
    const GURL& url) {
 | 
			
		||||
  native_delegate_->HandleExternalProtocol(url);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::TranslateKeyEvent(
 | 
			
		||||
    content::NativeWebKeyboardEvent& result,
 | 
			
		||||
    const CefKeyEvent& key_event) const {
 | 
			
		||||
  native_delegate_->TranslateKeyEvent(result, key_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::TranslateClickEvent(
 | 
			
		||||
    blink::WebMouseEvent& result,
 | 
			
		||||
    const CefMouseEvent& mouse_event,
 | 
			
		||||
    CefBrowserHost::MouseButtonType type,
 | 
			
		||||
    bool mouseUp,
 | 
			
		||||
    int clickCount) const {
 | 
			
		||||
  native_delegate_->TranslateClickEvent(result, mouse_event, type, mouseUp,
 | 
			
		||||
                                        clickCount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::TranslateMoveEvent(
 | 
			
		||||
    blink::WebMouseEvent& result,
 | 
			
		||||
    const CefMouseEvent& mouse_event,
 | 
			
		||||
    bool mouseLeave) const {
 | 
			
		||||
  native_delegate_->TranslateMoveEvent(result, mouse_event, mouseLeave);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefBrowserPlatformDelegateBackground::TranslateWheelEvent(
 | 
			
		||||
    blink::WebMouseWheelEvent& result,
 | 
			
		||||
    const CefMouseEvent& mouse_event,
 | 
			
		||||
    int deltaX,
 | 
			
		||||
    int deltaY) const {
 | 
			
		||||
  native_delegate_->TranslateWheelEvent(result, mouse_event, deltaX, deltaY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefEventHandle CefBrowserPlatformDelegateBackground::GetEventHandle(
 | 
			
		||||
    const content::NativeWebKeyboardEvent& event) const {
 | 
			
		||||
  return native_delegate_->GetEventHandle(event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<CefFileDialogRunner>
 | 
			
		||||
CefBrowserPlatformDelegateBackground::CreateFileDialogRunner() {
 | 
			
		||||
  return native_delegate_->CreateFileDialogRunner();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<CefJavaScriptDialogRunner>
 | 
			
		||||
CefBrowserPlatformDelegateBackground::CreateJavaScriptDialogRunner() {
 | 
			
		||||
  return native_delegate_->CreateJavaScriptDialogRunner();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<CefMenuRunner>
 | 
			
		||||
CefBrowserPlatformDelegateBackground::CreateMenuRunner() {
 | 
			
		||||
  // No default menu implementation for background browsers.
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefBrowserPlatformDelegateBackground::IsWindowless() const {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefBrowserPlatformDelegateBackground::IsViewsHosted() const {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefWindowHandle CefBrowserPlatformDelegateBackground::GetParentWindowHandle()
 | 
			
		||||
    const {
 | 
			
		||||
  return GetHostWindowHandle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gfx::Point CefBrowserPlatformDelegateBackground::GetParentScreenPoint(
 | 
			
		||||
    const gfx::Point& view) const {
 | 
			
		||||
  return GetScreenPoint(view);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
// Copyright 2017 The Chromium Embedded Framework Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_BACKGROUND_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_BACKGROUND_H_
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_platform_delegate.h"
 | 
			
		||||
#include "libcef/browser/native/browser_platform_delegate_native.h"
 | 
			
		||||
 | 
			
		||||
// Implementation of browser functionality for background script hosts.
 | 
			
		||||
class CefBrowserPlatformDelegateBackground
 | 
			
		||||
    : public CefBrowserPlatformDelegate,
 | 
			
		||||
      public CefBrowserPlatformDelegateNative::WindowlessHandler {
 | 
			
		||||
 public:
 | 
			
		||||
  // Platform-specific behaviors will be delegated to |native_delegate|.
 | 
			
		||||
  CefBrowserPlatformDelegateBackground(
 | 
			
		||||
      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
 | 
			
		||||
 | 
			
		||||
  // CefBrowserPlatformDelegate methods:
 | 
			
		||||
  bool CreateHostWindow() override;
 | 
			
		||||
  void CloseHostWindow() override;
 | 
			
		||||
  CefWindowHandle GetHostWindowHandle() const override;
 | 
			
		||||
  SkColor GetBackgroundColor() const override;
 | 
			
		||||
  void WasResized() override;
 | 
			
		||||
  void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
 | 
			
		||||
  void SendMouseEvent(const blink::WebMouseEvent& event) override;
 | 
			
		||||
  void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
 | 
			
		||||
  void SendFocusEvent(bool setFocus) override;
 | 
			
		||||
  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
 | 
			
		||||
  void ViewText(const std::string& text) override;
 | 
			
		||||
  void HandleKeyboardEvent(
 | 
			
		||||
      const content::NativeWebKeyboardEvent& event) override;
 | 
			
		||||
  void HandleExternalProtocol(const GURL& url) override;
 | 
			
		||||
  void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
 | 
			
		||||
                         const CefKeyEvent& key_event) const override;
 | 
			
		||||
  void TranslateClickEvent(blink::WebMouseEvent& result,
 | 
			
		||||
                           const CefMouseEvent& mouse_event,
 | 
			
		||||
                           CefBrowserHost::MouseButtonType type,
 | 
			
		||||
                           bool mouseUp,
 | 
			
		||||
                           int clickCount) const override;
 | 
			
		||||
  void TranslateMoveEvent(blink::WebMouseEvent& result,
 | 
			
		||||
                          const CefMouseEvent& mouse_event,
 | 
			
		||||
                          bool mouseLeave) const override;
 | 
			
		||||
  void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
 | 
			
		||||
                           const CefMouseEvent& mouse_event,
 | 
			
		||||
                           int deltaX,
 | 
			
		||||
                           int deltaY) const override;
 | 
			
		||||
  CefEventHandle GetEventHandle(
 | 
			
		||||
      const content::NativeWebKeyboardEvent& event) const override;
 | 
			
		||||
  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
 | 
			
		||||
  std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
 | 
			
		||||
      override;
 | 
			
		||||
  std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
 | 
			
		||||
  bool IsWindowless() const override;
 | 
			
		||||
  bool IsViewsHosted() const override;
 | 
			
		||||
 | 
			
		||||
  // CefBrowserPlatformDelegateNative::WindowlessHandler methods:
 | 
			
		||||
  CefWindowHandle GetParentWindowHandle() const override;
 | 
			
		||||
  gfx::Point GetParentScreenPoint(const gfx::Point& view) const override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_BACKGROUND_H_
 | 
			
		||||
@@ -22,23 +22,29 @@ namespace cefimpl = extensions::cef;
 | 
			
		||||
 | 
			
		||||
#define EXTENSION_FUNCTION_NAME(classname) classname::function_name()
 | 
			
		||||
 | 
			
		||||
// Maintain the same order as https://developer.chrome.com/extensions/api_index
 | 
			
		||||
// so chrome://extensions-support looks nice.
 | 
			
		||||
const char* const kSupportedAPIs[] = {
 | 
			
		||||
    "resourcesPrivate",
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(ResourcesPrivateGetStringsFunction),
 | 
			
		||||
    "streamsPrivate",
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(StreamsPrivateAbortFunction),
 | 
			
		||||
    "tabs",
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsExecuteScriptFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsInsertCSSFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsGetZoomFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomSettingsFunction),
 | 
			
		||||
    EXTENSION_FUNCTION_NAME(cefimpl::TabsGetZoomSettingsFunction),
 | 
			
		||||
    nullptr,  // Indicates end of array.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Only add APIs to this list that have been tested in CEF.
 | 
			
		||||
// static
 | 
			
		||||
bool ChromeFunctionRegistry::IsSupported(const std::string& name) {
 | 
			
		||||
  static const char* const supported_apis[] = {
 | 
			
		||||
      "resourcesPrivate",
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(ResourcesPrivateGetStringsFunction),
 | 
			
		||||
      "streamsPrivate",
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(StreamsPrivateAbortFunction),
 | 
			
		||||
      "tabs",
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomFunction),
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(cefimpl::TabsGetZoomFunction),
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomSettingsFunction),
 | 
			
		||||
      EXTENSION_FUNCTION_NAME(cefimpl::TabsGetZoomSettingsFunction),
 | 
			
		||||
  };
 | 
			
		||||
  for (size_t i = 0; i < arraysize(supported_apis); ++i) {
 | 
			
		||||
    if (name == supported_apis[i])
 | 
			
		||||
  for (size_t i = 0; kSupportedAPIs[i] != nullptr; ++i) {
 | 
			
		||||
    if (name == kSupportedAPIs[i])
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
@@ -49,6 +55,8 @@ bool ChromeFunctionRegistry::IsSupported(const std::string& name) {
 | 
			
		||||
void ChromeFunctionRegistry::RegisterAll(ExtensionFunctionRegistry* registry) {
 | 
			
		||||
  registry->RegisterFunction<ResourcesPrivateGetStringsFunction>();
 | 
			
		||||
  registry->RegisterFunction<StreamsPrivateAbortFunction>();
 | 
			
		||||
  registry->RegisterFunction<cefimpl::TabsExecuteScriptFunction>();
 | 
			
		||||
  registry->RegisterFunction<cefimpl::TabsInsertCSSFunction>();
 | 
			
		||||
  registry->RegisterFunction<cefimpl::TabsGetFunction>();
 | 
			
		||||
  registry->RegisterFunction<cefimpl::TabsSetZoomFunction>();
 | 
			
		||||
  registry->RegisterFunction<cefimpl::TabsGetZoomFunction>();
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,9 @@ namespace extensions {
 | 
			
		||||
namespace api {
 | 
			
		||||
namespace cef {
 | 
			
		||||
 | 
			
		||||
// Array of currently supported APIs.
 | 
			
		||||
extern const char* const kSupportedAPIs[];
 | 
			
		||||
 | 
			
		||||
class ChromeFunctionRegistry {
 | 
			
		||||
 public:
 | 
			
		||||
  static bool IsSupported(const std::string& name);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								libcef/browser/extensions/extension_background_host.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libcef/browser/extensions/extension_background_host.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2013 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extension_background_host.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_host_delegate.h"
 | 
			
		||||
 | 
			
		||||
#include "base/callback.h"
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
CefExtensionBackgroundHost::CefExtensionBackgroundHost(
 | 
			
		||||
    CefBrowserHostImpl* browser,
 | 
			
		||||
    base::OnceClosure deleted_callback,
 | 
			
		||||
    const Extension* extension,
 | 
			
		||||
    content::BrowserContext* browser_context,
 | 
			
		||||
    content::WebContents* host_contents,
 | 
			
		||||
    const GURL& url,
 | 
			
		||||
    ViewType host_type)
 | 
			
		||||
    : ExtensionHost(new CefExtensionHostDelegate(browser),
 | 
			
		||||
                    extension,
 | 
			
		||||
                    browser_context,
 | 
			
		||||
                    host_contents,
 | 
			
		||||
                    url,
 | 
			
		||||
                    host_type),
 | 
			
		||||
      deleted_callback_(std::move(deleted_callback)) {
 | 
			
		||||
  DCHECK(!deleted_callback_.is_null());
 | 
			
		||||
 | 
			
		||||
  // Only used for background pages.
 | 
			
		||||
  DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefExtensionBackgroundHost::~CefExtensionBackgroundHost() {
 | 
			
		||||
  std::move(deleted_callback_).Run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionBackgroundHost::ShouldTransferNavigation(
 | 
			
		||||
    bool is_main_frame_navigation) {
 | 
			
		||||
  // Block navigations that cause the main frame to navigate to non-extension
 | 
			
		||||
  // content (i.e. to web content).
 | 
			
		||||
  return !is_main_frame_navigation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
							
								
								
									
										48
									
								
								libcef/browser/extensions/extension_background_host.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								libcef/browser/extensions/extension_background_host.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2013 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_BACKGROUND_HOST_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_BACKGROUND_HOST_H_
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "base/callback_forward.h"
 | 
			
		||||
#include "base/macros.h"
 | 
			
		||||
#include "extensions/browser/extension_host.h"
 | 
			
		||||
 | 
			
		||||
class CefBrowserHostImpl;
 | 
			
		||||
 | 
			
		||||
namespace content {
 | 
			
		||||
class WebContents;
 | 
			
		||||
}  // namespace content
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
// The ExtensionHost for a background page. This is a thin wrapper around the
 | 
			
		||||
// ExtensionHost base class to support CEF-specific constructor. Object lifespan
 | 
			
		||||
// is managed by ProcessManager.
 | 
			
		||||
class CefExtensionBackgroundHost : public ExtensionHost {
 | 
			
		||||
 public:
 | 
			
		||||
  CefExtensionBackgroundHost(CefBrowserHostImpl* browser,
 | 
			
		||||
                             base::OnceClosure deleted_callback,
 | 
			
		||||
                             const Extension* extension,
 | 
			
		||||
                             content::BrowserContext* browser_context,
 | 
			
		||||
                             content::WebContents* host_contents,
 | 
			
		||||
                             const GURL& url,
 | 
			
		||||
                             ViewType host_type);
 | 
			
		||||
  ~CefExtensionBackgroundHost() override;
 | 
			
		||||
 | 
			
		||||
  // content::WebContentsDelegate methods:
 | 
			
		||||
  bool ShouldTransferNavigation(bool is_main_frame_navigation) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // Callback that will be executed on host deletion.
 | 
			
		||||
  base::OnceClosure deleted_callback_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionBackgroundHost);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 | 
			
		||||
#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_BACKGROUND_HOST_H_
 | 
			
		||||
							
								
								
									
										291
									
								
								libcef/browser/extensions/extension_function_details.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								libcef/browser/extensions/extension_function_details.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,291 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2014 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extension_function_details.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_context_impl.h"
 | 
			
		||||
#include "libcef/browser/extensions/browser_extensions_util.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_system.h"
 | 
			
		||||
#include "libcef/browser/thread_util.h"
 | 
			
		||||
 | 
			
		||||
#include "base/task_scheduler/post_task.h"
 | 
			
		||||
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 | 
			
		||||
#include "chrome/browser/profiles/profile.h"
 | 
			
		||||
#include "extensions/browser/extension_function.h"
 | 
			
		||||
#include "extensions/browser/extension_function_dispatcher.h"
 | 
			
		||||
#include "extensions/common/error_utils.h"
 | 
			
		||||
 | 
			
		||||
using content::WebContents;
 | 
			
		||||
using content::RenderViewHost;
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
namespace keys = extensions::tabs_constants;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
class CefGetExtensionLoadFileCallbackImpl
 | 
			
		||||
    : public CefGetExtensionResourceCallback {
 | 
			
		||||
 public:
 | 
			
		||||
  CefGetExtensionLoadFileCallbackImpl(
 | 
			
		||||
      const std::string& file,
 | 
			
		||||
      CefExtensionFunctionDetails::LoadFileCallback callback)
 | 
			
		||||
      : file_(file), callback_(std::move(callback)) {}
 | 
			
		||||
 | 
			
		||||
  ~CefGetExtensionLoadFileCallbackImpl() {
 | 
			
		||||
    if (!callback_.is_null()) {
 | 
			
		||||
      // The callback is still pending. Cancel it now.
 | 
			
		||||
      if (CEF_CURRENTLY_ON_UIT()) {
 | 
			
		||||
        RunNow(file_, std::move(callback_), nullptr);
 | 
			
		||||
      } else {
 | 
			
		||||
        CEF_POST_TASK(
 | 
			
		||||
            CEF_UIT,
 | 
			
		||||
            base::BindOnce(&CefGetExtensionLoadFileCallbackImpl::RunNow, file_,
 | 
			
		||||
                           base::Passed(std::move(callback_)), nullptr));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Continue(CefRefPtr<CefStreamReader> stream) override {
 | 
			
		||||
    if (CEF_CURRENTLY_ON_UIT()) {
 | 
			
		||||
      if (!callback_.is_null()) {
 | 
			
		||||
        // Always continue asynchronously.
 | 
			
		||||
        CEF_POST_TASK(
 | 
			
		||||
            CEF_UIT,
 | 
			
		||||
            base::BindOnce(&CefGetExtensionLoadFileCallbackImpl::RunNow, file_,
 | 
			
		||||
                           base::Passed(std::move(callback_)), stream));
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      CEF_POST_TASK(CEF_UIT, base::BindOnce(
 | 
			
		||||
                                 &CefGetExtensionLoadFileCallbackImpl::Continue,
 | 
			
		||||
                                 this, stream));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Cancel() override { Continue(nullptr); }
 | 
			
		||||
 | 
			
		||||
  void Disconnect() { callback_.Reset(); }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  static void RunNow(const std::string& file,
 | 
			
		||||
                     CefExtensionFunctionDetails::LoadFileCallback callback,
 | 
			
		||||
                     CefRefPtr<CefStreamReader> stream) {
 | 
			
		||||
    CEF_REQUIRE_UIT();
 | 
			
		||||
 | 
			
		||||
    if (!stream) {
 | 
			
		||||
      std::move(callback).Run(nullptr);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    base::PostTaskWithTraitsAndReplyWithResult(
 | 
			
		||||
        FROM_HERE,
 | 
			
		||||
        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
 | 
			
		||||
        base::BindOnce(LoadFileFromStream, file, stream), std::move(callback));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static std::unique_ptr<std::string> LoadFileFromStream(
 | 
			
		||||
      const std::string& file,
 | 
			
		||||
      CefRefPtr<CefStreamReader> stream) {
 | 
			
		||||
    base::ThreadRestrictions::AssertIOAllowed();
 | 
			
		||||
 | 
			
		||||
    // Move to the end of the stream.
 | 
			
		||||
    stream->Seek(0, SEEK_END);
 | 
			
		||||
    const int64 size = stream->Tell();
 | 
			
		||||
    if (size == 0) {
 | 
			
		||||
      LOG(WARNING) << "Extension resource " << file << " is empty.";
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<std::string> result(new std::string());
 | 
			
		||||
    result->resize(size);
 | 
			
		||||
 | 
			
		||||
    // Move to the beginning of the stream.
 | 
			
		||||
    stream->Seek(0, SEEK_SET);
 | 
			
		||||
 | 
			
		||||
    // Read all stream contents into the string.
 | 
			
		||||
    int64 read, offset = 0;
 | 
			
		||||
    do {
 | 
			
		||||
      read =
 | 
			
		||||
          static_cast<int>(stream->Read(&(*result)[offset], 1, size - offset));
 | 
			
		||||
      offset += read;
 | 
			
		||||
    } while (read > 0 && offset < size);
 | 
			
		||||
 | 
			
		||||
    if (offset != size) {
 | 
			
		||||
      LOG(WARNING) << "Extension resource " << file << " read failed; expected "
 | 
			
		||||
                   << size << ", got " << offset << " bytes.";
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const std::string file_;
 | 
			
		||||
  CefExtensionFunctionDetails::LoadFileCallback callback_;
 | 
			
		||||
 | 
			
		||||
  IMPLEMENT_REFCOUNTING(CefGetExtensionLoadFileCallbackImpl);
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefGetExtensionLoadFileCallbackImpl);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
CefExtensionFunctionDetails::CefExtensionFunctionDetails(
 | 
			
		||||
    UIThreadExtensionFunction* function)
 | 
			
		||||
    : function_(function) {}
 | 
			
		||||
 | 
			
		||||
CefExtensionFunctionDetails::~CefExtensionFunctionDetails() {}
 | 
			
		||||
 | 
			
		||||
Profile* CefExtensionFunctionDetails::GetProfile() const {
 | 
			
		||||
  return Profile::FromBrowserContext(function_->browser_context());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl> CefExtensionFunctionDetails::GetSenderBrowser()
 | 
			
		||||
    const {
 | 
			
		||||
  content::WebContents* web_contents = function_->GetSenderWebContents();
 | 
			
		||||
  if (web_contents)
 | 
			
		||||
    return CefBrowserHostImpl::GetBrowserForContents(web_contents);
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl> CefExtensionFunctionDetails::GetCurrentBrowser()
 | 
			
		||||
    const {
 | 
			
		||||
  // Start with the browser hosting the extension.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
 | 
			
		||||
  if (browser && browser->client()) {
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler = GetCefExtension()->GetHandler();
 | 
			
		||||
    if (handler) {
 | 
			
		||||
      // Give the handler an opportunity to specify a different browser.
 | 
			
		||||
      CefRefPtr<CefBrowser> active_browser = handler->GetActiveBrowser(
 | 
			
		||||
          GetCefExtension(), browser.get(), function_->include_incognito());
 | 
			
		||||
      if (active_browser && active_browser != browser) {
 | 
			
		||||
        CefRefPtr<CefBrowserHostImpl> active_browser_impl =
 | 
			
		||||
            static_cast<CefBrowserHostImpl*>(active_browser.get());
 | 
			
		||||
 | 
			
		||||
        // Make sure we're operating in the same BrowserContextImpl.
 | 
			
		||||
        if (CefBrowserContextImpl::GetForContext(
 | 
			
		||||
                browser->GetBrowserContext()) ==
 | 
			
		||||
            CefBrowserContextImpl::GetForContext(
 | 
			
		||||
                active_browser_impl->GetBrowserContext())) {
 | 
			
		||||
          browser = active_browser_impl;
 | 
			
		||||
        } else {
 | 
			
		||||
          LOG(WARNING) << "Browser with tabId "
 | 
			
		||||
                       << active_browser->GetIdentifier()
 | 
			
		||||
                       << " cannot be accessed because is uses a different "
 | 
			
		||||
                          "CefRequestContext";
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // May be null during startup/shutdown.
 | 
			
		||||
  return browser;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionFunctionDetails::CanAccessBrowser(
 | 
			
		||||
    CefRefPtr<CefBrowserHostImpl> target) const {
 | 
			
		||||
  DCHECK(target);
 | 
			
		||||
 | 
			
		||||
  // Start with the browser hosting the extension.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
 | 
			
		||||
  if (browser == target) {
 | 
			
		||||
    // A sender can always access itself.
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (browser && browser->client()) {
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler = GetCefExtension()->GetHandler();
 | 
			
		||||
    if (handler) {
 | 
			
		||||
      return handler->CanAccessBrowser(GetCefExtension(), browser.get(),
 | 
			
		||||
                                       function_->include_incognito(), target);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Default to allowing access.
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl>
 | 
			
		||||
CefExtensionFunctionDetails::GetBrowserForTabIdFirstTime(
 | 
			
		||||
    int tab_id,
 | 
			
		||||
    std::string* error_message) const {
 | 
			
		||||
  DCHECK_GE(tab_id, -1);
 | 
			
		||||
  DCHECK(!get_browser_called_first_time_);
 | 
			
		||||
  get_browser_called_first_time_ = true;
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser;
 | 
			
		||||
 | 
			
		||||
  if (tab_id != -1) {
 | 
			
		||||
    // May be an invalid tabId or in the wrong BrowserContext.
 | 
			
		||||
    browser = GetBrowserForTabId(tab_id, function_->browser_context());
 | 
			
		||||
    if (!browser || !browser->web_contents() || !CanAccessBrowser(browser)) {
 | 
			
		||||
      if (error_message) {
 | 
			
		||||
        *error_message = ErrorUtils::FormatErrorMessage(
 | 
			
		||||
            keys::kTabNotFoundError, base::IntToString(tab_id));
 | 
			
		||||
      }
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // May return NULL during shutdown.
 | 
			
		||||
    browser = GetCurrentBrowser();
 | 
			
		||||
    if (!browser || !browser->web_contents()) {
 | 
			
		||||
      if (error_message) {
 | 
			
		||||
        *error_message = keys::kNoCurrentWindowError;
 | 
			
		||||
      }
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return browser;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefBrowserHostImpl>
 | 
			
		||||
CefExtensionFunctionDetails::GetBrowserForTabIdAgain(
 | 
			
		||||
    int tab_id,
 | 
			
		||||
    std::string* error_message) const {
 | 
			
		||||
  DCHECK_GE(tab_id, 0);
 | 
			
		||||
  DCHECK(get_browser_called_first_time_);
 | 
			
		||||
 | 
			
		||||
  // May return NULL during shutdown.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      GetBrowserForTabId(tab_id, function_->browser_context());
 | 
			
		||||
  if (!browser || !browser->web_contents()) {
 | 
			
		||||
    if (error_message) {
 | 
			
		||||
      *error_message = ErrorUtils::FormatErrorMessage(
 | 
			
		||||
          keys::kTabNotFoundError, base::IntToString(tab_id));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return browser;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionFunctionDetails::LoadFile(const std::string& file,
 | 
			
		||||
                                           LoadFileCallback callback) const {
 | 
			
		||||
  // Start with the browser hosting the extension.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
 | 
			
		||||
  if (browser && browser->client()) {
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler = GetCefExtension()->GetHandler();
 | 
			
		||||
    if (handler) {
 | 
			
		||||
      CefRefPtr<CefGetExtensionLoadFileCallbackImpl> cef_callback(
 | 
			
		||||
          new CefGetExtensionLoadFileCallbackImpl(file, std::move(callback)));
 | 
			
		||||
      if (handler->GetExtensionResource(GetCefExtension(), browser.get(), file,
 | 
			
		||||
                                        cef_callback)) {
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
      cef_callback->Disconnect();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefExtension> CefExtensionFunctionDetails::GetCefExtension() const {
 | 
			
		||||
  if (!cef_extension_) {
 | 
			
		||||
    cef_extension_ =
 | 
			
		||||
        static_cast<CefBrowserContext*>(function_->browser_context())
 | 
			
		||||
            ->extension_system()
 | 
			
		||||
            ->GetExtension(function_->extension_id());
 | 
			
		||||
    DCHECK(cef_extension_);
 | 
			
		||||
  }
 | 
			
		||||
  return cef_extension_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
							
								
								
									
										114
									
								
								libcef/browser/extensions/extension_function_details.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								libcef/browser/extensions/extension_function_details.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2014 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_DETAILS_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_DETAILS_H_
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
 | 
			
		||||
#include "include/cef_extension.h"
 | 
			
		||||
 | 
			
		||||
#include "base/callback_forward.h"
 | 
			
		||||
#include "base/macros.h"
 | 
			
		||||
#include "ui/gfx/native_widget_types.h"
 | 
			
		||||
 | 
			
		||||
class Profile;
 | 
			
		||||
class UIThreadExtensionFunction;
 | 
			
		||||
 | 
			
		||||
namespace content {
 | 
			
		||||
class WebContents;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
// Provides CEF-specific details to UIThreadExtensionFunction implementations.
 | 
			
		||||
// Based on chrome/browser/extensions/chrome_extension_function_details.h.
 | 
			
		||||
class CefExtensionFunctionDetails {
 | 
			
		||||
 public:
 | 
			
		||||
  // Constructs a new ChromeExtensionFunctionDetails instance for |function|.
 | 
			
		||||
  // This instance does not own |function| and must outlive it.
 | 
			
		||||
  explicit CefExtensionFunctionDetails(UIThreadExtensionFunction* function);
 | 
			
		||||
  ~CefExtensionFunctionDetails();
 | 
			
		||||
 | 
			
		||||
  Profile* GetProfile() const;
 | 
			
		||||
 | 
			
		||||
  // Get the "sender" browser that is hosting the extension. May return NULL
 | 
			
		||||
  // during startup/shutdown.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> GetSenderBrowser() const;
 | 
			
		||||
 | 
			
		||||
  // Get the "current" browser that will be acted on by this extension function,
 | 
			
		||||
  // if any. When mapping from a tabId use the GetBrowserForTabId* methods
 | 
			
		||||
  // instead of calling this method directly.
 | 
			
		||||
  //
 | 
			
		||||
  // Many extension APIs operate relative to the browser that the calling code
 | 
			
		||||
  // is running inside of. For example, popups and tabs all have a containing
 | 
			
		||||
  // browser, but background pages and notification bubbles do not. Other APIs,
 | 
			
		||||
  // like chrome.tabs.*, can act on either a specific browser (specified via the
 | 
			
		||||
  // tabId parameter) or should allow the client to determine the most
 | 
			
		||||
  // appropriate browser (for example, the browser that representing the
 | 
			
		||||
  // foreground window).
 | 
			
		||||
  //
 | 
			
		||||
  // Incognito browsers should not be considered unless the calling extension
 | 
			
		||||
  // has incognito access enabled. CEF does not internally enforce incognito
 | 
			
		||||
  // status so we pass this flag to client callbacks for consideration.
 | 
			
		||||
  //
 | 
			
		||||
  // This method can return NULL if there is no matching browser, which can
 | 
			
		||||
  // happen if only incognito windows are open, or early in startup or shutdown
 | 
			
		||||
  // shutdown when there are no active windows.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> GetCurrentBrowser() const;
 | 
			
		||||
 | 
			
		||||
  // Returns true if the sender browser can access |target|. When mapping from a
 | 
			
		||||
  // tabId use the GetBrowserForTabId* methods instead of calling this method
 | 
			
		||||
  // directly.
 | 
			
		||||
  bool CanAccessBrowser(CefRefPtr<CefBrowserHostImpl> target) const;
 | 
			
		||||
 | 
			
		||||
  // Returns the browser matching |tab_id| or NULL if the browser cannot be
 | 
			
		||||
  // found or does not have a WebContents. If |tab_id| is -1 the "current"
 | 
			
		||||
  // browser will be returned. |error_message| can optionally be passed in and
 | 
			
		||||
  // will be set with an appropriate message on error. This method should only
 | 
			
		||||
  // be called one time per extension function and will check all necessary
 | 
			
		||||
  // client permissions.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> GetBrowserForTabIdFirstTime(
 | 
			
		||||
      int tab_id,
 | 
			
		||||
      std::string* error_message) const;
 | 
			
		||||
 | 
			
		||||
  // Returns the browser matching |tab_id| or NULL if the browser cannot be
 | 
			
		||||
  // found or does not have a WebContents. |tab_id| must be >= 0.
 | 
			
		||||
  // |error_message| can optionally be passed in and will be set with an
 | 
			
		||||
  // appropriate message on error. This method should be called only after
 | 
			
		||||
  // GetBrowserForTabIdFirstTime() has succeeded for the same |tab_id|.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> GetBrowserForTabIdAgain(
 | 
			
		||||
      int tab_id,
 | 
			
		||||
      std::string* error_message) const;
 | 
			
		||||
 | 
			
		||||
  // Give the client a chance to handle |file|. |callback| will be executed
 | 
			
		||||
  // once the file contents have been loaded. Returns false if the file is
 | 
			
		||||
  // unhandled.
 | 
			
		||||
  using LoadFileCallback =
 | 
			
		||||
      base::OnceCallback<void(std::unique_ptr<std::string>)>;
 | 
			
		||||
  bool LoadFile(const std::string& file, LoadFileCallback callback) const;
 | 
			
		||||
 | 
			
		||||
  // Returns a pointer to the associated UIThreadExtensionFunction
 | 
			
		||||
  UIThreadExtensionFunction* function() { return function_; }
 | 
			
		||||
  const UIThreadExtensionFunction* function() const { return function_; }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  CefRefPtr<CefExtension> GetCefExtension() const;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // The function for which these details have been created. Must outlive the
 | 
			
		||||
  // CefExtensionFunctionDetails instance.
 | 
			
		||||
  UIThreadExtensionFunction* function_;
 | 
			
		||||
 | 
			
		||||
  mutable CefRefPtr<CefExtension> cef_extension_;
 | 
			
		||||
 | 
			
		||||
  // Verifies correct usage of GetBrowserForTabId* methods.
 | 
			
		||||
  mutable bool get_browser_called_first_time_ = false;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionFunctionDetails);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 | 
			
		||||
#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_DETAILS_H_
 | 
			
		||||
							
								
								
									
										63
									
								
								libcef/browser/extensions/extension_host_delegate.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								libcef/browser/extensions/extension_host_delegate.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2014 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extension_host_delegate.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extensions_browser_client.h"
 | 
			
		||||
 | 
			
		||||
#include "base/logging.h"
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
CefExtensionHostDelegate::CefExtensionHostDelegate(
 | 
			
		||||
    CefBrowserHostImpl* browser) {}
 | 
			
		||||
 | 
			
		||||
CefExtensionHostDelegate::~CefExtensionHostDelegate() {}
 | 
			
		||||
 | 
			
		||||
void CefExtensionHostDelegate::OnExtensionHostCreated(
 | 
			
		||||
    content::WebContents* web_contents) {}
 | 
			
		||||
 | 
			
		||||
void CefExtensionHostDelegate::OnRenderViewCreatedForBackgroundPage(
 | 
			
		||||
    ExtensionHost* host) {}
 | 
			
		||||
 | 
			
		||||
content::JavaScriptDialogManager*
 | 
			
		||||
CefExtensionHostDelegate::GetJavaScriptDialogManager() {
 | 
			
		||||
  // Never routed here from CefBrowserHostImpl.
 | 
			
		||||
  NOTREACHED();
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionHostDelegate::CreateTab(content::WebContents* web_contents,
 | 
			
		||||
                                         const std::string& extension_id,
 | 
			
		||||
                                         WindowOpenDisposition disposition,
 | 
			
		||||
                                         const gfx::Rect& initial_rect,
 | 
			
		||||
                                         bool user_gesture) {
 | 
			
		||||
  // TODO(cef): Add support for extensions opening popup windows.
 | 
			
		||||
  NOTIMPLEMENTED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionHostDelegate::ProcessMediaAccessRequest(
 | 
			
		||||
    content::WebContents* web_contents,
 | 
			
		||||
    const content::MediaStreamRequest& request,
 | 
			
		||||
    const content::MediaResponseCallback& callback,
 | 
			
		||||
    const Extension* extension) {
 | 
			
		||||
  // Never routed here from CefBrowserHostImpl.
 | 
			
		||||
  NOTREACHED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionHostDelegate::CheckMediaAccessPermission(
 | 
			
		||||
    content::WebContents* web_contents,
 | 
			
		||||
    const GURL& security_origin,
 | 
			
		||||
    content::MediaStreamType type,
 | 
			
		||||
    const Extension* extension) {
 | 
			
		||||
  // Never routed here from CefBrowserHostImpl.
 | 
			
		||||
  NOTREACHED();
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ExtensionHostQueue* CefExtensionHostDelegate::GetExtensionHostQueue() const {
 | 
			
		||||
  return CefExtensionsBrowserClient::Get()->GetExtensionHostQueue();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
							
								
								
									
										45
									
								
								libcef/browser/extensions/extension_host_delegate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								libcef/browser/extensions/extension_host_delegate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2014 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCEF_BROWSER_EXTENSIONS_EXTENSION_HOST_DELEGATE_H_
 | 
			
		||||
#define LIBCEF_BROWSER_EXTENSIONS_EXTENSION_HOST_DELEGATE_H_
 | 
			
		||||
 | 
			
		||||
#include "base/macros.h"
 | 
			
		||||
#include "extensions/browser/extension_host_delegate.h"
 | 
			
		||||
 | 
			
		||||
class CefBrowserHostImpl;
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
class CefExtensionHostDelegate : public ExtensionHostDelegate {
 | 
			
		||||
 public:
 | 
			
		||||
  explicit CefExtensionHostDelegate(CefBrowserHostImpl* browser);
 | 
			
		||||
  ~CefExtensionHostDelegate() override;
 | 
			
		||||
 | 
			
		||||
  // ExtensionHostDelegate implementation.
 | 
			
		||||
  void OnExtensionHostCreated(content::WebContents* web_contents) override;
 | 
			
		||||
  void OnRenderViewCreatedForBackgroundPage(ExtensionHost* host) override;
 | 
			
		||||
  content::JavaScriptDialogManager* GetJavaScriptDialogManager() override;
 | 
			
		||||
  void CreateTab(content::WebContents* web_contents,
 | 
			
		||||
                 const std::string& extension_id,
 | 
			
		||||
                 WindowOpenDisposition disposition,
 | 
			
		||||
                 const gfx::Rect& initial_rect,
 | 
			
		||||
                 bool user_gesture) override;
 | 
			
		||||
  void ProcessMediaAccessRequest(content::WebContents* web_contents,
 | 
			
		||||
                                 const content::MediaStreamRequest& request,
 | 
			
		||||
                                 const content::MediaResponseCallback& callback,
 | 
			
		||||
                                 const Extension* extension) override;
 | 
			
		||||
  bool CheckMediaAccessPermission(content::WebContents* web_contents,
 | 
			
		||||
                                  const GURL& security_origin,
 | 
			
		||||
                                  content::MediaStreamType type,
 | 
			
		||||
                                  const Extension* extension) override;
 | 
			
		||||
  ExtensionHostQueue* GetExtensionHostQueue() const override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionHostDelegate);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 | 
			
		||||
#endif  // LIBCEF_BROWSER_EXTENSIONS_EXTENSION_HOST_DELEGATE_H_
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extension_impl.h"
 | 
			
		||||
#include "libcef/browser/extensions/pdf_extension_util.h"
 | 
			
		||||
#include "libcef/browser/thread_util.h"
 | 
			
		||||
#include "libcef/common/extensions/extensions_util.h"
 | 
			
		||||
 | 
			
		||||
#include "base/command_line.h"
 | 
			
		||||
@@ -17,6 +19,7 @@
 | 
			
		||||
#include "base/path_service.h"
 | 
			
		||||
#include "base/strings/string_tokenizer.h"
 | 
			
		||||
#include "base/strings/utf_string_conversions.h"
 | 
			
		||||
#include "base/task_scheduler/post_task.h"
 | 
			
		||||
#include "base/threading/thread_restrictions.h"
 | 
			
		||||
#include "chrome/common/chrome_paths.h"
 | 
			
		||||
#include "components/crx_file/id_util.h"
 | 
			
		||||
@@ -53,18 +56,9 @@ namespace extensions {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
std::string GenerateId(const base::DictionaryValue* manifest,
 | 
			
		||||
                       const base::FilePath& path) {
 | 
			
		||||
  std::string raw_key;
 | 
			
		||||
  std::string id_input;
 | 
			
		||||
  CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
 | 
			
		||||
  CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
 | 
			
		||||
  std::string id = crx_file::id_util::GenerateId(id_input);
 | 
			
		||||
  return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation based on ComponentLoader::ParseManifest.
 | 
			
		||||
base::DictionaryValue* ParseManifest(const std::string& manifest_contents) {
 | 
			
		||||
std::unique_ptr<base::DictionaryValue> ParseManifest(
 | 
			
		||||
    const std::string& manifest_contents) {
 | 
			
		||||
  JSONStringValueDeserializer deserializer(manifest_contents);
 | 
			
		||||
  std::unique_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +67,81 @@ base::DictionaryValue* ParseManifest(const std::string& manifest_contents) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  // Transfer ownership to the caller.
 | 
			
		||||
  return static_cast<base::DictionaryValue*>(manifest.release());
 | 
			
		||||
  return base::WrapUnique(
 | 
			
		||||
      static_cast<base::DictionaryValue*>(manifest.release()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExecuteLoadFailure(CefRefPtr<CefExtensionHandler> handler,
 | 
			
		||||
                        cef_errorcode_t result) {
 | 
			
		||||
  if (!handler)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
			
		||||
    CEF_POST_TASK(CEF_UIT, base::BindOnce(ExecuteLoadFailure, handler, result));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handler->OnExtensionLoadFailed(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LoadExtensionOnUIThread(base::WeakPtr<CefExtensionSystem> context,
 | 
			
		||||
                             std::unique_ptr<base::DictionaryValue> manifest,
 | 
			
		||||
                             const base::FilePath& root_directory,
 | 
			
		||||
                             bool internal,
 | 
			
		||||
                             CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                             CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  if (!CEF_CURRENTLY_ON_UIT()) {
 | 
			
		||||
    CEF_POST_TASK(CEF_UIT, base::BindOnce(LoadExtensionOnUIThread, context,
 | 
			
		||||
                                          base::Passed(std::move(manifest)),
 | 
			
		||||
                                          root_directory, internal,
 | 
			
		||||
                                          loader_context, handler));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (context) {
 | 
			
		||||
    context->LoadExtension(std::move(manifest), root_directory, internal,
 | 
			
		||||
                           loader_context, handler);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LoadExtensionWithManifest(base::WeakPtr<CefExtensionSystem> context,
 | 
			
		||||
                               const std::string& manifest_contents,
 | 
			
		||||
                               const base::FilePath& root_directory,
 | 
			
		||||
                               bool internal,
 | 
			
		||||
                               CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                               CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  base::ThreadRestrictions::AssertIOAllowed();
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<base::DictionaryValue> manifest =
 | 
			
		||||
      ParseManifest(manifest_contents);
 | 
			
		||||
  if (!manifest) {
 | 
			
		||||
    LOG(WARNING) << "Failed to parse extension manifest";
 | 
			
		||||
    ExecuteLoadFailure(handler, ERR_INVALID_ARGUMENT);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  LoadExtensionOnUIThread(context, std::move(manifest), root_directory,
 | 
			
		||||
                          internal, loader_context, handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LoadExtensionFromDisk(base::WeakPtr<CefExtensionSystem> context,
 | 
			
		||||
                           const base::FilePath& root_directory,
 | 
			
		||||
                           bool internal,
 | 
			
		||||
                           CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                           CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  base::ThreadRestrictions::AssertIOAllowed();
 | 
			
		||||
 | 
			
		||||
  base::FilePath manifest_path = root_directory.AppendASCII("manifest.json");
 | 
			
		||||
  std::string manifest_contents;
 | 
			
		||||
  if (!base::ReadFileToString(manifest_path, &manifest_contents)) {
 | 
			
		||||
    LOG(WARNING) << "Failed to read extension manifest from "
 | 
			
		||||
                 << manifest_path.MaybeAsASCII();
 | 
			
		||||
    ExecuteLoadFailure(handler, ERR_FILE_NOT_FOUND);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  LoadExtensionWithManifest(context, manifest_contents, root_directory,
 | 
			
		||||
                            internal, loader_context, handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
@@ -110,7 +178,7 @@ void CefExtensionSystem::Init() {
 | 
			
		||||
      content::Source<BrowserContext>(browser_context_),
 | 
			
		||||
      content::NotificationService::NoDetails());
 | 
			
		||||
 | 
			
		||||
  // Add the built-in PDF extension. PDF loading works as follows:
 | 
			
		||||
  // Add the internal PDF extension. PDF loading works as follows:
 | 
			
		||||
  // 1. PDF PPAPI plugin is registered to handle kPDFPluginOutOfProcessMimeType
 | 
			
		||||
  //    in libcef/common/content_client.cc ComputeBuiltInPlugins.
 | 
			
		||||
  // 2. PDF extension is registered and associated with the "application/pdf"
 | 
			
		||||
@@ -153,40 +221,139 @@ void CefExtensionSystem::Init() {
 | 
			
		||||
  //    CefExtensionWebContentsObserver::RenderViewCreated in the browser
 | 
			
		||||
  //    process.
 | 
			
		||||
  if (PdfExtensionEnabled()) {
 | 
			
		||||
    AddExtension(pdf_extension_util::GetManifest(),
 | 
			
		||||
                 base::FilePath(FILE_PATH_LITERAL("pdf")));
 | 
			
		||||
    LoadExtension(pdf_extension_util::GetManifest(),
 | 
			
		||||
                  base::FilePath(FILE_PATH_LITERAL("pdf")), true /* internal */,
 | 
			
		||||
                  nullptr, nullptr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  initialized_ = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation based on ComponentLoader::Add.
 | 
			
		||||
const Extension* CefExtensionSystem::AddExtension(
 | 
			
		||||
void CefExtensionSystem::LoadExtension(
 | 
			
		||||
    const base::FilePath& root_directory,
 | 
			
		||||
    bool internal,
 | 
			
		||||
    CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  base::PostTaskWithTraits(
 | 
			
		||||
      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
 | 
			
		||||
      base::BindOnce(LoadExtensionFromDisk, weak_ptr_factory_.GetWeakPtr(),
 | 
			
		||||
                     root_directory, internal, loader_context, handler));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionSystem::LoadExtension(
 | 
			
		||||
    const std::string& manifest_contents,
 | 
			
		||||
    const base::FilePath& root_directory) {
 | 
			
		||||
  base::DictionaryValue* manifest = ParseManifest(manifest_contents);
 | 
			
		||||
  if (!manifest)
 | 
			
		||||
    return NULL;
 | 
			
		||||
    const base::FilePath& root_directory,
 | 
			
		||||
    bool internal,
 | 
			
		||||
    CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  base::PostTaskWithTraits(
 | 
			
		||||
      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
 | 
			
		||||
      base::BindOnce(LoadExtensionWithManifest, weak_ptr_factory_.GetWeakPtr(),
 | 
			
		||||
                     manifest_contents, root_directory, internal,
 | 
			
		||||
                     loader_context, handler));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  ComponentExtensionInfo info(manifest, root_directory);
 | 
			
		||||
  const Extension* extension = LoadExtension(info);
 | 
			
		||||
  delete manifest;
 | 
			
		||||
// Implementation based on ComponentLoader::Add.
 | 
			
		||||
void CefExtensionSystem::LoadExtension(
 | 
			
		||||
    std::unique_ptr<base::DictionaryValue> manifest,
 | 
			
		||||
    const base::FilePath& root_directory,
 | 
			
		||||
    bool internal,
 | 
			
		||||
    CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
 | 
			
		||||
  return extension;
 | 
			
		||||
// Internal extensions don't have a loader context. External extensions should.
 | 
			
		||||
#if DCHECK_IS_ON()
 | 
			
		||||
  if (internal) {
 | 
			
		||||
    DCHECK(!loader_context);
 | 
			
		||||
  } else {
 | 
			
		||||
    DCHECK(loader_context);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ComponentExtensionInfo info(manifest.get(), root_directory, internal);
 | 
			
		||||
  const Extension* extension = LoadExtension(info, loader_context, handler);
 | 
			
		||||
  if (!extension)
 | 
			
		||||
    ExecuteLoadFailure(handler, ERR_FAILED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation based on ExtensionService::RemoveComponentExtension.
 | 
			
		||||
void CefExtensionSystem::RemoveExtension(const std::string& extension_id) {
 | 
			
		||||
bool CefExtensionSystem::UnloadExtension(const std::string& extension_id) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  ExtensionMap::iterator it = extension_map_.find(extension_id);
 | 
			
		||||
  if (it == extension_map_.end()) {
 | 
			
		||||
    // No CEF representation so we've already unloaded it.
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefExtensionImpl> cef_extension =
 | 
			
		||||
      static_cast<CefExtensionImpl*>(it->second.get());
 | 
			
		||||
 | 
			
		||||
  // Erase first so that callbacks can't retrieve the unloaded extension.
 | 
			
		||||
  extension_map_.erase(it);
 | 
			
		||||
 | 
			
		||||
  cef_extension->OnExtensionUnloaded();
 | 
			
		||||
 | 
			
		||||
  scoped_refptr<const Extension> extension(
 | 
			
		||||
      registry_->enabled_extensions().GetByID(extension_id));
 | 
			
		||||
      registry_->GetInstalledExtension(extension_id));
 | 
			
		||||
  UnloadExtension(extension_id, UnloadedExtensionReason::UNINSTALL);
 | 
			
		||||
  if (extension.get()) {
 | 
			
		||||
    registry_->TriggerOnUninstalled(
 | 
			
		||||
        extension.get(), extensions::UNINSTALL_REASON_COMPONENT_REMOVED);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionSystem::Shutdown() {}
 | 
			
		||||
bool CefExtensionSystem::HasExtension(const std::string& extension_id) const {
 | 
			
		||||
  return !!GetExtension(extension_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefRefPtr<CefExtension> CefExtensionSystem::GetExtension(
 | 
			
		||||
    const std::string& extension_id) const {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  ExtensionMap::const_iterator it = extension_map_.find(extension_id);
 | 
			
		||||
  if (it != extension_map_.end())
 | 
			
		||||
    return it->second;
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefExtensionSystem::ExtensionMap CefExtensionSystem::GetExtensions() const {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  return extension_map_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionSystem::OnRequestContextDeleted(CefRequestContext* context) {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
  DCHECK(context);
 | 
			
		||||
 | 
			
		||||
  // Make a copy of the map because UnloadExtension will modify it.
 | 
			
		||||
  // Don't add any references to |context|.
 | 
			
		||||
  ExtensionMap map = extension_map_;
 | 
			
		||||
  ExtensionMap::const_iterator it = map.begin();
 | 
			
		||||
  for (; it != map.end(); ++it) {
 | 
			
		||||
    CefRefPtr<CefExtensionImpl> cef_extension =
 | 
			
		||||
        static_cast<CefExtensionImpl*>(it->second.get());
 | 
			
		||||
    if (cef_extension->loader_context() == context)
 | 
			
		||||
      UnloadExtension(it->first);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionSystem::Shutdown() {
 | 
			
		||||
  CEF_REQUIRE_UIT();
 | 
			
		||||
// Only internal extensions should exist at this point.
 | 
			
		||||
#if DCHECK_IS_ON()
 | 
			
		||||
  ExtensionMap::iterator it = extension_map_.begin();
 | 
			
		||||
  for (; it != extension_map_.end(); ++it) {
 | 
			
		||||
    CefRefPtr<CefExtensionImpl> cef_extension =
 | 
			
		||||
        static_cast<CefExtensionImpl*>(it->second.get());
 | 
			
		||||
    DCHECK(!cef_extension->loader_context());
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  extension_map_.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
 | 
			
		||||
  DCHECK(!initialized_);
 | 
			
		||||
@@ -289,15 +456,15 @@ void CefExtensionSystem::InstallUpdate(const std::string& extension_id,
 | 
			
		||||
 | 
			
		||||
CefExtensionSystem::ComponentExtensionInfo::ComponentExtensionInfo(
 | 
			
		||||
    const base::DictionaryValue* manifest,
 | 
			
		||||
    const base::FilePath& directory)
 | 
			
		||||
    : manifest(manifest), root_directory(directory) {
 | 
			
		||||
    const base::FilePath& directory,
 | 
			
		||||
    bool internal)
 | 
			
		||||
    : manifest(manifest), root_directory(directory), internal(internal) {
 | 
			
		||||
  if (!root_directory.IsAbsolute()) {
 | 
			
		||||
    // This path structure is required by
 | 
			
		||||
    // url_request_util::MaybeCreateURLRequestResourceBundleJob.
 | 
			
		||||
    CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory));
 | 
			
		||||
    root_directory = root_directory.Append(directory);
 | 
			
		||||
  }
 | 
			
		||||
  extension_id = GenerateId(manifest, root_directory);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation based on ComponentLoader::CreateExtension.
 | 
			
		||||
@@ -306,24 +473,45 @@ scoped_refptr<const Extension> CefExtensionSystem::CreateExtension(
 | 
			
		||||
    std::string* utf8_error) {
 | 
			
		||||
  // TODO(abarth): We should REQUIRE_MODERN_MANIFEST_VERSION once we've updated
 | 
			
		||||
  //               our component extensions to the new manifest version.
 | 
			
		||||
  int flags = Extension::REQUIRE_KEY;
 | 
			
		||||
  return Extension::Create(info.root_directory, Manifest::COMPONENT,
 | 
			
		||||
                           *info.manifest, flags, utf8_error);
 | 
			
		||||
  int flags = 0;
 | 
			
		||||
  if (info.internal) {
 | 
			
		||||
    // Internal extensions must have kPublicKey in the manifest.
 | 
			
		||||
    flags |= Extension::REQUIRE_KEY;
 | 
			
		||||
  }
 | 
			
		||||
  return Extension::Create(
 | 
			
		||||
      info.root_directory,
 | 
			
		||||
      info.internal ? Manifest::COMPONENT : Manifest::COMMAND_LINE,
 | 
			
		||||
      *info.manifest, flags, utf8_error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implementation based on ComponentLoader::Load and
 | 
			
		||||
// ExtensionService::AddExtension.
 | 
			
		||||
const Extension* CefExtensionSystem::LoadExtension(
 | 
			
		||||
    const ComponentExtensionInfo& info) {
 | 
			
		||||
    const ComponentExtensionInfo& info,
 | 
			
		||||
    CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
    CefRefPtr<CefExtensionHandler> handler) {
 | 
			
		||||
  std::string error;
 | 
			
		||||
  scoped_refptr<const Extension> extension(CreateExtension(info, &error));
 | 
			
		||||
  if (!extension.get()) {
 | 
			
		||||
    LOG(ERROR) << error;
 | 
			
		||||
    return NULL;
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CHECK_EQ(info.extension_id, extension->id()) << extension->name();
 | 
			
		||||
  if (registry_->GetInstalledExtension(extension->id())) {
 | 
			
		||||
    LOG(ERROR) << "Extension with id " << extension->id()
 | 
			
		||||
               << "is already installed";
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefExtensionImpl> cef_extension =
 | 
			
		||||
      new CefExtensionImpl(extension.get(), loader_context.get(), handler);
 | 
			
		||||
 | 
			
		||||
  // Insert first so that callbacks can retrieve the loaded extension.
 | 
			
		||||
  extension_map_.insert(std::make_pair(extension->id(), cef_extension));
 | 
			
		||||
 | 
			
		||||
  cef_extension->OnExtensionLoaded();
 | 
			
		||||
 | 
			
		||||
  // This may trigger additional callbacks.
 | 
			
		||||
  registry_->AddEnabled(extension.get());
 | 
			
		||||
  NotifyExtensionLoaded(extension.get());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,11 @@
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_H_
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "include/cef_extension_handler.h"
 | 
			
		||||
#include "include/cef_request_context.h"
 | 
			
		||||
 | 
			
		||||
#include "base/compiler_specific.h"
 | 
			
		||||
#include "base/memory/weak_ptr.h"
 | 
			
		||||
@@ -16,8 +20,9 @@
 | 
			
		||||
class BrowserContextKeyedServiceFactory;
 | 
			
		||||
 | 
			
		||||
namespace base {
 | 
			
		||||
class DictionaryValue;
 | 
			
		||||
class FilePath;
 | 
			
		||||
}
 | 
			
		||||
}  // namespace base
 | 
			
		||||
 | 
			
		||||
namespace content {
 | 
			
		||||
class BrowserContext;
 | 
			
		||||
@@ -41,13 +46,43 @@ class CefExtensionSystem : public ExtensionSystem {
 | 
			
		||||
  // Initializes the extension system.
 | 
			
		||||
  void Init();
 | 
			
		||||
 | 
			
		||||
  // Add an extension. Returns the new Extension object on success or NULL on
 | 
			
		||||
  // failure.
 | 
			
		||||
  const Extension* AddExtension(const std::string& manifest_contents,
 | 
			
		||||
                                const base::FilePath& root_directory);
 | 
			
		||||
  // Load an extension. For internal (built-in) extensions set |internal| to
 | 
			
		||||
  // true and |loader_context| and |handler| to NULL. For external extensions
 | 
			
		||||
  // set |internal| to false and |loader_context| must be the request context
 | 
			
		||||
  // that loaded the extension. |handler| is optional for internal extensions
 | 
			
		||||
  // and, if specified, will receive extension-related callbacks.
 | 
			
		||||
  void LoadExtension(const base::FilePath& root_directory,
 | 
			
		||||
                     bool internal,
 | 
			
		||||
                     CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                     CefRefPtr<CefExtensionHandler> handler);
 | 
			
		||||
  void LoadExtension(const std::string& manifest_contents,
 | 
			
		||||
                     const base::FilePath& root_directory,
 | 
			
		||||
                     bool internal,
 | 
			
		||||
                     CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                     CefRefPtr<CefExtensionHandler> handler);
 | 
			
		||||
  void LoadExtension(std::unique_ptr<base::DictionaryValue> manifest,
 | 
			
		||||
                     const base::FilePath& root_directory,
 | 
			
		||||
                     bool internal,
 | 
			
		||||
                     CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                     CefRefPtr<CefExtensionHandler> handler);
 | 
			
		||||
 | 
			
		||||
  // Remove an extension.
 | 
			
		||||
  void RemoveExtension(const std::string& extension_id);
 | 
			
		||||
  // Unload the external extension identified by |extension_id|.
 | 
			
		||||
  bool UnloadExtension(const std::string& extension_id);
 | 
			
		||||
 | 
			
		||||
  // Returns true if an extension matching |extension_id| is loaded.
 | 
			
		||||
  bool HasExtension(const std::string& extension_id) const;
 | 
			
		||||
 | 
			
		||||
  // Returns the loaded extention matching |extension_id| or NULL if not found.
 | 
			
		||||
  CefRefPtr<CefExtension> GetExtension(const std::string& extension_id) const;
 | 
			
		||||
 | 
			
		||||
  using ExtensionMap = std::map<std::string, CefRefPtr<CefExtension>>;
 | 
			
		||||
 | 
			
		||||
  // Returns the map of all loaded extensions.
 | 
			
		||||
  ExtensionMap GetExtensions() const;
 | 
			
		||||
 | 
			
		||||
  // Called when a request context is deleted. Unregisters any external
 | 
			
		||||
  // extensions that were registered with this context.
 | 
			
		||||
  void OnRequestContextDeleted(CefRequestContext* context);
 | 
			
		||||
 | 
			
		||||
  // KeyedService implementation:
 | 
			
		||||
  void Shutdown() override;
 | 
			
		||||
@@ -84,7 +119,8 @@ class CefExtensionSystem : public ExtensionSystem {
 | 
			
		||||
  // Information about a registered component extension.
 | 
			
		||||
  struct ComponentExtensionInfo {
 | 
			
		||||
    ComponentExtensionInfo(const base::DictionaryValue* manifest,
 | 
			
		||||
                           const base::FilePath& root_directory);
 | 
			
		||||
                           const base::FilePath& root_directory,
 | 
			
		||||
                           bool internal);
 | 
			
		||||
 | 
			
		||||
    // The parsed contents of the extensions's manifest file.
 | 
			
		||||
    const base::DictionaryValue* manifest;
 | 
			
		||||
@@ -92,8 +128,8 @@ class CefExtensionSystem : public ExtensionSystem {
 | 
			
		||||
    // Directory where the extension is stored.
 | 
			
		||||
    base::FilePath root_directory;
 | 
			
		||||
 | 
			
		||||
    // The component extension's ID.
 | 
			
		||||
    std::string extension_id;
 | 
			
		||||
    // True if the extension is an internal (built-in) component.
 | 
			
		||||
    bool internal;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  scoped_refptr<const Extension> CreateExtension(
 | 
			
		||||
@@ -101,7 +137,9 @@ class CefExtensionSystem : public ExtensionSystem {
 | 
			
		||||
      std::string* utf8_error);
 | 
			
		||||
 | 
			
		||||
  // Loads a registered component extension.
 | 
			
		||||
  const Extension* LoadExtension(const ComponentExtensionInfo& info);
 | 
			
		||||
  const Extension* LoadExtension(const ComponentExtensionInfo& info,
 | 
			
		||||
                                 CefRefPtr<CefRequestContext> loader_context,
 | 
			
		||||
                                 CefRefPtr<CefExtensionHandler> handler);
 | 
			
		||||
 | 
			
		||||
  // Unload the specified extension.
 | 
			
		||||
  void UnloadExtension(const std::string& extension_id,
 | 
			
		||||
@@ -141,6 +179,9 @@ class CefExtensionSystem : public ExtensionSystem {
 | 
			
		||||
  // ExtensionSystem, and thus us.
 | 
			
		||||
  extensions::RendererStartupHelper* renderer_helper_;
 | 
			
		||||
 | 
			
		||||
  // Map of extension ID to CEF extension object.
 | 
			
		||||
  ExtensionMap extension_map_;
 | 
			
		||||
 | 
			
		||||
  // Must be the last member.
 | 
			
		||||
  base::WeakPtrFactory<CefExtensionSystem> weak_ptr_factory_;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								libcef/browser/extensions/extension_view_host.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								libcef/browser/extensions/extension_view_host.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2013 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/extensions/extension_view_host.h"
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_platform_delegate.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_host_delegate.h"
 | 
			
		||||
 | 
			
		||||
#include "content/public/browser/notification_source.h"
 | 
			
		||||
#include "content/public/browser/web_contents.h"
 | 
			
		||||
#include "extensions/browser/extension_system.h"
 | 
			
		||||
#include "extensions/browser/notification_types.h"
 | 
			
		||||
#include "extensions/browser/runtime_data.h"
 | 
			
		||||
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
 | 
			
		||||
 | 
			
		||||
using content::NativeWebKeyboardEvent;
 | 
			
		||||
using content::OpenURLParams;
 | 
			
		||||
using content::WebContents;
 | 
			
		||||
using content::WebContentsObserver;
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
CefExtensionViewHost::CefExtensionViewHost(
 | 
			
		||||
    CefBrowserHostImpl* browser,
 | 
			
		||||
    const Extension* extension,
 | 
			
		||||
    content::BrowserContext* browser_context,
 | 
			
		||||
    content::WebContents* host_contents,
 | 
			
		||||
    const GURL& url,
 | 
			
		||||
    ViewType host_type)
 | 
			
		||||
    : ExtensionHost(new CefExtensionHostDelegate(browser),
 | 
			
		||||
                    extension,
 | 
			
		||||
                    browser_context,
 | 
			
		||||
                    host_contents,
 | 
			
		||||
                    url,
 | 
			
		||||
                    host_type) {
 | 
			
		||||
  // Only used for dialogs and popups.
 | 
			
		||||
  DCHECK(host_type == VIEW_TYPE_EXTENSION_DIALOG ||
 | 
			
		||||
         host_type == VIEW_TYPE_EXTENSION_POPUP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CefExtensionViewHost::~CefExtensionViewHost() {}
 | 
			
		||||
 | 
			
		||||
void CefExtensionViewHost::OnDidStopFirstLoad() {
 | 
			
		||||
  // Nothing to do here, but don't call the base class method.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionViewHost::LoadInitialURL() {
 | 
			
		||||
  if (!ExtensionSystem::Get(browser_context())
 | 
			
		||||
           ->runtime_data()
 | 
			
		||||
           ->IsBackgroundPageReady(extension())) {
 | 
			
		||||
    // Make sure the background page loads before any others.
 | 
			
		||||
    registrar_.Add(this,
 | 
			
		||||
                   extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
 | 
			
		||||
                   content::Source<Extension>(extension()));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ExtensionHost::LoadInitialURL();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionViewHost::IsBackgroundPage() const {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionViewHost::ShouldTransferNavigation(
 | 
			
		||||
    bool is_main_frame_navigation) {
 | 
			
		||||
  // Block navigations that cause the main frame to navigate to non-extension
 | 
			
		||||
  // content (i.e. to web content).
 | 
			
		||||
  return !is_main_frame_navigation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionViewHost::PreHandleGestureEvent(
 | 
			
		||||
    content::WebContents* source,
 | 
			
		||||
    const blink::WebGestureEvent& event) {
 | 
			
		||||
  // Disable pinch zooming.
 | 
			
		||||
  return blink::WebInputEvent::IsPinchGestureEventType(event.GetType());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WebContents* CefExtensionViewHost::GetVisibleWebContents() const {
 | 
			
		||||
  if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP)
 | 
			
		||||
    return host_contents();
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionViewHost::Observe(
 | 
			
		||||
    int type,
 | 
			
		||||
    const content::NotificationSource& source,
 | 
			
		||||
    const content::NotificationDetails& details) {
 | 
			
		||||
  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY);
 | 
			
		||||
  DCHECK(ExtensionSystem::Get(browser_context())
 | 
			
		||||
             ->runtime_data()
 | 
			
		||||
             ->IsBackgroundPageReady(extension()));
 | 
			
		||||
  LoadInitialURL();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
							
								
								
									
										64
									
								
								libcef/browser/extensions/extension_view_host.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								libcef/browser/extensions/extension_view_host.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
// Copyright 2017 the Chromium Embedded Framework Authors. Portions copyright
 | 
			
		||||
// 2013 The Chromium Authors. All rights reserved. Use of this source code is
 | 
			
		||||
// governed by a BSD-style license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_VIEW_HOST_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_VIEW_HOST_H_
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "base/macros.h"
 | 
			
		||||
#include "content/public/browser/notification_observer.h"
 | 
			
		||||
#include "content/public/browser/notification_registrar.h"
 | 
			
		||||
#include "extensions/browser/extension_host.h"
 | 
			
		||||
 | 
			
		||||
class CefBrowserHostImpl;
 | 
			
		||||
 | 
			
		||||
namespace content {
 | 
			
		||||
class WebContents;
 | 
			
		||||
}  // namespace content
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
// The ExtensionHost for an extension that backs a view in the browser UI. For
 | 
			
		||||
// example, this could be an extension popup or dialog, but not a background
 | 
			
		||||
// page. Object lifespan is managed by CefBrowserHostImpl. Based on
 | 
			
		||||
// chrome/browser/extensions/extension_view_host.h.
 | 
			
		||||
class CefExtensionViewHost : public ExtensionHost,
 | 
			
		||||
                             public content::NotificationObserver {
 | 
			
		||||
 public:
 | 
			
		||||
  CefExtensionViewHost(CefBrowserHostImpl* browser,
 | 
			
		||||
                       const Extension* extension,
 | 
			
		||||
                       content::BrowserContext* browser_context,
 | 
			
		||||
                       content::WebContents* host_contents,
 | 
			
		||||
                       const GURL& url,
 | 
			
		||||
                       ViewType host_type);
 | 
			
		||||
  ~CefExtensionViewHost() override;
 | 
			
		||||
 | 
			
		||||
  // ExtensionHost methods:
 | 
			
		||||
  void OnDidStopFirstLoad() override;
 | 
			
		||||
  void LoadInitialURL() override;
 | 
			
		||||
  bool IsBackgroundPage() const override;
 | 
			
		||||
 | 
			
		||||
  // content::WebContentsDelegate methods:
 | 
			
		||||
  bool ShouldTransferNavigation(bool is_main_frame_navigation) override;
 | 
			
		||||
  bool PreHandleGestureEvent(content::WebContents* source,
 | 
			
		||||
                             const blink::WebGestureEvent& event) override;
 | 
			
		||||
 | 
			
		||||
  // extensions::ExtensionFunctionDispatcher::Delegate methods:
 | 
			
		||||
  content::WebContents* GetVisibleWebContents() const override;
 | 
			
		||||
 | 
			
		||||
  // content::NotificationObserver methods:
 | 
			
		||||
  void Observe(int type,
 | 
			
		||||
               const content::NotificationSource& source,
 | 
			
		||||
               const content::NotificationDetails& details) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  content::NotificationRegistrar registrar_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionViewHost);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 | 
			
		||||
#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_VIEW_HOST_H_
 | 
			
		||||
@@ -15,7 +15,9 @@ namespace extensions {
 | 
			
		||||
 | 
			
		||||
CefExtensionWebContentsObserver::CefExtensionWebContentsObserver(
 | 
			
		||||
    content::WebContents* web_contents)
 | 
			
		||||
    : ExtensionWebContentsObserver(web_contents) {}
 | 
			
		||||
    : ExtensionWebContentsObserver(web_contents),
 | 
			
		||||
      script_executor_(
 | 
			
		||||
          new ScriptExecutor(web_contents, &script_execution_observers_)) {}
 | 
			
		||||
 | 
			
		||||
CefExtensionWebContentsObserver::~CefExtensionWebContentsObserver() {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,13 @@
 | 
			
		||||
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_WEB_CONTENTS_OBSERVER_H_
 | 
			
		||||
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_WEB_CONTENTS_OBSERVER_H_
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "base/observer_list.h"
 | 
			
		||||
#include "content/public/browser/web_contents_user_data.h"
 | 
			
		||||
#include "extensions/browser/extension_web_contents_observer.h"
 | 
			
		||||
#include "extensions/browser/script_execution_observer.h"
 | 
			
		||||
#include "extensions/browser/script_executor.h"
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
@@ -17,6 +22,8 @@ class CefExtensionWebContentsObserver
 | 
			
		||||
 public:
 | 
			
		||||
  ~CefExtensionWebContentsObserver() override;
 | 
			
		||||
 | 
			
		||||
  ScriptExecutor* script_executor() { return script_executor_.get(); }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  friend class content::WebContentsUserData<CefExtensionWebContentsObserver>;
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +32,12 @@ class CefExtensionWebContentsObserver
 | 
			
		||||
  // content::WebContentsObserver overrides.
 | 
			
		||||
  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
 | 
			
		||||
 | 
			
		||||
  // Our content script observers. Declare at top so that it will outlive all
 | 
			
		||||
  // other members, since they might add themselves as observers.
 | 
			
		||||
  base::ObserverList<ScriptExecutionObserver> script_execution_observers_;
 | 
			
		||||
 | 
			
		||||
  std::unique_ptr<ScriptExecutor> script_executor_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionWebContentsObserver);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@
 | 
			
		||||
#include "libcef/browser/printing/print_view_manager.h"
 | 
			
		||||
 | 
			
		||||
#include "base/memory/ptr_util.h"
 | 
			
		||||
#include "chrome/browser/sessions/session_tab_helper.h"
 | 
			
		||||
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 | 
			
		||||
#include "components/pdf/browser/pdf_web_contents_helper.h"
 | 
			
		||||
#include "components/zoom/zoom_controller.h"
 | 
			
		||||
@@ -64,7 +63,6 @@ void CefExtensionsAPIClient::AttachWebContentsHelpers(
 | 
			
		||||
                        new CefPDFWebContentsHelperClient()));
 | 
			
		||||
 | 
			
		||||
  // Used by the tabs extension API.
 | 
			
		||||
  SessionTabHelper::CreateForWebContents(web_contents);
 | 
			
		||||
  zoom::ZoomController::CreateForWebContents(web_contents);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,17 +8,19 @@
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include "libcef/browser/browser_context_impl.h"
 | 
			
		||||
#include "libcef/browser/browser_host_impl.h"
 | 
			
		||||
#include "libcef/browser/extensions/chrome_api_registration.h"
 | 
			
		||||
#include "libcef/browser/extensions/component_extension_resource_manager.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_system.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_system_factory.h"
 | 
			
		||||
#include "libcef/browser/extensions/extension_web_contents_observer.h"
 | 
			
		||||
#include "libcef/browser/extensions/extensions_api_client.h"
 | 
			
		||||
#include "libcef/browser/request_context_impl.h"
 | 
			
		||||
 | 
			
		||||
//#include "cef/libcef/browser/extensions/api/generated_api_registration.h"
 | 
			
		||||
#include "chrome/browser/browser_process.h"
 | 
			
		||||
#include "chrome/browser/extensions/chrome_url_request_util.h"
 | 
			
		||||
#include "chrome/browser/extensions/event_router_forwarder.h"
 | 
			
		||||
#include "chrome/browser/profiles/incognito_helpers.h"
 | 
			
		||||
#include "content/public/browser/browser_context.h"
 | 
			
		||||
#include "content/public/browser/browser_thread.h"
 | 
			
		||||
#include "content/public/browser/render_frame_host.h"
 | 
			
		||||
@@ -30,6 +32,7 @@
 | 
			
		||||
#include "extensions/browser/extension_function_registry.h"
 | 
			
		||||
#include "extensions/browser/extension_host_delegate.h"
 | 
			
		||||
#include "extensions/browser/mojo/service_registration.h"
 | 
			
		||||
#include "extensions/browser/serial_extension_host_queue.h"
 | 
			
		||||
#include "extensions/browser/url_request_util.h"
 | 
			
		||||
#include "extensions/common/constants.h"
 | 
			
		||||
 | 
			
		||||
@@ -44,6 +47,12 @@ CefExtensionsBrowserClient::CefExtensionsBrowserClient()
 | 
			
		||||
 | 
			
		||||
CefExtensionsBrowserClient::~CefExtensionsBrowserClient() {}
 | 
			
		||||
 | 
			
		||||
// static
 | 
			
		||||
CefExtensionsBrowserClient* CefExtensionsBrowserClient::Get() {
 | 
			
		||||
  return static_cast<CefExtensionsBrowserClient*>(
 | 
			
		||||
      ExtensionsBrowserClient::Get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionsBrowserClient::IsShuttingDown() {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
@@ -62,24 +71,28 @@ bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first,
 | 
			
		||||
                                               BrowserContext* second) {
 | 
			
		||||
  // Returns true if |first| and |second| share the same underlying
 | 
			
		||||
  // CefBrowserContextImpl.
 | 
			
		||||
  return CefBrowserContextImpl::GetForContext(first) ==
 | 
			
		||||
         CefBrowserContextImpl::GetForContext(second);
 | 
			
		||||
  return GetCefImplContext(first) == GetCefImplContext(second);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionsBrowserClient::HasOffTheRecordContext(
 | 
			
		||||
    BrowserContext* context) {
 | 
			
		||||
  // CEF doesn't use incognito contexts.
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BrowserContext* CefExtensionsBrowserClient::GetOffTheRecordContext(
 | 
			
		||||
    BrowserContext* context) {
 | 
			
		||||
  // TODO(extensions): Do we need to support this?
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BrowserContext* CefExtensionsBrowserClient::GetOriginalContext(
 | 
			
		||||
    BrowserContext* context) {
 | 
			
		||||
  return chrome::GetBrowserContextRedirectedInIncognito(context);
 | 
			
		||||
  return GetCefImplContext(context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BrowserContext* CefExtensionsBrowserClient::GetCefImplContext(
 | 
			
		||||
    BrowserContext* context) {
 | 
			
		||||
  return CefBrowserContextImpl::GetForContext(context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionsBrowserClient::IsGuestSession(BrowserContext* context) const {
 | 
			
		||||
@@ -148,11 +161,68 @@ ProcessManagerDelegate* CefExtensionsBrowserClient::GetProcessManagerDelegate()
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<ExtensionHostDelegate>
 | 
			
		||||
CefExtensionsBrowserClient::CreateExtensionHostDelegate() {
 | 
			
		||||
  // TODO(extensions): Implement to support Apps.
 | 
			
		||||
  // CEF does not use the ExtensionHost constructor that calls this method.
 | 
			
		||||
  NOTREACHED();
 | 
			
		||||
  return std::unique_ptr<ExtensionHostDelegate>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionsBrowserClient::CreateBackgroundExtensionHost(
 | 
			
		||||
    const Extension* extension,
 | 
			
		||||
    content::BrowserContext* browser_context,
 | 
			
		||||
    const GURL& url,
 | 
			
		||||
    ExtensionHost** host) {
 | 
			
		||||
  // The BrowserContext referenced by ProcessManager should always be an *Impl.
 | 
			
		||||
  DCHECK(!static_cast<CefBrowserContext*>(browser_context)->is_proxy());
 | 
			
		||||
  CefBrowserContextImpl* browser_context_impl =
 | 
			
		||||
      CefBrowserContextImpl::GetForContext(browser_context);
 | 
			
		||||
 | 
			
		||||
  // A CEF representation should always exist.
 | 
			
		||||
  CefRefPtr<CefExtension> cef_extension =
 | 
			
		||||
      browser_context_impl->extension_system()->GetExtension(extension->id());
 | 
			
		||||
  DCHECK(cef_extension);
 | 
			
		||||
  if (!cef_extension) {
 | 
			
		||||
    // Cancel the background host creation.
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Always use the same request context that the extension was registered with.
 | 
			
		||||
  // May represent an *Impl or *Proxy BrowserContext.
 | 
			
		||||
  // GetLoaderContext() will return NULL for internal extensions.
 | 
			
		||||
  CefRefPtr<CefRequestContext> request_context =
 | 
			
		||||
      cef_extension->GetLoaderContext();
 | 
			
		||||
  if (!request_context) {
 | 
			
		||||
    // Cancel the background host creation.
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CefBrowserHostImpl::CreateParams create_params;
 | 
			
		||||
  create_params.url = url;
 | 
			
		||||
  create_params.request_context = request_context;
 | 
			
		||||
 | 
			
		||||
  CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
 | 
			
		||||
  if (handler.get() && handler->OnBeforeBackgroundBrowser(
 | 
			
		||||
                           cef_extension, url.spec(), create_params.client,
 | 
			
		||||
                           create_params.settings)) {
 | 
			
		||||
    // Cancel the background host creation.
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // This triggers creation of the background host.
 | 
			
		||||
  create_params.extension = extension;
 | 
			
		||||
  create_params.extension_host_type =
 | 
			
		||||
      extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
 | 
			
		||||
 | 
			
		||||
  // Browser creation may fail under certain rare circumstances. Fail the
 | 
			
		||||
  // background host creation in that case.
 | 
			
		||||
  CefRefPtr<CefBrowserHostImpl> browser =
 | 
			
		||||
      CefBrowserHostImpl::Create(create_params);
 | 
			
		||||
  if (browser) {
 | 
			
		||||
    *host = browser->extension_host();
 | 
			
		||||
    DCHECK(*host);
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CefExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
 | 
			
		||||
  // TODO(jamescook): We might want to tell extensions when app_shell updates.
 | 
			
		||||
  return false;
 | 
			
		||||
@@ -250,9 +320,10 @@ bool CefExtensionsBrowserClient::IsLockScreenContext(
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CefExtensionsBrowserClient::SetAPIClientForTest(
 | 
			
		||||
    ExtensionsAPIClient* api_client) {
 | 
			
		||||
  api_client_.reset(api_client);
 | 
			
		||||
ExtensionHostQueue* CefExtensionsBrowserClient::GetExtensionHostQueue() {
 | 
			
		||||
  if (!extension_host_queue_)
 | 
			
		||||
    extension_host_queue_.reset(new SerialExtensionHostQueue);
 | 
			
		||||
  return extension_host_queue_.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace extensions
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
 | 
			
		||||
namespace extensions {
 | 
			
		||||
 | 
			
		||||
class ExtensionHostQueue;
 | 
			
		||||
class ExtensionsAPIClient;
 | 
			
		||||
 | 
			
		||||
// An ExtensionsBrowserClient that supports a single content::BrowserContent
 | 
			
		||||
@@ -20,6 +21,9 @@ class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
 | 
			
		||||
  CefExtensionsBrowserClient();
 | 
			
		||||
  ~CefExtensionsBrowserClient() override;
 | 
			
		||||
 | 
			
		||||
  // Returns the singleton CefExtensionsBrowserClient instance.
 | 
			
		||||
  static CefExtensionsBrowserClient* Get();
 | 
			
		||||
 | 
			
		||||
  // ExtensionsBrowserClient overrides:
 | 
			
		||||
  bool IsShuttingDown() override;
 | 
			
		||||
  bool AreExtensionsDisabled(const base::CommandLine& command_line,
 | 
			
		||||
@@ -32,6 +36,8 @@ class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
 | 
			
		||||
      content::BrowserContext* context) override;
 | 
			
		||||
  content::BrowserContext* GetOriginalContext(
 | 
			
		||||
      content::BrowserContext* context) override;
 | 
			
		||||
  content::BrowserContext* GetCefImplContext(
 | 
			
		||||
      content::BrowserContext* context) override;
 | 
			
		||||
  bool IsGuestSession(content::BrowserContext* context) const override;
 | 
			
		||||
  bool IsExtensionIncognitoEnabled(
 | 
			
		||||
      const std::string& extension_id,
 | 
			
		||||
@@ -56,6 +62,10 @@ class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
 | 
			
		||||
      std::vector<ExtensionPrefsObserver*>* observers) const override;
 | 
			
		||||
  ProcessManagerDelegate* GetProcessManagerDelegate() const override;
 | 
			
		||||
  std::unique_ptr<ExtensionHostDelegate> CreateExtensionHostDelegate() override;
 | 
			
		||||
  bool CreateBackgroundExtensionHost(const Extension* extension,
 | 
			
		||||
                                     content::BrowserContext* browser_context,
 | 
			
		||||
                                     const GURL& url,
 | 
			
		||||
                                     ExtensionHost** host) override;
 | 
			
		||||
  bool DidVersionUpdate(content::BrowserContext* context) override;
 | 
			
		||||
  void PermitExternalProtocolHandler() override;
 | 
			
		||||
  bool IsRunningInForcedAppMode() override;
 | 
			
		||||
@@ -82,8 +92,7 @@ class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
 | 
			
		||||
  KioskDelegate* GetKioskDelegate() override;
 | 
			
		||||
  bool IsLockScreenContext(content::BrowserContext* context) override;
 | 
			
		||||
 | 
			
		||||
  // Sets the API client.
 | 
			
		||||
  void SetAPIClientForTest(ExtensionsAPIClient* api_client);
 | 
			
		||||
  ExtensionHostQueue* GetExtensionHostQueue();
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // Support for extension APIs.
 | 
			
		||||
@@ -92,6 +101,9 @@ class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
 | 
			
		||||
  // Resource manager used to supply resources from pak files.
 | 
			
		||||
  std::unique_ptr<ComponentExtensionResourceManager> resource_manager_;
 | 
			
		||||
 | 
			
		||||
  // Used to create deferred RenderViews for extensions.
 | 
			
		||||
  std::unique_ptr<ExtensionHostQueue> extension_host_queue_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(CefExtensionsBrowserClient);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user