Add PDF extension support (issue #1565)

This commit is contained in:
Marshall Greenblatt 2015-07-16 17:40:01 -04:00
parent aefb5ccce8
commit b7a56d9343
108 changed files with 5513 additions and 427 deletions

View File

@ -289,6 +289,7 @@ if(OS_LINUX)
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
icudtl.dat
locales
@ -457,6 +458,7 @@ if(OS_WINDOWS)
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
icudtl.dat
locales

136
cef.gyp
View File

@ -656,6 +656,7 @@
'<(DEPTH)/ui/strings/ui_strings.gyp:ui_strings',
'<(DEPTH)/components/components_strings.gyp:components_strings',
'<(DEPTH)/content/app/strings/content_strings.gyp:content_strings',
'<(DEPTH)/extensions/extensions_strings.gyp:extensions_strings',
'cef_strings',
],
'actions': [
@ -733,6 +734,59 @@
},
],
},
{
# Create the pack file for component extension resources.
'target_name': 'component_extension_resources',
'type': 'none',
'actions': [
{
'action_name': 'component_extension_resources',
'variables': {
'grit_grd_file': '../chrome/browser/resources/component_extension_resources.grd',
},
'includes': [ '../build/grit_action.gypi' ],
},
],
'includes': [ '../build/grit_target.gypi' ],
'copies': [
{
'destination': '<(PRODUCT_DIR)',
'files': [
'<(grit_out_dir)/component_extension_resources.pak'
],
},
],
},
{
# Combine all extensions-related non-localized pack file resources into a
# single CEF pack file. Scaled resources are still in cef_pak.
'target_name': 'cef_extensions_pak',
'type': 'none',
'dependencies': [
'<(DEPTH)/extensions/extensions_resources.gyp:extensions_resources',
'<(DEPTH)/extensions/extensions_strings.gyp:extensions_strings',
'<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
'component_extension_resources',
],
'variables': {
'make_pack_header_path': 'tools/make_pack_header.py',
},
'actions': [
{
'action_name': 'repack_cef_extensions_pack',
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_renderer_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/webui_resources.pak',
'<(grit_out_dir)/component_extension_resources.pak',
],
'pak_output': '<(PRODUCT_DIR)/cef_extensions.pak',
},
'includes': [ '../build/repack_action.gypi' ],
},
],
},
{
# Combine all non-localized pack file resources into a single CEF pack file.
'target_name': 'cef_pak',
@ -745,6 +799,7 @@
'<(DEPTH)/content/browser/devtools/devtools_resources.gyp:devtools_resources',
'<(DEPTH)/net/net.gyp:net_resources',
'<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
'cef_extensions_pak',
'cef_locales',
'cef_resources',
],
@ -773,6 +828,7 @@
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_image_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/components/components_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_browser_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_100_percent.pak',
],
'pak_output': '<(PRODUCT_DIR)/cef_100_percent.pak',
@ -786,6 +842,7 @@
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_image_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/components/components_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/extensions/extensions_browser_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_200_percent.pak',
],
'pak_output': '<(PRODUCT_DIR)/cef_200_percent.pak',
@ -799,9 +856,14 @@
'<(SHARED_INTERMEDIATE_DIR)/blink/grit/devtools_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/grit/blink_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/content/grit/content_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/extensions/grit/extensions_browser_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/extensions/grit/extensions_renderer_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/extensions/grit/extensions_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/net/grit/net_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/grit/ui_resources.h',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/grit/webui_resources.h',
'<(grit_out_dir)/grit/cef_resources.h',
'<(grit_out_dir)/grit/component_extension_resources.h',
],
},
'inputs': [
@ -820,6 +882,7 @@
'header_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/components/strings/grit/components_strings.h',
'<(SHARED_INTERMEDIATE_DIR)/content/app/strings/grit/content_strings.h',
'<(SHARED_INTERMEDIATE_DIR)/extensions/strings/grit/extensions_strings.h',
'<(SHARED_INTERMEDIATE_DIR)/ui/strings/grit/ui_strings.h',
'<(grit_out_dir)/grit/cef_strings.h',
],
@ -874,16 +937,19 @@
# zip_analyzer_results.h via chrome_utility_messages.h
'<(DEPTH)/chrome/chrome.gyp:safe_browsing_proto',
'<(DEPTH)/components/components.gyp:crash_component_breakpad_mac_to_be_deleted',
'<(DEPTH)/components/components.gyp:crx_file',
'<(DEPTH)/components/components.gyp:devtools_discovery',
'<(DEPTH)/components/components.gyp:devtools_http_handler',
'<(DEPTH)/components/components.gyp:keyed_service_content',
'<(DEPTH)/components/components.gyp:keyed_service_core',
'<(DEPTH)/components/components.gyp:navigation_interception',
'<(DEPTH)/components/components.gyp:pdf_browser',
'<(DEPTH)/components/components.gyp:pdf_renderer',
'<(DEPTH)/components/components.gyp:plugins_renderer',
'<(DEPTH)/components/components.gyp:pref_registry',
'<(DEPTH)/components/components.gyp:printing_common',
'<(DEPTH)/components/components.gyp:printing_renderer',
'<(DEPTH)/components/components.gyp:update_client',
'<(DEPTH)/components/components.gyp:user_prefs',
'<(DEPTH)/components/components.gyp:web_cache_renderer',
'<(DEPTH)/content/content.gyp:content_app_both',
@ -896,6 +962,14 @@
'<(DEPTH)/content/content.gyp:content_resources',
'<(DEPTH)/content/content.gyp:content_utility',
'<(DEPTH)/crypto/crypto.gyp:crypto',
'<(DEPTH)/device/core/core.gyp:device_core',
'<(DEPTH)/device/hid/hid.gyp:device_hid',
'<(DEPTH)/extensions/browser/api/api_registration.gyp:extensions_api_registration',
'<(DEPTH)/extensions/common/api/api.gyp:extensions_api',
'<(DEPTH)/extensions/extensions.gyp:extensions_browser',
'<(DEPTH)/extensions/extensions.gyp:extensions_renderer',
'<(DEPTH)/extensions/extensions.gyp:extensions_utility',
'<(DEPTH)/extensions/extensions_resources.gyp:extensions_resources',
'<(DEPTH)/gpu/gpu.gyp:gpu',
'<(DEPTH)/ipc/ipc.gyp:ipc',
'<(DEPTH)/media/blink/media_blink.gyp:media_blink',
@ -903,6 +977,7 @@
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/net/net.gyp:net_browser_services',
'<(DEPTH)/net/net.gyp:net_with_v8',
'<(DEPTH)/pdf/pdf.gyp:pdf',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/storage/storage_browser.gyp:storage',
'<(DEPTH)/sync/sync.gyp:sync',
@ -917,6 +992,9 @@
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
# Necessary to generate the grit include files.
'cef_pak',
# Necessary to generate API bindings for extensions.
'libcef/browser/extensions/api/api_registration.gyp:cef_api_registration',
'libcef/common/extensions/api/api.gyp:cef_api',
],
'sources': [
'<@(includes_common)',
@ -966,6 +1044,36 @@
'libcef/browser/download_item_impl.h',
'libcef/browser/download_manager_delegate.cc',
'libcef/browser/download_manager_delegate.h',
'libcef/browser/extensions/api/streams_private/streams_private_api.cc',
'libcef/browser/extensions/api/streams_private/streams_private_api.h',
'libcef/browser/extensions/browser_context_keyed_service_factories.cc',
'libcef/browser/extensions/browser_context_keyed_service_factories.h',
'libcef/browser/extensions/browser_extensions_util.cc',
'libcef/browser/extensions/browser_extensions_util.h',
'libcef/browser/extensions/component_extension_resource_manager.cc',
'libcef/browser/extensions/component_extension_resource_manager.h',
'libcef/browser/extensions/event_router_forwarder.cc',
'libcef/browser/extensions/event_router_forwarder.h',
'libcef/browser/extensions/extensions_api_client.cc',
'libcef/browser/extensions/extensions_api_client.h',
'libcef/browser/extensions/extensions_browser_client.cc',
'libcef/browser/extensions/extensions_browser_client.h',
'libcef/browser/extensions/extension_system.cc',
'libcef/browser/extensions/extension_system.h',
'libcef/browser/extensions/extension_system_factory.cc',
'libcef/browser/extensions/extension_system_factory.h',
'libcef/browser/extensions/extension_web_contents_observer.cc',
'libcef/browser/extensions/extension_web_contents_observer.h',
'libcef/browser/extensions/mime_handler_view_guest_delegate.cc',
'libcef/browser/extensions/mime_handler_view_guest_delegate.h',
'libcef/browser/extensions/pdf_extension_util.cc',
'libcef/browser/extensions/pdf_extension_util.h',
'libcef/browser/extensions/pdf_web_contents_helper_client.cc',
'libcef/browser/extensions/pdf_web_contents_helper_client.h',
'libcef/browser/extensions/plugin_info_message_filter.cc',
'libcef/browser/extensions/plugin_info_message_filter.h',
'libcef/browser/extensions/url_request_util.cc',
'libcef/browser/extensions/url_request_util.h',
'libcef/browser/frame_host_impl.cc',
'libcef/browser/frame_host_impl.h',
'libcef/browser/geolocation_impl.cc',
@ -1074,6 +1182,10 @@
'libcef/common/crash_reporter_client.h',
'libcef/common/drag_data_impl.cc',
'libcef/common/drag_data_impl.h',
'libcef/common/extensions/extensions_client.cc',
'libcef/common/extensions/extensions_client.h',
'libcef/common/extensions/extensions_util.cc',
'libcef/common/extensions/extensions_util.h',
'libcef/common/http_header_utils.cc',
'libcef/common/http_header_utils.h',
'libcef/common/json_impl.cc',
@ -1123,10 +1235,15 @@
'libcef/renderer/dom_document_impl.h',
'libcef/renderer/dom_node_impl.cc',
'libcef/renderer/dom_node_impl.h',
'libcef/renderer/extensions/extensions_renderer_client.cc',
'libcef/renderer/extensions/extensions_renderer_client.h',
'libcef/renderer/extensions/print_web_view_helper_delegate.cc',
'libcef/renderer/extensions/print_web_view_helper_delegate.h',
'libcef/renderer/frame_impl.cc',
'libcef/renderer/frame_impl.h',
'libcef/renderer/pepper/pepper_helper.cc',
'libcef/renderer/pepper/pepper_helper.h',
'libcef/renderer/pepper/pepper_uma_host.cc',
'libcef/renderer/pepper/renderer_pepper_host_factory.cc',
'libcef/renderer/pepper/renderer_pepper_host_factory.h',
'libcef/renderer/render_frame_observer.cc',
@ -1185,8 +1302,6 @@
'<(DEPTH)/chrome/browser/printing/printer_query.h',
'<(DEPTH)/chrome/common/extensions/extension_constants.cc',
'<(DEPTH)/chrome/common/extensions/extension_constants.h',
'<(DEPTH)/extensions/common/constants.cc',
'<(DEPTH)/extensions/common/constants.h',
# Include header for stub creation (BrowserProcess) so print_job_worker can
# determine the current locale.
'<(DEPTH)/chrome/browser/browser_process.cc',
@ -1258,13 +1373,21 @@
# Include sources required by chrome_utility_messages.h.
'<(DEPTH)/chrome/common/safe_browsing/zip_analyzer_results.h',
'<(DEPTH)/chrome/common/safe_browsing/zip_analyzer_results.cc',
# Include sources for pepper PDF support.
'<(DEPTH)/chrome/child/pdf_child_init.cc',
'<(DEPTH)/chrome/child/pdf_child_init.h',
'<(DEPTH)/chrome/renderer/pepper/chrome_pdf_print_client.cc',
'<(DEPTH)/chrome/renderer/pepper/chrome_pdf_print_client.h',
# Include sources for extensions support.
'<(DEPTH)/chrome/common/pepper_permission_util.cc',
'<(DEPTH)/chrome/common/pepper_permission_util.h',
'<(DEPTH)/extensions/shell/browser/shell_display_info_provider.cc',
'<(DEPTH)/extensions/shell/browser/shell_display_info_provider.h',
'<(DEPTH)/extensions/shell/browser/shell_web_contents_modal_dialog_manager.cc',
'<(grit_out_dir)/grit/component_extension_resources_map.cc',
],
'conditions': [
['OS=="win"', {
'dependencies': [
# For printing using PDF.
'<(DEPTH)/pdf/pdf.gyp:pdf',
],
'sources': [
'<@(includes_win)',
'libcef/browser/browser_host_impl_win.cc',
@ -1363,6 +1486,7 @@
'<(PRODUCT_DIR)/cef.pak',
'<(PRODUCT_DIR)/cef_100_percent.pak',
'<(PRODUCT_DIR)/cef_200_percent.pak',
'<(PRODUCT_DIR)/cef_extensions.pak',
'<(PRODUCT_DIR)/devtools_resources.pak',
'<(PRODUCT_DIR)/icudtl.dat',
'<(PRODUCT_DIR)/natives_blob.bin',

View File

@ -214,6 +214,8 @@
'tests/cefclient/resources/logo.png',
'tests/cefclient/resources/osr_test.html',
'tests/cefclient/resources/other_tests.html',
'tests/cefclient/resources/pdf.html',
'tests/cefclient/resources/pdf.pdf',
'tests/cefclient/resources/performance.html',
'tests/cefclient/resources/performance2.html',
'tests/cefclient/resources/transparency.html',

View File

@ -4,6 +4,8 @@
#include "libcef/browser/browser_context.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/extensions/extension_system.h"
#include "libcef/common/extensions/extensions_util.h"
#include "base/logging.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
@ -15,16 +17,7 @@ base::AtomicRefCount CefBrowserContext::DebugObjCt = 0;
#endif
CefBrowserContext::CefBrowserContext()
: resource_context_(new CefResourceContext) {
BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
this);
// Spell checking support and possibly other subsystems retrieve the
// PrefService associated with a BrowserContext via UserPrefs::Get().
PrefService* pref_service = CefContentBrowserClient::Get()->pref_service();
DCHECK(pref_service);
user_prefs::UserPrefs::Set(this, pref_service);
: extension_system_(NULL) {
#ifndef NDEBUG
base::AtomicRefCountInc(&DebugObjCt);
#endif
@ -47,6 +40,33 @@ CefBrowserContext::~CefBrowserContext() {
#endif
}
void CefBrowserContext::Initialize() {
const bool extensions_enabled = extensions::ExtensionsEnabled();
if (extensions_enabled) {
// Create the custom ExtensionSystem first because other KeyedServices
// depend on it.
extension_system_ = static_cast<extensions::CefExtensionSystem*>(
extensions::ExtensionSystem::Get(this));
extension_system_->InitForRegularProfile(true);
}
resource_context_.reset(new CefResourceContext(
IsOffTheRecord(),
extensions_enabled ? extension_system_->info_map() : NULL));
BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
this);
// Spell checking support and possibly other subsystems retrieve the
// PrefService associated with a BrowserContext via UserPrefs::Get().
PrefService* pref_service = CefContentBrowserClient::Get()->pref_service();
DCHECK(pref_service);
user_prefs::UserPrefs::Set(this, pref_service);
if (extensions_enabled)
extension_system_->Init();
}
content::ResourceContext* CefBrowserContext::GetResourceContext() {
return resource_context_.get();
}

View File

@ -104,6 +104,10 @@
// CefURLRequestContextGetter* destruction.
*/
namespace extensions {
class CefExtensionSystem;
}
// Main entry point for configuring behavior on a per-browser basis. An instance
// of this class is passed to WebContents::Create in CefBrowserHostImpl::
// CreateInternal. Only accessed on the UI thread unless otherwise indicated.
@ -114,13 +118,12 @@ class CefBrowserContext
public:
CefBrowserContext();
// Must be called immediately after this object is created.
virtual void Initialize();
// BrowserContext methods.
content::ResourceContext* GetResourceContext() override;
// Returns true if this is a CefBrowserContextProxy object. Safe to call from
// any thread.
virtual bool IsProxy() const = 0;
// Returns the settings associated with this object. Safe to call from any
// thread.
virtual const CefRequestContextSettings& GetSettings() const = 0;
@ -140,7 +143,10 @@ class CefBrowserContext
content::URLRequestInterceptorScopedVector request_interceptors) = 0;
CefResourceContext* resource_context() const {
return resource_context_.get();
return resource_context_.get();
}
extensions::CefExtensionSystem* extension_system() const {
return extension_system_;
}
#ifndef NDEBUG
@ -159,6 +165,9 @@ class CefBrowserContext
scoped_ptr<CefResourceContext> resource_context_;
// Owned by the KeyedService system.
extensions::CefExtensionSystem* extension_system_;
DISALLOW_COPY_AND_ASSIGN(CefBrowserContext);
};

View File

@ -6,18 +6,21 @@
#include <map>
#include "libcef/browser/browser_context_proxy.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/download_manager_delegate.h"
#include "libcef/browser/permission_manager.h"
#include "libcef/browser/ssl_host_state_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/extensions/extensions_util.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/net/proxy_service_factory.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@ -27,15 +30,64 @@ using content::BrowserThread;
namespace {
// Manages the global mapping of cache path to Impl instance.
// Manages the global list of Impl instances.
class ImplManager {
public:
typedef std::vector<CefBrowserContextImpl*> Vector;
ImplManager() {}
~ImplManager() {
DCHECK(all_.empty());
DCHECK(map_.empty());
}
CefBrowserContextImpl* GetImpl(const base::FilePath& path) {
void AddImpl(CefBrowserContextImpl* impl) {
CEF_REQUIRE_UIT();
DCHECK(!IsValidImpl(impl));
all_.push_back(impl);
}
void RemoveImpl(CefBrowserContextImpl* impl, const base::FilePath& path) {
CEF_REQUIRE_UIT();
Vector::iterator it = GetImplPos(impl);
DCHECK(it != all_.end());
all_.erase(it);
if (!path.empty()) {
PathMap::iterator it = map_.find(path);
DCHECK(it != map_.end());
if (it != map_.end())
map_.erase(it);
}
}
bool IsValidImpl(const CefBrowserContextImpl* impl) {
CEF_REQUIRE_UIT();
return GetImplPos(impl) != all_.end();
}
CefBrowserContextImpl* GetImplForContext(
const content::BrowserContext* context) {
CEF_REQUIRE_UIT();
Vector::iterator it = all_.begin();
for (; it != all_.end(); ++it) {
if (*it == context || (*it)->HasProxy(context))
return *it;
}
return NULL;
}
void SetImplPath(CefBrowserContextImpl* impl, const base::FilePath& path) {
CEF_REQUIRE_UIT();
DCHECK(!path.empty());
DCHECK(IsValidImpl(impl));
DCHECK(GetImplForPath(path) == NULL);
map_.insert(std::make_pair(path, impl));
}
CefBrowserContextImpl* GetImplForPath(const base::FilePath& path) {
CEF_REQUIRE_UIT();
DCHECK(!path.empty());
PathMap::const_iterator it = map_.find(path);
@ -44,26 +96,23 @@ class ImplManager {
return NULL;
}
void AddImpl(const base::FilePath& path, CefBrowserContextImpl* impl) {
CEF_REQUIRE_UIT();
DCHECK(!path.empty());
DCHECK(GetImpl(path) == NULL);
map_.insert(std::make_pair(path, impl));
}
void RemoveImpl(const base::FilePath& path) {
CEF_REQUIRE_UIT();
DCHECK(!path.empty());
PathMap::iterator it = map_.find(path);
DCHECK(it != map_.end());
if (it != map_.end())
map_.erase(it);
}
const Vector GetAllImpl() const { return all_; }
private:
Vector::iterator GetImplPos(const CefBrowserContextImpl* impl) {
Vector::iterator it = all_.begin();
for (; it != all_.end(); ++it) {
if (*it == impl)
return it;
}
return all_.end();
}
typedef std::map<base::FilePath, CefBrowserContextImpl*> PathMap;
PathMap map_;
Vector all_;
DISALLOW_COPY_AND_ASSIGN(ImplManager);
};
@ -74,6 +123,7 @@ base::LazyInstance<ImplManager> g_manager = LAZY_INSTANCE_INITIALIZER;
CefBrowserContextImpl::CefBrowserContextImpl(
const CefRequestContextSettings& settings)
: settings_(settings) {
g_manager.Get().AddImpl(this);
}
CefBrowserContextImpl::~CefBrowserContextImpl() {
@ -84,8 +134,7 @@ CefBrowserContextImpl::~CefBrowserContextImpl() {
if (download_manager_delegate_.get())
download_manager_delegate_.reset(NULL);
if (!cache_path_.empty())
g_manager.Get().RemoveImpl(cache_path_);
g_manager.Get().RemoveImpl(this, cache_path_);
}
void CefBrowserContextImpl::Initialize() {
@ -102,7 +151,7 @@ void CefBrowserContextImpl::Initialize() {
}
if (!cache_path_.empty())
g_manager.Get().AddImpl(cache_path_, this);
g_manager.Get().SetImplPath(this, cache_path_);
if (settings_.accept_language_list.length == 0) {
// Use the global language list setting.
@ -110,6 +159,8 @@ void CefBrowserContextImpl::Initialize() {
CefString(&CefContext::Get()->settings().accept_language_list);
}
CefBrowserContext::Initialize();
// Initialize proxy configuration tracker.
pref_proxy_config_tracker_.reset(
ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
@ -123,10 +174,52 @@ void CefBrowserContextImpl::Initialize() {
DCHECK(url_request_getter_.get());
}
void CefBrowserContextImpl::AddProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT();
DCHECK(!HasProxy(proxy));
proxy_list_.push_back(proxy);
}
void CefBrowserContextImpl::RemoveProxy(const CefBrowserContextProxy* proxy) {
CEF_REQUIRE_UIT();
bool found = false;
ProxyList::iterator it = proxy_list_.begin();
for (; it != proxy_list_.end(); ++it) {
if (*it == proxy) {
proxy_list_.erase(it);
found = true;
break;
}
}
DCHECK(found);
}
bool CefBrowserContextImpl::HasProxy(
const content::BrowserContext* context) const {
CEF_REQUIRE_UIT();
ProxyList::const_iterator it = proxy_list_.begin();
for (; it != proxy_list_.end(); ++it) {
if (*it == context)
return true;
}
return false;
}
// static
scoped_refptr<CefBrowserContextImpl> CefBrowserContextImpl::GetForCachePath(
const base::FilePath& cache_path) {
return g_manager.Get().GetImpl(cache_path);
return g_manager.Get().GetImplForPath(cache_path);
}
// static
CefRefPtr<CefBrowserContextImpl> CefBrowserContextImpl::GetForContext(
content::BrowserContext* context) {
return g_manager.Get().GetImplForContext(context);
}
// static
std::vector<CefBrowserContextImpl*> CefBrowserContextImpl::GetAll() {
return g_manager.Get().GetAllImpl();
}
base::FilePath CefBrowserContextImpl::GetPath() const {
@ -181,7 +274,8 @@ net::URLRequestContextGetter*
}
content::BrowserPluginGuestManager* CefBrowserContextImpl::GetGuestManager() {
return NULL;
DCHECK(extensions::ExtensionsEnabled());
return guest_view::GuestViewManager::FromBrowserContext(this);
}
storage::SpecialStoragePolicy*
@ -207,10 +301,6 @@ content::PermissionManager* CefBrowserContextImpl::GetPermissionManager() {
return permission_manager_.get();
}
bool CefBrowserContextImpl::IsProxy() const {
return false;
}
const CefRequestContextSettings& CefBrowserContextImpl::GetSettings() const {
return settings_;
}

View File

@ -20,6 +20,7 @@ class DownloadManagerDelegate;
class SpeechRecognitionPreferences;
}
class CefBrowserContextProxy;
class CefDownloadManagerDelegate;
class CefSSLHostStateDelegate;
@ -36,8 +37,20 @@ class CefBrowserContextImpl : public CefBrowserContext {
static scoped_refptr<CefBrowserContextImpl> GetForCachePath(
const base::FilePath& cache_path);
// Returns the underlying CefBrowserContextImpl if any.
static CefRefPtr<CefBrowserContextImpl> GetForContext(
content::BrowserContext* context);
// Returns all existing CefBrowserContextImpl.
static std::vector<CefBrowserContextImpl*> GetAll();
// Must be called immediately after this object is created.
void Initialize();
void Initialize() override;
// Track associated proxy objects.
void AddProxy(const CefBrowserContextProxy* proxy);
void RemoveProxy(const CefBrowserContextProxy* proxy);
bool HasProxy(const content::BrowserContext* context) const;
// BrowserContext methods.
base::FilePath GetPath() const override;
@ -62,7 +75,6 @@ class CefBrowserContextImpl : public CefBrowserContext {
content::PermissionManager* GetPermissionManager() override;
// CefBrowserContext methods.
bool IsProxy() const override;
const CefRequestContextSettings& GetSettings() const override;
CefRefPtr<CefRequestContextHandler> GetHandler() const override;
net::URLRequestContextGetter* CreateRequestContext(
@ -93,6 +105,10 @@ class CefBrowserContextImpl : public CefBrowserContext {
CefRequestContextSettings settings_;
base::FilePath cache_path_;
// Not owned by this class.
typedef std::vector<const CefBrowserContextProxy*> ProxyList;
ProxyList proxy_list_;
scoped_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
scoped_ptr<CefDownloadManagerDelegate> download_manager_delegate_;

View File

@ -19,9 +19,11 @@ CefBrowserContextProxy::CefBrowserContextProxy(
parent_(parent) {
DCHECK(handler_.get());
DCHECK(parent_.get());
parent_->AddProxy(this);
}
CefBrowserContextProxy::~CefBrowserContextProxy() {
parent_->RemoveProxy(this);
}
base::FilePath CefBrowserContextProxy::GetPath() const {
@ -99,10 +101,6 @@ content::PermissionManager* CefBrowserContextProxy::GetPermissionManager() {
return parent_->GetPermissionManager();
}
bool CefBrowserContextProxy::IsProxy() const {
return true;
}
const CefRequestContextSettings& CefBrowserContextProxy::GetSettings() const {
return parent_->GetSettings();
}

View File

@ -52,7 +52,6 @@ class CefBrowserContextProxy : public CefBrowserContext {
content::PermissionManager* GetPermissionManager() override;
// CefBrowserContext methods.
bool IsProxy() const override;
const CefRequestContextSettings& GetSettings() const override;
CefRefPtr<CefRequestContextHandler> GetHandler() const override;
net::URLRequestContextGetter* CreateRequestContext(

View File

@ -16,6 +16,7 @@
#include "libcef/browser/context.h"
#include "libcef/browser/devtools_delegate.h"
#include "libcef/browser/devtools_frontend.h"
#include "libcef/browser/extensions/browser_extensions_util.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/navigate_params.h"
#include "libcef/browser/navigation_entry_impl.h"
@ -28,6 +29,7 @@
#include "libcef/common/cef_messages.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/drag_data_impl.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/http_header_utils.h"
#include "libcef/common/main_delegate.h"
#include "libcef/common/process_message_impl.h"
@ -73,6 +75,63 @@
namespace {
// Manages the global list of Impl instances.
class ImplManager {
public:
typedef std::vector<CefBrowserHostImpl*> Vector;
ImplManager() {}
~ImplManager() {
DCHECK(all_.empty());
}
void AddImpl(CefBrowserHostImpl* impl) {
CEF_REQUIRE_UIT();
DCHECK(!IsValidImpl(impl));
all_.push_back(impl);
}
void RemoveImpl(CefBrowserHostImpl* impl) {
CEF_REQUIRE_UIT();
Vector::iterator it = GetImplPos(impl);
DCHECK(it != all_.end());
all_.erase(it);
}
bool IsValidImpl(const CefBrowserHostImpl* impl) {
CEF_REQUIRE_UIT();
return GetImplPos(impl) != all_.end();
}
CefBrowserHostImpl* GetImplForWebContents(
const content::WebContents* web_contents) {
CEF_REQUIRE_UIT();
Vector::const_iterator it = all_.begin();
for (; it != all_.end(); ++it) {
if ((*it)->web_contents() == web_contents)
return *it;
}
return NULL;
}
private:
Vector::iterator GetImplPos(const CefBrowserHostImpl* impl) {
Vector::iterator it = all_.begin();
for (; it != all_.end(); ++it) {
if (*it == impl)
return it;
}
return all_.end();
}
Vector all_;
DISALLOW_COPY_AND_ASSIGN(ImplManager);
};
base::LazyInstance<ImplManager> g_manager = LAZY_INSTANCE_INITIALIZER;
class CreateBrowserHelper {
public:
CreateBrowserHelper(const CefWindowInfo& windowInfo,
@ -520,7 +579,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForHost(
content::WebContents* web_contents =
content::WebContents::FromRenderViewHost(host);
if (web_contents)
return static_cast<CefBrowserHostImpl*>(web_contents->GetDelegate());
return GetBrowserForContents(web_contents);
return NULL;
}
@ -533,21 +592,20 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForHost(
content::WebContents::FromRenderFrameHost(
const_cast<content::RenderFrameHost*>(host));
if (web_contents)
return static_cast<CefBrowserHostImpl*>(web_contents->GetDelegate());
return GetBrowserForContents(web_contents);
return NULL;
}
// static
CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForContents(
content::WebContents* contents) {
const content::WebContents* contents) {
DCHECK(contents);
CEF_REQUIRE_UIT();
return static_cast<CefBrowserHostImpl*>(contents->GetDelegate());
return g_manager.Get().GetImplForWebContents(contents);
}
// static
CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForRequest(
net::URLRequest* request) {
const net::URLRequest* request) {
DCHECK(request);
CEF_REQUIRE_IOT();
int render_process_id = -1;
@ -584,7 +642,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForView(
render_routing_id);
if (info.get()) {
CefRefPtr<CefBrowserHostImpl> browser = info->browser();
if (!browser.get()) {
if (!browser.get() && !info->is_mime_handler_view()) {
LOG(WARNING) << "Found browser id " << info->browser_id() <<
" but no browser object matching view process id " <<
render_process_id << " and routing id " <<
@ -617,7 +675,7 @@ CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForFrame(
render_routing_id);
if (info.get()) {
CefRefPtr<CefBrowserHostImpl> browser = info->browser();
if (!browser.get()) {
if (!browser.get() && !info->is_mime_handler_view()) {
LOG(WARNING) << "Found browser id " << info->browser_id() <<
" but no browser object matching frame process id " <<
render_process_id << " and routing id " <<
@ -836,10 +894,11 @@ void CefBrowserHostImpl::StartDownload(const CefString& url) {
void CefBrowserHostImpl::Print() {
if (CEF_CURRENTLY_ON_UIT()) {
if (!web_contents_)
content::WebContents* actionable_contents = GetActionableWebContents();
if (!actionable_contents)
return;
printing::PrintViewManager::FromWebContents(
web_contents_.get())->PrintNow();
actionable_contents)->PrintNow();
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::Print, this));
@ -850,7 +909,8 @@ void CefBrowserHostImpl::PrintToPDF(const CefString& path,
const CefPdfPrintSettings& settings,
CefRefPtr<CefPdfPrintCallback> callback) {
if (CEF_CURRENTLY_ON_UIT()) {
if (!web_contents_)
content::WebContents* actionable_contents = GetActionableWebContents();
if (!actionable_contents)
return;
printing::PrintViewManager::PdfPrintCallback pdf_callback;
@ -858,7 +918,7 @@ void CefBrowserHostImpl::PrintToPDF(const CefString& path,
pdf_callback = base::Bind(&CefPdfPrintCallback::OnPdfPrintFinished,
callback.get(), path);
}
printing::PrintViewManager::FromWebContents(web_contents_.get())->
printing::PrintViewManager::FromWebContents(actionable_contents)->
PrintToPDF(base::FilePath(path), settings, pdf_callback);
} else {
CEF_POST_TASK(CEF_UIT,
@ -1538,6 +1598,8 @@ void CefBrowserHostImpl::DestroyBrowser() {
queued_messages_.pop();
}
g_manager.Get().RemoveImpl(this);
registrar_.reset(NULL);
response_manager_.reset(NULL);
content::WebContentsObserver::Observe(NULL);
@ -2265,9 +2327,17 @@ bool CefBrowserHostImpl::TakeFocus(content::WebContents* source,
bool CefBrowserHostImpl::HandleContextMenu(
const content::ContextMenuParams& params) {
if (!menu_creator_.get())
menu_creator_.reset(new CefMenuCreator(this));
return menu_creator_->CreateContextMenu(params);
return HandleContextMenu(web_contents(), params);
}
content::WebContents* CefBrowserHostImpl::GetActionableWebContents() {
if (web_contents() && extensions::ExtensionsEnabled()) {
content::WebContents* guest_contents =
extensions::GetGuestForOwnerContents(web_contents());
if (guest_contents)
return guest_contents;
}
return web_contents();
}
bool CefBrowserHostImpl::PreHandleKeyboardEvent(
@ -2451,6 +2521,14 @@ void CefBrowserHostImpl::RunFileChooser(
web_contents, params.mode));
}
bool CefBrowserHostImpl::HandleContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params) {
if (!menu_creator_.get())
menu_creator_.reset(new CefMenuCreator(web_contents, this));
return menu_creator_->CreateContextMenu(params);
}
bool CefBrowserHostImpl::SetPendingPopupInfo(
scoped_ptr<PendingPopupInfo> info) {
base::AutoLock lock_scope(pending_popup_info_lock_);
@ -2911,6 +2989,8 @@ CefBrowserHostImpl::CefBrowserHostImpl(
web_contents_.reset(web_contents);
web_contents->SetDelegate(this);
g_manager.Get().AddImpl(this);
registrar_.reset(new content::NotificationRegistrar);
registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
content::Source<content::WebContents>(web_contents));

View File

@ -131,10 +131,10 @@ class CefBrowserHostImpl : public CefBrowserHost,
const content::RenderFrameHost* host);
// Returns the browser associated with the specified WebContents.
static CefRefPtr<CefBrowserHostImpl> GetBrowserForContents(
content::WebContents* contents);
const content::WebContents* contents);
// Returns the browser associated with the specified URLRequest.
static CefRefPtr<CefBrowserHostImpl> GetBrowserForRequest(
net::URLRequest* request);
const net::URLRequest* request);
// Returns the browser associated with the specified view routing IDs.
static CefRefPtr<CefBrowserHostImpl> GetBrowserForView(
int render_process_id, int render_routing_id);
@ -333,6 +333,16 @@ class CefBrowserHostImpl : public CefBrowserHost,
void RunFileChooser(const FileChooserParams& params,
const RunFileChooserCallback& callback);
bool HandleContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params);
// Returns the WebContents most likely to handle an action. If extensions are
// enabled and this browser has a full-page guest (for example, a full-page
// PDF viewer extension) then the guest's WebContents will be returned.
// Otherwise, the browser's WebContents will be returned.
content::WebContents* GetActionableWebContents();
// Used when creating a new popup window.
struct PendingPopupInfo {
CefWindowInfo window_info;

View File

@ -8,7 +8,8 @@
CefBrowserInfo::CefBrowserInfo(int browser_id, bool is_popup)
: browser_id_(browser_id),
is_popup_(is_popup),
is_windowless_(false) {
is_windowless_(false),
is_mime_handler_view_(false) {
DCHECK_GT(browser_id, 0);
}
@ -19,6 +20,10 @@ void CefBrowserInfo::set_windowless(bool windowless) {
is_windowless_ = windowless;
}
void CefBrowserInfo::set_mime_handler_view(bool mime_handler_view) {
is_mime_handler_view_ = mime_handler_view;
}
void CefBrowserInfo::add_render_view_id(
int render_process_id, int render_routing_id) {
add_render_id(&render_view_id_set_, render_process_id, render_routing_id);

View File

@ -24,8 +24,10 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
int browser_id() const { return browser_id_; };
bool is_popup() const { return is_popup_; }
bool is_windowless() const { return is_windowless_; }
bool is_mime_handler_view() const { return is_mime_handler_view_; }
void set_windowless(bool windowless);
void set_mime_handler_view(bool mime_handler_view);
// Adds an ID pair if it doesn't already exist.
void add_render_view_id(int render_process_id, int render_routing_id);
@ -62,6 +64,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
int browser_id_;
bool is_popup_;
bool is_windowless_;
bool is_mime_handler_view_;
base::Lock lock_;

View File

@ -12,7 +12,12 @@
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/devtools_delegate.h"
#include "libcef/browser/extensions/browser_context_keyed_service_factories.h"
#include "libcef/browser/extensions/extensions_browser_client.h"
#include "libcef/browser/extensions/extension_system_factory.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/extensions/extensions_client.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/net_resource_provider.h"
#include "base/bind.h"
@ -20,9 +25,12 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/web_ui_controller_factory.h"
#include "content/public/common/content_switches.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
#include "net/base/net_module.h"
#include "ui/base/resource/resource_bundle.h"
@ -123,6 +131,20 @@ int CefBrowserMainParts::PreCreateThreads() {
}
void CefBrowserMainParts::PreMainMessageLoopRun() {
if (extensions::ExtensionsEnabled()) {
// Initialize extension global objects before creating the global
// BrowserContext.
extensions_client_.reset(new extensions::CefExtensionsClient());
extensions::ExtensionsClient::Set(extensions_client_.get());
extensions_browser_client_.reset(new extensions::CefExtensionsBrowserClient);
extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
// Register additional KeyedService factories here. See
// ChromeBrowserMainExtraPartsProfiles for details.
extensions::cef::EnsureBrowserContextKeyedServiceFactoriesBuilt();
extensions::CefExtensionSystemFactory::GetInstance();
}
CefRequestContextSettings settings;
CefContext::Get()->PopulateRequestContextSettings(&settings);
@ -150,6 +172,11 @@ void CefBrowserMainParts::PreMainMessageLoopRun() {
}
void CefBrowserMainParts::PostMainMessageLoopRun() {
if (extensions::ExtensionsEnabled()) {
extensions::ExtensionsBrowserClient::Set(NULL);
extensions_browser_client_.reset();
}
if (devtools_delegate_) {
devtools_delegate_->Stop();
devtools_delegate_ = NULL;

View File

@ -27,6 +27,11 @@ namespace content {
struct MainFunctionParams;
}
namespace extensions {
class ExtensionsBrowserClient;
class ExtensionsClient;
}
class CefDevToolsDelegate;
class CefBrowserMainParts : public content::BrowserMainParts {
@ -63,6 +68,9 @@ class CefBrowserMainParts : public content::BrowserMainParts {
scoped_refptr<CefBrowserPrefStore> pref_store_;
scoped_ptr<PrefService> pref_service_;
scoped_ptr<extensions::ExtensionsClient> extensions_client_;
scoped_ptr<extensions::ExtensionsBrowserClient> extensions_browser_client_;
DISALLOW_COPY_AND_ASSIGN(CefBrowserMainParts);
};

View File

@ -101,6 +101,7 @@ void CefBrowserMessageFilter::OnGetNewBrowserInfo(
params->browser_id = info->browser_id();
params->is_popup = info->is_popup();
params->is_windowless = info->is_windowless();
params->is_mime_handler_view = info->is_mime_handler_view();
}
void CefBrowserMessageFilter::OnCreateWindow(

View File

@ -18,6 +18,8 @@
#include "chrome/browser/prefs/proxy_config_dictionary.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "extensions/browser/extension_prefs.h"
#include "grit/cef_strings.h"
#include "ui/base/l10n/l10n_util.h"
@ -82,11 +84,13 @@ scoped_ptr<PrefService> CefBrowserPrefStore::CreateService() {
new CommandLinePrefStore(command_line));
factory.set_user_prefs(this);
scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
scoped_refptr< user_prefs::PrefRegistrySyncable> registry(
new user_prefs::PrefRegistrySyncable());
// Default settings.
CefMediaCaptureDevicesDispatcher::RegisterPrefs(registry.get());
PrefProxyConfigTrackerImpl::RegisterPrefs(registry.get());
extensions::ExtensionPrefs::RegisterProfilePrefs(registry.get());
// Print settings.
registry->RegisterBooleanPref(prefs::kPrintingEnabled, true);

View File

@ -31,6 +31,9 @@
#include "grit/cef_resources.h"
#include "ipc/ipc_channel.h"
#include "net/url_request/url_request.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/resources/grit/webui_resources.h"
#include "ui/resources/grit/webui_resources_map.h"
#include "v8/include/v8.h"
namespace scheme {
@ -41,12 +44,14 @@ namespace {
const char kChromeCreditsDomain[] = "credits";
const char kChromeLicenseDomain[] = "license";
const char kChromeResourcesDomain[] = "resources";
const char kChromeVersionDomain[] = "version";
enum ChromeDomain {
CHROME_UNKNOWN = 0,
CHROME_CREDITS,
CHROME_LICENSE,
CHROME_RESOURCES,
CHROME_VERSION,
};
@ -57,6 +62,7 @@ ChromeDomain GetChromeDomain(const std::string& domain_name) {
} domains[] = {
{ kChromeCreditsDomain, CHROME_CREDITS },
{ kChromeLicenseDomain, CHROME_LICENSE },
{ kChromeResourcesDomain, CHROME_RESOURCES },
{ kChromeVersionDomain, CHROME_VERSION },
};
@ -177,6 +183,48 @@ class TemplateParser {
std::string ident_end_;
};
// From content/browser/webui/shared_resources_data_source.cc.
using ResourcesMap = base::hash_map<std::string, int>;
// TODO(rkc): Once we have a separate source for apps, remove '*/apps/' aliases.
const char* kPathAliases[][2] = {
{"../../../third_party/polymer/v1_0/components-chromium/", "polymer/v1_0/"},
{"../../../third_party/web-animations-js/sources/",
"polymer/v1_0/web-animations-js/"},
{"../../views/resources/default_100_percent/common/", "images/apps/"},
{"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
{"../../webui/resources/cr_elements/", "cr_elements/"}};
void AddResource(const std::string& path,
int resource_id,
ResourcesMap* resources_map) {
if (!resources_map->insert(std::make_pair(path, resource_id)).second)
NOTREACHED() << "Redefinition of '" << path << "'";
}
const ResourcesMap* CreateResourcesMap() {
ResourcesMap* result = new ResourcesMap();
for (size_t i = 0; i < kWebuiResourcesSize; ++i) {
const std::string resource_name = kWebuiResources[i].name;
const int resource_id = kWebuiResources[i].value;
AddResource(resource_name, resource_id, result);
for (const char* (&alias)[2]: kPathAliases) {
if (StartsWithASCII(resource_name, alias[0], true)) {
AddResource(alias[1] + resource_name.substr(strlen(alias[0])),
resource_id, result);
}
}
}
return result;
}
const ResourcesMap& GetResourcesMap() {
// This pointer will be intentionally leaked on shutdown.
static const ResourcesMap* resources_map = CreateResourcesMap();
return *resources_map;
}
class Delegate : public InternalHandlerDelegate {
public:
Delegate() {}
@ -199,6 +247,9 @@ class Delegate : public InternalHandlerDelegate {
case CHROME_LICENSE:
handled = OnLicense(action);
break;
case CHROME_RESOURCES:
handled = OnResources(path, action);
break;
case CHROME_VERSION:
handled = OnVersion(browser, action);
break;
@ -209,11 +260,15 @@ class Delegate : public InternalHandlerDelegate {
if (!handled && domain != CHROME_VERSION) {
LOG(INFO) << "Reguest for unknown chrome resource: " <<
url.spec().c_str();
action->redirect_url =
GURL(std::string(kChromeURL) + kChromeVersionDomain);
if (domain != CHROME_RESOURCES) {
action->redirect_url =
GURL(std::string(kChromeURL) + kChromeVersionDomain);
return true;
}
}
return true;
return handled;
}
bool OnCredits(const std::string& path, Action* action) {
@ -245,6 +300,31 @@ class Delegate : public InternalHandlerDelegate {
return true;
}
bool OnResources(const std::string& path, Action* action) {
// Implementation based on SharedResourcesDataSource::StartDataRequest.
const ResourcesMap& resources_map = GetResourcesMap();
auto it = resources_map.find(path);
int resource_id = (it != resources_map.end()) ? it->second : -1;
if (resource_id == -1) {
NOTREACHED() << "Failed to find resource id for " << path;
return false;
}
if (resource_id == IDR_WEBUI_CSS_TEXT_DEFAULTS) {
const std::string& css = webui::GetWebUiCssTextDefaults();
DCHECK(!css.empty());
action->mime_type = "text/css";
action->stream = CefStreamReader::CreateForData(
const_cast<char*>(css.c_str()), css.length());
action->stream_size = css.length();
} else {
action->resource_id = resource_id;
}
return true;
}
bool OnVersion(CefRefPtr<CefBrowser> browser,
Action* action) {
base::StringPiece piece = CefContentClient::Get()->GetDataResource(
@ -273,8 +353,8 @@ class Delegate : public InternalHandlerDelegate {
parser.Add("USERAGENT", CefContentClient::Get()->GetUserAgent());
parser.Add("COMMANDLINE", GetCommandLine());
parser.Add("MODULEPATH", GetModulePath());
parser.Add("CACHEPATH",
browser->GetHost()->GetRequestContext()->GetCachePath());
parser.Add("CACHEPATH", browser.get() ?
browser->GetHost()->GetRequestContext()->GetCachePath() : "");
std::string tmpl = piece.as_string();
parser.Parse(&tmpl);

View File

@ -14,6 +14,9 @@
#include "libcef/browser/chrome_scheme_handler.h"
#include "libcef/browser/context.h"
#include "libcef/browser/devtools_delegate.h"
#include "libcef/browser/extensions/browser_extensions_util.h"
#include "libcef/browser/extensions/extension_system.h"
#include "libcef/browser/extensions/plugin_info_message_filter.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/pepper/browser_pepper_host_factory.h"
#include "libcef/browser/printing/printing_message_filter.h"
@ -22,9 +25,11 @@
#include "libcef/browser/ssl_info_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/web_plugin_impl.h"
#include "libcef/common/cef_messages.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/command_line_impl.h"
#include "libcef/common/content_client.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/scheme_registration.h"
#include "base/base_switches.h"
@ -46,6 +51,12 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/storage_quota_params.h"
#include "content/public/common/web_preferences.h"
#include "extensions/browser/extension_message_filter.h"
#include "extensions/browser/extension_protocols.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
#include "extensions/browser/io_thread_extension_message_filter.h"
#include "extensions/common/constants.h"
#include "gin/v8_initializer.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
@ -561,6 +572,49 @@ void CefContentBrowserClient::RenderProcessWillLaunch(
host->AddFilter(new SpellCheckMessageFilterMac(id));
#endif
}
content::BrowserContext* browser_context = host->GetBrowserContext();
if (extensions::ExtensionsEnabled()) {
host->AddFilter(
new extensions::CefPluginInfoMessageFilter(id, browser_context));
host->AddFilter(
new extensions::ExtensionMessageFilter(id, browser_context));
host->AddFilter(
new extensions::IOThreadExtensionMessageFilter(id, browser_context));
host->AddFilter(
new extensions::ExtensionsGuestViewMessageFilter(id, browser_context));
}
host->Send(new CefProcessMsg_SetIsIncognitoProcess(
browser_context->IsOffTheRecord()));
}
bool CefContentBrowserClient::ShouldUseProcessPerSite(
content::BrowserContext* browser_context,
const GURL& effective_url) {
if (!extensions::ExtensionsEnabled())
return false;
if (!effective_url.SchemeIs(extensions::kExtensionScheme))
return false;
extensions::ExtensionRegistry* registry =
extensions::ExtensionRegistry::Get(browser_context);
if (!registry)
return false;
const extensions::Extension* extension =
registry->enabled_extensions().GetByID(effective_url.host());
if (!extension)
return false;
// TODO(extensions): Extra checks required if type is TYPE_HOSTED_APP.
// Hosted apps that have script access to their background page must use
// process per site, since all instances can make synchronous calls to the
// background window. Other extensions should use process per site as well.
return true;
}
net::URLRequestContextGetter* CefContentBrowserClient::CreateRequestContext(
@ -569,6 +623,19 @@ net::URLRequestContextGetter* CefContentBrowserClient::CreateRequestContext(
content::URLRequestInterceptorScopedVector request_interceptors) {
scoped_refptr<CefBrowserContext> context =
static_cast<CefBrowserContext*>(content_browser_context);
if (extensions::ExtensionsEnabled()) {
// Handle only chrome-extension:// requests. CEF does not support
// chrome-extension-resource:// requests (it does not store shared extension
// data in its installation directory).
extensions::InfoMap* extension_info_map =
context->extension_system()->info_map();
(*protocol_handlers)[extensions::kExtensionScheme] =
linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
extensions::CreateExtensionProtocolHandler(
context->IsOffTheRecord(), extension_info_map));
}
return context->CreateRequestContext(
protocol_handlers,
request_interceptors.Pass());
@ -635,6 +702,8 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
// any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
switches::kContextSafetyImplementation,
switches::kDisableExtensions,
switches::kDisablePdfExtension,
switches::kDisableScrollBounce,
switches::kDisableSpellChecking,
switches::kEnableSpeechInput,
@ -802,11 +871,8 @@ bool CefContentBrowserClient::CanCreateWindow(
CefBrowserHostImpl::GetBrowserForView(
last_create_window_params_.opener_process_id,
last_create_window_params_.opener_view_id);
DCHECK(browser.get());
if (!browser.get()) {
LOG(WARNING) << "CanCreateWindow called before browser was created";
if (!browser.get())
return false;
}
CefRefPtr<CefClient> client = browser->GetClient();
bool allow = true;
@ -886,12 +952,20 @@ void CefContentBrowserClient::OverrideWebkitPrefs(
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForHost(rvh);
DCHECK(browser.get());
if (!browser.get() && extensions::ExtensionsEnabled()) {
// Retrieve the owner browser, if any.
content::WebContents* owner = extensions::GetOwnerForGuestContents(
content::WebContents::FromRenderViewHost(rvh));
if (owner)
browser = CefBrowserHostImpl::GetBrowserForContents(owner);
}
// Populate WebPreferences based on CefBrowserSettings.
BrowserToWebSettings(browser->settings(), *prefs);
if (browser.get()) {
// Populate WebPreferences based on CefBrowserSettings.
BrowserToWebSettings(browser->settings(), *prefs);
}
prefs->base_background_color = GetBaseBackgroundColor(rvh);
prefs->base_background_color = GetBaseBackgroundColor(browser);
if (rvh->GetView())
rvh->GetView()->SetBackgroundColor(prefs->base_background_color);
@ -1013,27 +1087,26 @@ PrefService* CefContentBrowserClient::pref_service() const {
return browser_main_parts_->pref_service();
}
// static
SkColor CefContentBrowserClient::GetBaseBackgroundColor(
content::RenderViewHost* rvh) {
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForHost(rvh);
DCHECK(browser.get());
const CefBrowserSettings& browser_settings = browser->settings();
if (CefColorGetA(browser_settings.background_color) > 0) {
return SkColorSetRGB(
CefColorGetR(browser_settings.background_color),
CefColorGetG(browser_settings.background_color),
CefColorGetB(browser_settings.background_color));
} else {
const CefSettings& settings = CefContext::Get()->settings();
if (CefColorGetA(settings.background_color) > 0) {
CefRefPtr<CefBrowserHostImpl> browser) {
if (browser.get()) {
const CefBrowserSettings& browser_settings = browser->settings();
if (CefColorGetA(browser_settings.background_color) > 0) {
return SkColorSetRGB(
CefColorGetR(settings.background_color),
CefColorGetG(settings.background_color),
CefColorGetB(settings.background_color));
CefColorGetR(browser_settings.background_color),
CefColorGetG(browser_settings.background_color),
CefColorGetB(browser_settings.background_color));
}
}
const CefSettings& settings = CefContext::Get()->settings();
if (CefColorGetA(settings.background_color) > 0) {
return SkColorSetRGB(
CefColorGetR(settings.background_color),
CefColorGetG(settings.background_color),
CefColorGetB(settings.background_color));
}
return SK_ColorWHITE;
}

View File

@ -24,6 +24,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "url/gurl.h"
class CefBrowserHostImpl;
class CefBrowserInfo;
class CefBrowserMainParts;
class CefDevToolsDelegate;
@ -73,6 +74,8 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
const content::MainFunctionParams& parameters) override;
void RenderProcessWillLaunch(
content::RenderProcessHost* host) override;
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
const GURL& effective_url) override;
net::URLRequestContextGetter* CreateRequestContext(
content::BrowserContext* browser_context,
content::ProtocolHandlerMap* protocol_handlers,
@ -165,7 +168,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
PrefService* pref_service() const;
private:
SkColor GetBaseBackgroundColor(content::RenderViewHost* rvh);
static SkColor GetBaseBackgroundColor(CefRefPtr<CefBrowserHostImpl> browser);
CefBrowserMainParts* browser_main_parts_;

View File

@ -0,0 +1,21 @@
# 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.
{
'targets': [
{
'target_name': 'cef_api_registration',
'type': 'static_library',
# TODO(jschuh): http://crbug.com/167187 size_t -> int
'msvs_disabled_warnings': [ 4267 ],
'includes': [
'../../../../../build/json_schema_bundle_registration_compile.gypi',
'../../../common/extensions/api/schemas.gypi',
],
'dependencies': [
'../../../common/extensions/api/api.gyp:cef_api',
],
},
],
}

View File

@ -0,0 +1,175 @@
// 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.
#include "libcef/browser/extensions/api/streams_private/streams_private_api.h"
#include "base/lazy_instance.h"
#include "base/values.h"
#include "cef/libcef/common/extensions/api/streams_private.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/stream_info.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "net/http/http_response_headers.h"
namespace extensions {
namespace {
void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
base::DictionaryValue* result) {
if (!headers)
return;
void* iter = NULL;
std::string header_name;
std::string header_value;
while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
base::Value* existing_value = NULL;
if (result->Get(header_name, &existing_value)) {
base::StringValue* existing_string_value =
static_cast<base::StringValue*>(existing_value);
existing_string_value->GetString()->append(", ").append(header_value);
} else {
result->SetString(header_name, header_value);
}
}
}
} // namespace
namespace streams_private = api::streams_private;
// static
StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) {
return GetFactoryInstance()->Get(context);
}
StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context)
: browser_context_(context),
extension_registry_observer_(this),
weak_ptr_factory_(this) {
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
}
StreamsPrivateAPI::~StreamsPrivateAPI() {
}
void StreamsPrivateAPI::ExecuteMimeTypeHandler(
const std::string& extension_id,
int tab_id,
scoped_ptr<content::StreamInfo> stream,
const std::string& view_id,
int64 expected_content_size,
bool embedded,
int render_process_id,
int render_frame_id) {
const Extension* extension = ExtensionRegistry::Get(browser_context_)
->enabled_extensions()
.GetByID(extension_id);
if (!extension)
return;
MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
// If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
// will take ownership of the stream. Otherwise, store the stream handle in
// |streams_| and fire an event notifying the extension.
if (!handler->handler_url().empty()) {
GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() +
handler->handler_url());
scoped_ptr<StreamContainer> stream_container(new StreamContainer(
stream.Pass(), tab_id, embedded, handler_url, extension_id));
MimeHandlerStreamManager::Get(browser_context_)
->AddStream(view_id, stream_container.Pass(), render_process_id,
render_frame_id);
return;
}
// Create the event's arguments value.
streams_private::StreamInfo info;
info.mime_type = stream->mime_type;
info.original_url = stream->original_url.spec();
info.stream_url = stream->handle->GetURL().spec();
info.tab_id = tab_id;
info.embedded = embedded;
if (!view_id.empty()) {
info.view_id.reset(new std::string(view_id));
}
int size = -1;
if (expected_content_size <= INT_MAX)
size = expected_content_size;
info.expected_content_size = size;
CreateResponseHeadersDictionary(stream->response_headers.get(),
&info.response_headers.additional_properties);
scoped_ptr<Event> event(
new Event(streams_private::OnExecuteMimeTypeHandler::kEventName,
streams_private::OnExecuteMimeTypeHandler::Create(info)));
EventRouter::Get(browser_context_)
->DispatchEventToExtension(extension_id, event.Pass());
GURL url = stream->handle->GetURL();
streams_[extension_id][url] = make_linked_ptr(stream->handle.release());
}
void StreamsPrivateAPI::AbortStream(const std::string& extension_id,
const GURL& stream_url,
const base::Closure& callback) {
StreamMap::iterator extension_it = streams_.find(extension_id);
if (extension_it == streams_.end()) {
callback.Run();
return;
}
StreamMap::mapped_type* url_map = &extension_it->second;
StreamMap::mapped_type::iterator url_it = url_map->find(stream_url);
if (url_it == url_map->end()) {
callback.Run();
return;
}
url_it->second->AddCloseListener(callback);
url_map->erase(url_it);
}
void StreamsPrivateAPI::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
streams_.erase(extension->id());
}
StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() {
}
ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_));
StreamsPrivateAPI::Get(browser_context())->AbortStream(
extension_id(), GURL(stream_url_), base::Bind(
&StreamsPrivateAbortFunction::OnClose, this));
return RespondLater();
}
void StreamsPrivateAbortFunction::OnClose() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Respond(NoArguments());
}
static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<StreamsPrivateAPI>*
StreamsPrivateAPI::GetFactoryInstance() {
return g_factory.Pointer();
}
} // namespace extensions

View File

@ -0,0 +1,104 @@
// 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.
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
#include <map>
#include <string>
#include "base/scoped_observer.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry_observer.h"
namespace content {
class BrowserContext;
class StreamHandle;
struct StreamInfo;
}
namespace extensions {
class ExtensionRegistry;
class StreamsPrivateAPI : public BrowserContextKeyedAPI,
public ExtensionRegistryObserver {
public:
// Convenience method to get the StreamsPrivateAPI for a BrowserContext.
static StreamsPrivateAPI* Get(content::BrowserContext* context);
explicit StreamsPrivateAPI(content::BrowserContext* context);
~StreamsPrivateAPI() override;
// Send the onExecuteMimeTypeHandler event to |extension_id|.
// |tab_id| is used to determine the tabId where the document is being
// opened. The data for the document will be readable from |stream|, and
// should be |expected_content_size| bytes long. If the viewer is being opened
// in a BrowserPlugin, specify a non-empty |view_id| of the plugin. |embedded|
// should be set to whether the document is embedded within another document.
void ExecuteMimeTypeHandler(const std::string& extension_id,
int tab_id,
scoped_ptr<content::StreamInfo> stream,
const std::string& view_id,
int64 expected_content_size,
bool embedded,
int render_process_id,
int render_frame_id);
void AbortStream(const std::string& extension_id,
const GURL& stream_url,
const base::Closure& callback);
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<StreamsPrivateAPI>* GetFactoryInstance();
private:
friend class BrowserContextKeyedAPIFactory<StreamsPrivateAPI>;
typedef std::map<std::string,
std::map<GURL,
linked_ptr<content::StreamHandle> > > StreamMap;
// ExtensionRegistryObserver implementation.
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) override;
// BrowserContextKeyedAPI implementation.
static const char* service_name() {
return "StreamsPrivateAPI";
}
static const bool kServiceIsNULLWhileTesting = true;
static const bool kServiceRedirectedInIncognito = true;
content::BrowserContext* const browser_context_;
StreamMap streams_;
// Listen to extension unloaded notifications.
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
base::WeakPtrFactory<StreamsPrivateAPI> weak_ptr_factory_;
};
class StreamsPrivateAbortFunction : public UIThreadExtensionFunction {
public:
StreamsPrivateAbortFunction();
DECLARE_EXTENSION_FUNCTION("streamsPrivate.abort", STREAMSPRIVATE_ABORT)
protected:
~StreamsPrivateAbortFunction() override {}
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
private:
void OnClose();
std::string stream_url_;
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_

View File

@ -0,0 +1,20 @@
// Copyright 2015 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_context_keyed_service_factories.h"
#include "libcef/browser/extensions/api/streams_private/streams_private_api.h"
#include "extensions/browser/renderer_startup_helper.h"
namespace extensions {
namespace cef {
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
RendererStartupHelperFactory::GetInstance();
StreamsPrivateAPI::GetFactoryInstance();
}
} // namespace cef
} // namespace extensions

View File

@ -0,0 +1,19 @@
// Copyright 2015 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_EXTENSIONS_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_
namespace extensions {
namespace cef {
// Ensures the existence of any BrowserContextKeyedServiceFactory provided by
// the CEF extensions code or otherwise required by CEF. See
// libcef/common/extensions/api/README.txt for additional details.
void EnsureBrowserContextKeyedServiceFactoriesBuilt();
} // namespace cef
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_

View File

@ -0,0 +1,35 @@
// Copyright (c) 2015 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_extensions_util.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/web_contents/web_contents_impl.h"
namespace extensions {
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest) {
content::WebContentsImpl* guest_impl =
static_cast<content::WebContentsImpl*>(guest);
content::BrowserPluginEmbedder* embedder =
guest_impl->GetBrowserPluginEmbedder();
if (embedder) {
content::BrowserPluginGuest* guest = embedder->GetFullPageGuest();
if (guest)
return guest->web_contents();
}
return NULL;
}
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner) {
content::WebContentsImpl* owner_impl =
static_cast<content::WebContentsImpl*>(owner);
content::BrowserPluginGuest* guest = owner_impl->GetBrowserPluginGuest();
if (guest)
return guest->embedder_web_contents();
return NULL;
}
} // namespace extensions

View File

@ -0,0 +1,22 @@
// Copyright (c) 2015 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_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_
namespace content {
class WebContents;
}
namespace extensions {
// Returns the WebContents that owns the specified |guest|, if any.
content::WebContents* GetGuestForOwnerContents(content::WebContents* guest);
// Returns the guest WebContents for the specified |owner|, if any.
content::WebContents* GetOwnerForGuestContents(content::WebContents* owner);
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_BROWSER_EXTENSIONS_UTIL_H_

View File

@ -0,0 +1,58 @@
// 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/component_extension_resource_manager.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "grit/component_extension_resources_map.h"
namespace extensions {
CefComponentExtensionResourceManager::CefComponentExtensionResourceManager() {
AddComponentResourceEntries(
kComponentExtensionResources,
kComponentExtensionResourcesSize);
}
CefComponentExtensionResourceManager::~CefComponentExtensionResourceManager() {}
bool CefComponentExtensionResourceManager::IsComponentExtensionResource(
const base::FilePath& extension_path,
const base::FilePath& resource_path,
int* resource_id) const {
base::FilePath directory_path = extension_path;
base::FilePath resources_dir;
base::FilePath relative_path;
if (!PathService::Get(chrome::DIR_RESOURCES, &resources_dir) ||
!resources_dir.AppendRelativePath(directory_path, &relative_path)) {
return false;
}
relative_path = relative_path.Append(resource_path);
relative_path = relative_path.NormalizePathSeparators();
std::map<base::FilePath, int>::const_iterator entry =
path_to_resource_id_.find(relative_path);
if (entry != path_to_resource_id_.end())
*resource_id = entry->second;
return entry != path_to_resource_id_.end();
}
void CefComponentExtensionResourceManager::AddComponentResourceEntries(
const GritResourceMap* entries,
size_t size) {
for (size_t i = 0; i < size; ++i) {
base::FilePath resource_path = base::FilePath().AppendASCII(
entries[i].name);
resource_path = resource_path.NormalizePathSeparators();
DCHECK(path_to_resource_id_.find(resource_path) ==
path_to_resource_id_.end());
path_to_resource_id_[resource_path] = entries[i].value;
}
}
} // namespace extensions

View File

@ -0,0 +1,41 @@
// 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_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
#include <map>
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "extensions/browser/component_extension_resource_manager.h"
struct GritResourceMap;
namespace extensions {
class CefComponentExtensionResourceManager
: public ComponentExtensionResourceManager {
public:
CefComponentExtensionResourceManager();
~CefComponentExtensionResourceManager() override;
// Overridden from ComponentExtensionResourceManager:
bool IsComponentExtensionResource(const base::FilePath& extension_path,
const base::FilePath& resource_path,
int* resource_id) const override;
private:
void AddComponentResourceEntries(const GritResourceMap* entries, size_t size);
// A map from a resource path to the resource ID. Used by
// IsComponentExtensionResource.
std::map<base::FilePath, int> path_to_resource_id_;
DISALLOW_COPY_AND_ASSIGN(CefComponentExtensionResourceManager);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_

View File

@ -0,0 +1,124 @@
// 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.
#include "libcef/browser/extensions/event_router_forwarder.h"
#include "libcef/browser/browser_context_impl.h"
#include "base/bind.h"
#include "base/values.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/event_router.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace extensions {
EventRouterForwarder::EventRouterForwarder() {
}
EventRouterForwarder::~EventRouterForwarder() {
}
void EventRouterForwarder::BroadcastEventToRenderers(
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
const GURL& event_url) {
HandleEvent(std::string(), event_name, event_args.Pass(), 0, true, event_url);
}
void EventRouterForwarder::DispatchEventToRenderers(
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile,
bool use_profile_to_restrict_events,
const GURL& event_url) {
if (!profile)
return;
HandleEvent(std::string(),
event_name,
event_args.Pass(),
profile,
use_profile_to_restrict_events,
event_url);
}
void EventRouterForwarder::BroadcastEventToExtension(
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
const GURL& event_url) {
HandleEvent(extension_id, event_name, event_args.Pass(), 0, true, event_url);
}
void EventRouterForwarder::DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile,
bool use_profile_to_restrict_events,
const GURL& event_url) {
if (!profile)
return;
HandleEvent(extension_id, event_name, event_args.Pass(), profile,
use_profile_to_restrict_events, event_url);
}
void EventRouterForwarder::HandleEvent(const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile_ptr,
bool use_profile_to_restrict_events,
const GURL& event_url) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&EventRouterForwarder::HandleEvent, this,
extension_id, event_name, base::Passed(&event_args),
profile_ptr, use_profile_to_restrict_events, event_url));
return;
}
content::BrowserContext* profile = NULL;
if (profile_ptr) {
profile = reinterpret_cast<content::BrowserContext*>(profile_ptr);
if (CefBrowserContextImpl::GetForContext(profile) == NULL)
return;
}
if (profile) {
CallEventRouter(profile, extension_id, event_name, event_args.Pass(),
use_profile_to_restrict_events ? profile : NULL, event_url);
} else {
std::vector<CefBrowserContextImpl*> profiles(
CefBrowserContextImpl::GetAll());
for (size_t i = 0; i < profiles.size(); ++i) {
scoped_ptr<base::ListValue> per_profile_event_args(
event_args->DeepCopy());
CallEventRouter(
profiles[i], extension_id, event_name, per_profile_event_args.Pass(),
use_profile_to_restrict_events ? profiles[i] : NULL, event_url);
}
}
}
void EventRouterForwarder::CallEventRouter(
content::BrowserContext* profile,
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
content::BrowserContext* restrict_to_profile,
const GURL& event_url) {
scoped_ptr<Event> event(new Event(event_name, event_args.Pass()));
event->restrict_to_browser_context = restrict_to_profile;
event->event_url = event_url;
if (extension_id.empty()) {
extensions::EventRouter::Get(profile)->BroadcastEvent(event.Pass());
} else {
extensions::EventRouter::Get(profile)
->DispatchEventToExtension(extension_id, event.Pass());
}
}
} // namespace extensions

View File

@ -0,0 +1,107 @@
// 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.
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EVENT_ROUTER_FORWARDER_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EVENT_ROUTER_FORWARDER_H_
#include <string>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
class GURL;
namespace content {
class BrowserContext;
}
namespace extensions {
// This class forwards events to EventRouters.
// The advantages of this class over direct usage of EventRouters are:
// - this class is thread-safe, you can call the functions from UI and IO
// thread.
// - the class can handle if a profile is deleted between the time of sending
// the event from the IO thread to the UI thread.
// - this class can be used in contexts that are not governed by a profile, e.g.
// by system URLRequestContexts. In these cases the |restrict_to_profile|
// parameter remains NULL and events are broadcasted to all profiles.
class EventRouterForwarder
: public base::RefCountedThreadSafe<EventRouterForwarder> {
public:
EventRouterForwarder();
// Calls
// DispatchEventToRenderers(event_name, event_args, profile, event_url)
// on all (original) profiles' EventRouters.
// May be called on any thread.
void BroadcastEventToRenderers(const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
const GURL& event_url);
// Calls
// DispatchEventToExtension(extension_id, event_name, event_args,
// profile, event_url)
// on all (original) profiles' EventRouters.
// May be called on any thread.
void BroadcastEventToExtension(const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
const GURL& event_url);
// Calls
// DispatchEventToRenderers(event_name, event_args,
// use_profile_to_restrict_events ? profile : NULL, event_url)
// on |profile|'s EventRouter. May be called on any thread.
void DispatchEventToRenderers(const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile,
bool use_profile_to_restrict_events,
const GURL& event_url);
// Calls
// DispatchEventToExtension(extension_id, event_name, event_args,
// use_profile_to_restrict_events ? profile : NULL, event_url)
// on |profile|'s EventRouter. May be called on any thread.
void DispatchEventToExtension(const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile,
bool use_profile_to_restrict_events,
const GURL& event_url);
protected:
// Protected for testing.
virtual ~EventRouterForwarder();
// Helper function for {Broadcast,Dispatch}EventTo{Extension,Renderers}.
// Virtual for testing.
virtual void HandleEvent(const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
void* profile,
bool use_profile_to_restrict_events,
const GURL& event_url);
// Calls DispatchEventToRenderers or DispatchEventToExtension (depending on
// whether extension_id == "" or not) of |profile|'s EventRouter.
// |profile| may never be NULL.
// Virtual for testing.
virtual void CallEventRouter(content::BrowserContext* profile,
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args,
content::BrowserContext* restrict_to_profile,
const GURL& event_url);
private:
friend class base::RefCountedThreadSafe<EventRouterForwarder>;
DISALLOW_COPY_AND_ASSIGN(EventRouterForwarder);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EVENT_ROUTER_FORWARDER_H_

View File

@ -0,0 +1,436 @@
// Copyright 2015 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_system.h"
#include <string>
#include "libcef/browser/extensions/pdf_extension_util.h"
#include "libcef/common/extensions/extensions_util.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h"
#include "base/path_service.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/common/chrome_paths.h"
#include "components/crx_file/id_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/api/app_runtime/app_runtime_api.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/info_map.h"
#include "extensions/browser/notification_types.h"
#include "extensions/browser/quota_service.h"
#include "extensions/browser/runtime_data.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "extensions/common/switches.h"
#include "net/base/mime_util.h"
using content::BrowserContext;
using content::BrowserThread;
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) {
JSONStringValueDeserializer deserializer(manifest_contents);
scoped_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
LOG(ERROR) << "Failed to parse extension manifest.";
return NULL;
}
// Transfer ownership to the caller.
return static_cast<base::DictionaryValue*>(manifest.release());
}
} // namespace
CefExtensionSystem::CefExtensionSystem(BrowserContext* browser_context)
: browser_context_(browser_context),
registry_(ExtensionRegistry::Get(browser_context)) {
}
CefExtensionSystem::~CefExtensionSystem() {
}
void CefExtensionSystem::Init() {
// There's complexity here related to the ordering of message delivery. For
// an extension to load correctly both the ExtensionMsg_Loaded and
// ExtensionMsg_ActivateExtension messages must be sent. These messages are
// currently sent by RendererStartupHelper, ExtensionWebContentsObserver, and
// this class. ExtensionMsg_Loaded is handled by Dispatcher::OnLoaded and adds
// the extension to |extensions_|. ExtensionMsg_ActivateExtension is handled
// by Dispatcher::OnActivateExtension and adds the extension to
// |active_extension_ids_|. If these messages are not sent correctly then
// ScriptContextSet::Register called from Dispatcher::DidCreateScriptContext
// will classify the extension incorrectly and API bindings will not be added.
// Inform the rest of the extensions system to start.
ready_.Signal();
content::NotificationService::current()->Notify(
NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
content::Source<BrowserContext>(browser_context_),
content::NotificationService::NoDetails());
// Add the built-in 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 with the below call to AddExtension.
// 3. A page requests a plugin to handle "application/pdf" mime type. This
// results in a call to CefContentRendererClient::OverrideCreatePlugin
// in the renderer process which calls CefContentRendererClient::
// CreateBrowserPluginDelegate indirectly to create a
// MimeHandlerViewContainer.
// 4. CefResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream
// intercepts the PDF load in the browser process, associates the load with
// the PDF extension and makes the PDF file contents available to the
// extension via the Stream API.
// 5. A MimeHandlerViewGuest and CefMimeHandlerViewGuestDelegate is created in
// the browser process.
// 6. MimeHandlerViewGuest navigates to the PDF extension URL.
// 7. PDF extension resources are provided from bundle via
// CefExtensionsBrowserClient::MaybeCreateResourceBundleRequestJob and
// CefComponentExtensionResourceManager.
// 8. The PDF extension communicates via the chrome.mimeHandlerPrivate Mojo
// API which is implemented as described in
// libcef/common/extensions/api/README.txt.
// 9. The PDF extension requests a plugin to handle
// kPDFPluginOutOfProcessMimeType which loads the PDF PPAPI plugin.
// 10.Routing of print-related commands are handled by ChromePDFPrintClient
// and CefPrintWebViewHelperDelegate in the renderer process.
if (PdfExtensionEnabled()) {
AddExtension(pdf_extension_util::GetManifest(),
base::FilePath(FILE_PATH_LITERAL("pdf")));
}
}
// Implementation based on ComponentLoader::Add.
const Extension* CefExtensionSystem::AddExtension(
const std::string& manifest_contents,
const base::FilePath& root_directory) {
base::DictionaryValue* manifest = ParseManifest(manifest_contents);
if (!manifest)
return NULL;
ComponentExtensionInfo info(manifest, root_directory);
const Extension* extension = LoadExtension(info);
delete manifest;
return extension;
}
// Implementation based on ExtensionService::RemoveComponentExtension.
void CefExtensionSystem::RemoveExtension(const std::string& extension_id) {
scoped_refptr<const Extension> extension(
registry_->enabled_extensions().GetByID(extension_id));
UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_UNINSTALL);
if (extension.get()) {
registry_->TriggerOnUninstalled(
extension.get(), extensions::UNINSTALL_REASON_COMPONENT_REMOVED);
}
}
void CefExtensionSystem::Shutdown() {
}
void CefExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
runtime_data_.reset(new RuntimeData(registry_));
quota_service_.reset(new QuotaService);
}
ExtensionService* CefExtensionSystem::extension_service() {
return nullptr;
}
RuntimeData* CefExtensionSystem::runtime_data() {
return runtime_data_.get();
}
ManagementPolicy* CefExtensionSystem::management_policy() {
return nullptr;
}
SharedUserScriptMaster* CefExtensionSystem::shared_user_script_master() {
return nullptr;
}
StateStore* CefExtensionSystem::state_store() {
return nullptr;
}
StateStore* CefExtensionSystem::rules_store() {
return nullptr;
}
InfoMap* CefExtensionSystem::info_map() {
if (!info_map_.get())
info_map_ = new InfoMap;
return info_map_.get();
}
QuotaService* CefExtensionSystem::quota_service() {
return quota_service_.get();
}
// Implementation based on
// ExtensionSystemImpl::RegisterExtensionWithRequestContexts.
void CefExtensionSystem::RegisterExtensionWithRequestContexts(
const Extension* extension) {
// TODO(extensions): The |incognito_enabled| value should be set based on
// manifest settings.
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&InfoMap::AddExtension,
info_map(),
make_scoped_refptr(extension),
base::Time::Now(),
true, // incognito_enabled
false)); // notifications_disabled
}
// Implementation based on
// ExtensionSystemImpl::UnregisterExtensionWithRequestContexts.
void CefExtensionSystem::UnregisterExtensionWithRequestContexts(
const std::string& extension_id,
const UnloadedExtensionInfo::Reason reason) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&InfoMap::RemoveExtension, info_map(), extension_id, reason));
}
const OneShotEvent& CefExtensionSystem::ready() const {
return ready_;
}
ContentVerifier* CefExtensionSystem::content_verifier() {
return nullptr;
}
scoped_ptr<ExtensionSet> CefExtensionSystem::GetDependentExtensions(
const Extension* extension) {
return make_scoped_ptr(new ExtensionSet());
}
CefExtensionSystem::ComponentExtensionInfo::ComponentExtensionInfo(
const base::DictionaryValue* manifest, const base::FilePath& directory)
: manifest(manifest),
root_directory(directory) {
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::Load and
// ExtensionService::AddExtension.
const Extension* CefExtensionSystem::LoadExtension(
const ComponentExtensionInfo& info) {
// 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;
std::string error;
scoped_refptr<const Extension> extension(Extension::Create(
info.root_directory,
Manifest::COMPONENT,
*info.manifest,
flags,
&error));
if (!extension.get()) {
LOG(ERROR) << error;
return NULL;
}
CHECK_EQ(info.extension_id, extension->id()) << extension->name();
registry_->AddEnabled(extension.get());
NotifyExtensionLoaded(extension.get());
return extension.get();
}
// Implementation based on ExtensionService::UnloadExtension.
void CefExtensionSystem::UnloadExtension(
const std::string& extension_id,
UnloadedExtensionInfo::Reason reason) {
// Make sure the extension gets deleted after we return from this function.
int include_mask =
ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED;
scoped_refptr<const Extension> extension(
registry_->GetExtensionById(extension_id, include_mask));
// This method can be called via PostTask, so the extension may have been
// unloaded by the time this runs.
if (!extension.get()) {
// In case the extension may have crashed/uninstalled. Allow the profile to
// clean up its RequestContexts.
UnregisterExtensionWithRequestContexts(extension_id, reason);
return;
}
if (registry_->disabled_extensions().Contains(extension->id())) {
registry_->RemoveDisabled(extension->id());
// Make sure the profile cleans up its RequestContexts when an already
// disabled extension is unloaded (since they are also tracking the disabled
// extensions).
UnregisterExtensionWithRequestContexts(extension_id, reason);
// Don't send the unloaded notification. It was sent when the extension
// was disabled.
} else {
// Remove the extension from the enabled list.
registry_->RemoveEnabled(extension->id());
NotifyExtensionUnloaded(extension.get(), reason);
}
content::NotificationService::current()->Notify(
extensions::NOTIFICATION_EXTENSION_REMOVED,
content::Source<content::BrowserContext>(browser_context_),
content::Details<const Extension>(extension.get()));
}
// Implementation based on ExtensionService::NotifyExtensionLoaded.
void CefExtensionSystem::NotifyExtensionLoaded(const Extension* extension) {
// The URLRequestContexts need to be first to know that the extension
// was loaded, otherwise a race can arise where a renderer that is created
// for the extension may try to load an extension URL with an extension id
// that the request context doesn't yet know about. The profile is responsible
// for ensuring its URLRequestContexts appropriately discover the loaded
// extension.
RegisterExtensionWithRequestContexts(extension);
// Tell renderers about the new extension, unless it's a theme (renderers
// don't need to know about themes).
if (!extension->is_theme()) {
for (content::RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
content::RenderProcessHost* host = i.GetCurrentValue();
if (host->GetBrowserContext() == browser_context_) {
// We don't need to include tab permisisons here, since the extension
// was just loaded.
std::vector<ExtensionMsg_Loaded_Params> loaded_extensions(
1, ExtensionMsg_Loaded_Params(extension,
false /* no tab permissions */));
host->Send(
new ExtensionMsg_Loaded(loaded_extensions));
}
}
}
// Tell subsystems that use the EXTENSION_LOADED notification about the new
// extension.
//
// NOTE: It is important that this happen after notifying the renderers about
// the new extensions so that if we navigate to an extension URL in
// ExtensionRegistryObserver::OnLoaded or
// NOTIFICATION_EXTENSION_LOADED_DEPRECATED, the
// renderer is guaranteed to know about it.
registry_->TriggerOnLoaded(extension);
// Register plugins included with the extension.
// Implementation based on PluginManager::OnExtensionLoaded.
const MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
if (handler && !handler->handler_url().empty()) {
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
info.name = base::UTF8ToUTF16(extension->name());
info.path = base::FilePath::FromUTF8Unsafe(extension->url().spec());
for (std::set<std::string>::const_iterator mime_type =
handler->mime_type_set().begin();
mime_type != handler->mime_type_set().end(); ++mime_type) {
content::WebPluginMimeType mime_type_info;
mime_type_info.mime_type = *mime_type;
base::FilePath::StringType file_extension;
if (net::GetPreferredExtensionForMimeType(*mime_type, &file_extension)) {
mime_type_info.file_extensions.push_back(
base::FilePath(file_extension).AsUTF8Unsafe());
}
info.mime_types.push_back(mime_type_info);
}
content::PluginService* plugin_service =
content::PluginService::GetInstance();
plugin_service->RefreshPlugins();
plugin_service->RegisterInternalPlugin(info, true);
}
content::NotificationService::current()->Notify(
extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
content::Source<content::BrowserContext>(browser_context_),
content::Details<const Extension>(extension));
}
// Implementation based on ExtensionService::NotifyExtensionUnloaded.
void CefExtensionSystem::NotifyExtensionUnloaded(
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
UnloadedExtensionInfo details(extension, reason);
// Unregister plugins included with the extension.
// Implementation based on PluginManager::OnExtensionUnloaded.
const MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
if (handler && !handler->handler_url().empty()) {
base::FilePath path =
base::FilePath::FromUTF8Unsafe(extension->url().spec());
content::PluginService* plugin_service =
content::PluginService::GetInstance();
plugin_service->UnregisterInternalPlugin(path);
plugin_service->ForcePluginShutdown(path);
plugin_service->RefreshPlugins();
}
registry_->TriggerOnUnloaded(extension, reason);
content::NotificationService::current()->Notify(
extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
content::Source<content::BrowserContext>(browser_context_),
content::Details<UnloadedExtensionInfo>(&details));
for (content::RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
content::RenderProcessHost* host = i.GetCurrentValue();
if (host->GetBrowserContext() == browser_context_)
host->Send(new ExtensionMsg_Unloaded(extension->id()));
}
UnregisterExtensionWithRequestContexts(extension->id(), reason);
}
} // namespace extensions

View File

@ -0,0 +1,124 @@
// Copyright 2015 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_SYSTEM_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_H_
#include <vector>
#include "base/compiler_specific.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/one_shot_event.h"
class BrowserContextKeyedServiceFactory;
namespace base {
class FilePath;
}
namespace content {
class BrowserContext;
}
namespace extensions {
class ExtensionRegistry;
class InfoMap;
class ProcessManager;
class RendererStartupHelper;
class SharedUserScriptMaster;
// Used to manage extensions.
class CefExtensionSystem : public ExtensionSystem {
public:
explicit CefExtensionSystem(content::BrowserContext* browser_context);
~CefExtensionSystem() override;
// 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);
// Remove an extension.
void RemoveExtension(const std::string& extension_id);
// KeyedService implementation:
void Shutdown() override;
// ExtensionSystem implementation:
void InitForRegularProfile(bool extensions_enabled) override;
ExtensionService* extension_service() override;
RuntimeData* runtime_data() override;
ManagementPolicy* management_policy() override;
SharedUserScriptMaster* shared_user_script_master() override;
StateStore* state_store() override;
StateStore* rules_store() override;
InfoMap* info_map() override;
QuotaService* quota_service() override;
void RegisterExtensionWithRequestContexts(
const Extension* extension) override;
void UnregisterExtensionWithRequestContexts(
const std::string& extension_id,
const UnloadedExtensionInfo::Reason reason) override;
const OneShotEvent& ready() const override;
ContentVerifier* content_verifier() override;
scoped_ptr<ExtensionSet> GetDependentExtensions(
const Extension* extension) override;
private:
// Information about a registered component extension.
struct ComponentExtensionInfo {
ComponentExtensionInfo(const base::DictionaryValue* manifest,
const base::FilePath& root_directory);
// The parsed contents of the extensions's manifest file.
const base::DictionaryValue* manifest;
// Directory where the extension is stored.
base::FilePath root_directory;
// The component extension's ID.
std::string extension_id;
};
// Loads a registered component extension.
const Extension* LoadExtension(const ComponentExtensionInfo& info);
// Unload the specified extension.
void UnloadExtension(
const std::string& extension_id,
extensions::UnloadedExtensionInfo::Reason reason);
// Handles sending notification that |extension| was loaded.
void NotifyExtensionLoaded(const Extension* extension);
// Handles sending notification that |extension| was unloaded.
void NotifyExtensionUnloaded(
const Extension* extension,
UnloadedExtensionInfo::Reason reason);
content::BrowserContext* browser_context_; // Not owned.
// Data to be accessed on the IO thread. Must outlive process_manager_.
scoped_refptr<InfoMap> info_map_;
scoped_ptr<RuntimeData> runtime_data_;
scoped_ptr<QuotaService> quota_service_;
// Signaled when the extension system has completed its startup tasks.
OneShotEvent ready_;
// Sets of enabled/disabled/terminated/blacklisted extensions. Not owned.
ExtensionRegistry* registry_;
DISALLOW_COPY_AND_ASSIGN(CefExtensionSystem);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_H_

View File

@ -0,0 +1,55 @@
// 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_system_factory.h"
#include "libcef/browser/extensions/extension_system.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "extensions/browser/extension_prefs_factory.h"
#include "extensions/browser/extension_registry_factory.h"
using content::BrowserContext;
namespace extensions {
ExtensionSystem* CefExtensionSystemFactory::GetForBrowserContext(
BrowserContext* context) {
return static_cast<CefExtensionSystem*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
// static
CefExtensionSystemFactory* CefExtensionSystemFactory::GetInstance() {
return Singleton<CefExtensionSystemFactory>::get();
}
CefExtensionSystemFactory::CefExtensionSystemFactory()
: ExtensionSystemProvider("CefExtensionSystem",
BrowserContextDependencyManager::GetInstance()) {
// Other factories that this factory depends on. See
// libcef/common/extensions/api/README.txt for additional details.
DependsOn(ExtensionPrefsFactory::GetInstance());
DependsOn(ExtensionRegistryFactory::GetInstance());
}
CefExtensionSystemFactory::~CefExtensionSystemFactory() {
}
KeyedService* CefExtensionSystemFactory::BuildServiceInstanceFor(
BrowserContext* context) const {
return new CefExtensionSystem(context);
}
BrowserContext* CefExtensionSystemFactory::GetBrowserContextToUse(
BrowserContext* context) const {
// Use a separate instance for incognito.
return context;
}
bool CefExtensionSystemFactory::ServiceIsCreatedWithBrowserContext() const {
return true;
}
} // namespace extensions

View File

@ -0,0 +1,40 @@
// 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_SYSTEM_FACTORY_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_FACTORY_H_
#include "base/memory/singleton.h"
#include "extensions/browser/extension_system_provider.h"
namespace extensions {
// Factory that provides CefExtensionSystem.
class CefExtensionSystemFactory : public ExtensionSystemProvider {
public:
// ExtensionSystemProvider implementation:
ExtensionSystem* GetForBrowserContext(
content::BrowserContext* context) override;
static CefExtensionSystemFactory* GetInstance();
private:
friend struct DefaultSingletonTraits<CefExtensionSystemFactory>;
CefExtensionSystemFactory();
~CefExtensionSystemFactory() override;
// BrowserContextKeyedServiceFactory implementation:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
bool ServiceIsCreatedWithBrowserContext() const override;
DISALLOW_COPY_AND_ASSIGN(CefExtensionSystemFactory);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_SYSTEM_FACTORY_H_

View File

@ -0,0 +1,19 @@
// 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_web_contents_observer.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::CefExtensionWebContentsObserver);
namespace extensions {
CefExtensionWebContentsObserver::CefExtensionWebContentsObserver(
content::WebContents* web_contents)
: ExtensionWebContentsObserver(web_contents) {
}
CefExtensionWebContentsObserver::~CefExtensionWebContentsObserver() {
}
} // namespace extensions

View File

@ -0,0 +1,29 @@
// 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_WEB_CONTENTS_OBSERVER_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_WEB_CONTENTS_OBSERVER_H_
#include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/extension_web_contents_observer.h"
namespace extensions {
// The CEF version of ExtensionWebContentsObserver.
class CefExtensionWebContentsObserver
: public ExtensionWebContentsObserver,
public content::WebContentsUserData<CefExtensionWebContentsObserver> {
private:
friend class content::WebContentsUserData<CefExtensionWebContentsObserver>;
explicit CefExtensionWebContentsObserver(
content::WebContents* web_contents);
~CefExtensionWebContentsObserver() override;
DISALLOW_COPY_AND_ASSIGN(CefExtensionWebContentsObserver);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_WEB_CONTENTS_OBSERVER_H_

View File

@ -0,0 +1,28 @@
// Copyright 2015 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/extensions_api_client.h"
#include "libcef/browser/extensions/mime_handler_view_guest_delegate.h"
namespace extensions {
CefExtensionsAPIClient::CefExtensionsAPIClient() {
}
AppViewGuestDelegate* CefExtensionsAPIClient::CreateAppViewGuestDelegate()
const {
// TODO(extensions): Implement to support Apps.
NOTREACHED();
return NULL;
}
scoped_ptr<MimeHandlerViewGuestDelegate>
CefExtensionsAPIClient::CreateMimeHandlerViewGuestDelegate(
MimeHandlerViewGuest* guest) const {
return make_scoped_ptr(new CefMimeHandlerViewGuestDelegate(guest));
}
} // namespace extensions

View File

@ -0,0 +1,26 @@
// Copyright 2015 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_EXTENSIONS_API_CLIENT_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_API_CLIENT_H_
#include "extensions/browser/api/extensions_api_client.h"
namespace extensions {
class CefExtensionsAPIClient : public ExtensionsAPIClient {
public:
CefExtensionsAPIClient();
// ExtensionsAPIClient implementation.
AppViewGuestDelegate* CreateAppViewGuestDelegate() const override;
scoped_ptr<MimeHandlerViewGuestDelegate>
CreateMimeHandlerViewGuestDelegate(
MimeHandlerViewGuest* guest) const override;
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_API_CLIENT_H_

View File

@ -0,0 +1,234 @@
// Copyright 2015 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/extensions_browser_client.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/extensions/component_extension_resource_manager.h"
#include "libcef/browser/extensions/extension_system_factory.h"
#include "libcef/browser/extensions/extensions_api_client.h"
#include "libcef/browser/extensions/url_request_util.h"
#include "cef/libcef/browser/extensions/api/generated_api_registration.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/generated_api_registration.h"
#include "extensions/browser/api/runtime/runtime_api_delegate.h"
#include "extensions/browser/app_sorting.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_host_delegate.h"
#include "extensions/browser/mojo/service_registration.h"
#include "extensions/browser/null_app_sorting.h"
#include "extensions/browser/url_request_util.h"
using content::BrowserContext;
using content::BrowserThread;
namespace extensions {
CefExtensionsBrowserClient::CefExtensionsBrowserClient()
: api_client_(new CefExtensionsAPIClient),
resource_manager_(new CefComponentExtensionResourceManager),
event_router_forwarder_(new EventRouterForwarder) {
}
CefExtensionsBrowserClient::~CefExtensionsBrowserClient() {
}
bool CefExtensionsBrowserClient::IsShuttingDown() {
return false;
}
bool CefExtensionsBrowserClient::AreExtensionsDisabled(
const base::CommandLine& command_line,
BrowserContext* context) {
return false;
}
bool CefExtensionsBrowserClient::IsValidContext(BrowserContext* context) {
return CefBrowserContextImpl::GetForContext(context) != NULL;
}
bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first,
BrowserContext* second) {
return first == second;
}
bool CefExtensionsBrowserClient::HasOffTheRecordContext(
BrowserContext* context) {
return false;
}
BrowserContext* CefExtensionsBrowserClient::GetOffTheRecordContext(
BrowserContext* context) {
// TODO(extensions): Do we need to support this?
return NULL;
}
BrowserContext* CefExtensionsBrowserClient::GetOriginalContext(
BrowserContext* context) {
return context;
}
bool CefExtensionsBrowserClient::IsGuestSession(
BrowserContext* context) const {
return false;
}
bool CefExtensionsBrowserClient::IsExtensionIncognitoEnabled(
const std::string& extension_id,
content::BrowserContext* context) const {
return false;
}
bool CefExtensionsBrowserClient::CanExtensionCrossIncognito(
const Extension* extension,
content::BrowserContext* context) const {
return false;
}
net::URLRequestJob*
CefExtensionsBrowserClient::MaybeCreateResourceBundleRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& directory_path,
const std::string& content_security_policy,
bool send_cors_header) {
return url_request_util::MaybeCreateURLRequestResourceBundleJob(
request,
network_delegate,
directory_path,
content_security_policy,
send_cors_header);
}
bool CefExtensionsBrowserClient::AllowCrossRendererResourceLoad(
net::URLRequest* request,
bool is_incognito,
const Extension* extension,
InfoMap* extension_info_map) {
bool allowed = false;
if (url_request_util::AllowCrossRendererResourceLoad(
request, is_incognito, extension, extension_info_map, &allowed)) {
return allowed;
}
// Couldn't determine if resource is allowed. Block the load.
return false;
}
PrefService* CefExtensionsBrowserClient::GetPrefServiceForContext(
BrowserContext* context) {
// TODO(extensions): Do we need a per-context PrefService?
return CefContentBrowserClient::Get()->pref_service();
}
void CefExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
content::BrowserContext* context,
std::vector<ExtensionPrefsObserver*>* observers) const {
}
ProcessManagerDelegate*
CefExtensionsBrowserClient::GetProcessManagerDelegate() const {
return NULL;
}
scoped_ptr<ExtensionHostDelegate>
CefExtensionsBrowserClient::CreateExtensionHostDelegate() {
// TODO(extensions): Implement to support Apps.
NOTREACHED();
return scoped_ptr<ExtensionHostDelegate>();
}
bool CefExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
// TODO(jamescook): We might want to tell extensions when app_shell updates.
return false;
}
void CefExtensionsBrowserClient::PermitExternalProtocolHandler() {
}
scoped_ptr<AppSorting> CefExtensionsBrowserClient::CreateAppSorting() {
return scoped_ptr<AppSorting>(new NullAppSorting);
}
bool CefExtensionsBrowserClient::IsRunningInForcedAppMode() {
return false;
}
ApiActivityMonitor* CefExtensionsBrowserClient::GetApiActivityMonitor(
BrowserContext* context) {
// CEF doesn't monitor API function calls or events.
return NULL;
}
ExtensionSystemProvider*
CefExtensionsBrowserClient::GetExtensionSystemFactory() {
return CefExtensionSystemFactory::GetInstance();
}
void CefExtensionsBrowserClient::RegisterExtensionFunctions(
ExtensionFunctionRegistry* registry) const {
// Register core extension-system APIs.
core_api::GeneratedFunctionRegistry::RegisterAll(registry);
// CEF-only APIs.
api::GeneratedFunctionRegistry::RegisterAll(registry);
}
void CefExtensionsBrowserClient::RegisterMojoServices(
content::RenderFrameHost* render_frame_host,
const Extension* extension) const {
RegisterServicesForFrame(render_frame_host, extension);
}
scoped_ptr<RuntimeAPIDelegate>
CefExtensionsBrowserClient::CreateRuntimeAPIDelegate(
content::BrowserContext* context) const {
// TODO(extensions): Implement to support Apps.
NOTREACHED();
return scoped_ptr<RuntimeAPIDelegate>();
}
const ComponentExtensionResourceManager*
CefExtensionsBrowserClient::GetComponentExtensionResourceManager() {
return resource_manager_.get();
}
void CefExtensionsBrowserClient::BroadcastEventToRenderers(
const std::string& event_name,
scoped_ptr<base::ListValue> args) {
event_router_forwarder_->BroadcastEventToRenderers(
event_name, args.Pass(), GURL());
}
net::NetLog* CefExtensionsBrowserClient::GetNetLog() {
return NULL;
}
ExtensionCache* CefExtensionsBrowserClient::GetExtensionCache() {
// Only used by Chrome via ExtensionService.
NOTREACHED();
return NULL;
}
bool CefExtensionsBrowserClient::IsBackgroundUpdateAllowed() {
return true;
}
bool CefExtensionsBrowserClient::IsMinBrowserVersionSupported(
const std::string& min_version) {
return true;
}
void CefExtensionsBrowserClient::SetAPIClientForTest(
ExtensionsAPIClient* api_client) {
api_client_.reset(api_client);
}
} // namespace extensions

View File

@ -0,0 +1,102 @@
// Copyright 2015 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_EXTENSIONS_BROWSER_CLIENT_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_CLIENT_H_
#include "libcef/browser/extensions/event_router_forwarder.h"
#include "base/compiler_specific.h"
#include "extensions/browser/extensions_browser_client.h"
namespace extensions {
class ExtensionsAPIClient;
// An ExtensionsBrowserClient that supports a single content::BrowserContent
// with no related incognito context.
class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
public:
CefExtensionsBrowserClient();
~CefExtensionsBrowserClient() override;
// ExtensionsBrowserClient overrides:
bool IsShuttingDown() override;
bool AreExtensionsDisabled(const base::CommandLine& command_line,
content::BrowserContext* context) override;
bool IsValidContext(content::BrowserContext* context) override;
bool IsSameContext(content::BrowserContext* first,
content::BrowserContext* second) override;
bool HasOffTheRecordContext(content::BrowserContext* context) override;
content::BrowserContext* GetOffTheRecordContext(
content::BrowserContext* context) override;
content::BrowserContext* GetOriginalContext(
content::BrowserContext* context) override;
bool IsGuestSession(content::BrowserContext* context) const override;
bool IsExtensionIncognitoEnabled(
const std::string& extension_id,
content::BrowserContext* context) const override;
bool CanExtensionCrossIncognito(
const Extension* extension,
content::BrowserContext* context) const override;
net::URLRequestJob* MaybeCreateResourceBundleRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& directory_path,
const std::string& content_security_policy,
bool send_cors_header) override;
bool AllowCrossRendererResourceLoad(net::URLRequest* request,
bool is_incognito,
const Extension* extension,
InfoMap* extension_info_map) override;
PrefService* GetPrefServiceForContext(
content::BrowserContext* context) override;
void GetEarlyExtensionPrefsObservers(
content::BrowserContext* context,
std::vector<ExtensionPrefsObserver*>* observers) const
override;
ProcessManagerDelegate* GetProcessManagerDelegate() const override;
scoped_ptr<ExtensionHostDelegate>
CreateExtensionHostDelegate() override;
bool DidVersionUpdate(content::BrowserContext* context) override;
void PermitExternalProtocolHandler() override;
scoped_ptr<AppSorting> CreateAppSorting() override;
bool IsRunningInForcedAppMode() override;
ApiActivityMonitor* GetApiActivityMonitor(
content::BrowserContext* context) override;
ExtensionSystemProvider* GetExtensionSystemFactory() override;
void RegisterExtensionFunctions(
ExtensionFunctionRegistry* registry) const override;
void RegisterMojoServices(content::RenderFrameHost* render_frame_host,
const Extension* extension) const override;
scoped_ptr<RuntimeAPIDelegate> CreateRuntimeAPIDelegate(
content::BrowserContext* context) const override;
const ComponentExtensionResourceManager*
GetComponentExtensionResourceManager() override;
void BroadcastEventToRenderers(const std::string& event_name,
scoped_ptr<base::ListValue> args) override;
net::NetLog* GetNetLog() override;
ExtensionCache* GetExtensionCache() override;
bool IsBackgroundUpdateAllowed() override;
bool IsMinBrowserVersionSupported(const std::string& min_version) override;
// Sets the API client.
void SetAPIClientForTest(ExtensionsAPIClient* api_client);
private:
// Support for extension APIs.
scoped_ptr<ExtensionsAPIClient> api_client_;
// Resource manager used to supply resources from pak files.
scoped_ptr<ComponentExtensionResourceManager> resource_manager_;
scoped_refptr<EventRouterForwarder> event_router_forwarder_;
DISALLOW_COPY_AND_ASSIGN(CefExtensionsBrowserClient);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_CLIENT_H_

View File

@ -0,0 +1,135 @@
// Copyright 2015 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/mime_handler_view_guest_delegate.h"
#include "include/internal/cef_types_wrappers.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/browser_info.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/extensions/extension_web_contents_observer.h"
#include "libcef/browser/extensions/pdf_web_contents_helper_client.h"
#include "libcef/browser/printing/print_view_manager.h"
#include "libcef/browser/web_contents_view_osr.h"
#include "components/pdf/browser/pdf_web_contents_helper.h"
#include "components/pdf/browser/pdf_web_contents_helper_client.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
namespace extensions {
namespace {
CefRefPtr<CefBrowserHostImpl> GetOwnerBrowser(
extensions::MimeHandlerViewGuest* guest) {
content::WebContents* owner_web_contents = guest->GetOwnerWebContents();
CefRefPtr<CefBrowserHostImpl> owner_browser =
CefBrowserHostImpl::GetBrowserForContents(owner_web_contents);
DCHECK(owner_browser);
return owner_browser;
}
} // namespace
CefMimeHandlerViewGuestDelegate::CefMimeHandlerViewGuestDelegate(
MimeHandlerViewGuest* guest)
: MimeHandlerViewGuestDelegate(guest), guest_(guest) {
}
CefMimeHandlerViewGuestDelegate::~CefMimeHandlerViewGuestDelegate() {
}
void CefMimeHandlerViewGuestDelegate::OverrideWebContentsCreateParams(
content::WebContents::CreateParams* params) {
DCHECK(params->guest_delegate);
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
if (owner_browser->IsWindowless()) {
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR();
params->view = view_osr;
params->delegate_view = view_osr;
}
}
bool CefMimeHandlerViewGuestDelegate::OnGuestAttached(
content::WebContentsView* guest_view,
content::WebContentsView* parent_view) {
// Do nothing when the browser is windowless.
return GetOwnerBrowser(guest_)->IsWindowless();
}
bool CefMimeHandlerViewGuestDelegate::OnGuestDetached(
content::WebContentsView* guest_view,
content::WebContentsView* parent_view) {
// Do nothing when the browser is windowless.
return GetOwnerBrowser(guest_)->IsWindowless();
}
bool CefMimeHandlerViewGuestDelegate::CreateViewForWidget(
content::WebContentsView* guest_view,
content::RenderWidgetHost* render_widget_host) {
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
if (owner_browser->IsWindowless()) {
static_cast<CefWebContentsViewOSR*>(guest_view)->CreateViewForWidget(
render_widget_host, true);
return true;
}
return false;
}
// TODO(lazyboy): Investigate ways to move this out to /extensions.
void CefMimeHandlerViewGuestDelegate::AttachHelpers() {
content::WebContents* web_contents = guest_->web_contents();
// Associate state information with the new WebContents.
content::RenderViewHost* view_host = web_contents->GetRenderViewHost();
content::RenderFrameHost* main_frame_host = web_contents->GetMainFrame();
scoped_refptr<CefBrowserInfo> info =
CefContentBrowserClient::Get()->GetOrCreateBrowserInfo(
view_host->GetProcess()->GetID(),
view_host->GetRoutingID(),
main_frame_host->GetProcess()->GetID(),
main_frame_host->GetRoutingID());
info->set_mime_handler_view(true);
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
if (owner_browser->IsWindowless()) {
// Use the OSR view instead of the default WebContentsViewGuest.
content::WebContentsImpl* web_contents_impl =
static_cast<content::WebContentsImpl*>(web_contents);
CefWebContentsViewOSR* view_osr =
static_cast<CefWebContentsViewOSR*>(
web_contents_impl->GetView());
view_osr->set_web_contents(web_contents);
view_osr->set_guest(web_contents_impl->GetBrowserPluginGuest());
}
printing::PrintViewManager::CreateForWebContents(web_contents);
pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
web_contents,
scoped_ptr<pdf::PDFWebContentsHelperClient>(
new CefPDFWebContentsHelperClient()));
CefExtensionWebContentsObserver::CreateForWebContents(web_contents);
}
bool CefMimeHandlerViewGuestDelegate::HandleContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params) {
content::ContextMenuParams new_params = params;
gfx::Point guest_coordinates =
static_cast<content::WebContentsImpl*>(web_contents)->
GetBrowserPluginGuest()->GetScreenCoordinates(gfx::Point());
// Adjust (x,y) position for offset from guest to embedder.
new_params.x += guest_coordinates.x();
new_params.y += guest_coordinates.y();
return GetOwnerBrowser(guest_)->HandleContextMenu(web_contents, new_params);
}
} // namespace extensions

View File

@ -0,0 +1,44 @@
// Copyright 2015 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_MIME_HANDLER_VIEW_GUEST_DELEGATE_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_MIME_HANDLER_VIEW_GUEST_DELEGATE_H_
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h"
namespace content {
struct ContextMenuParams;
}
namespace extensions {
class CefMimeHandlerViewGuestDelegate : public MimeHandlerViewGuestDelegate {
public:
explicit CefMimeHandlerViewGuestDelegate(MimeHandlerViewGuest* guest);
~CefMimeHandlerViewGuestDelegate() override;
// MimeHandlerViewGuestDelegate methods.
void OverrideWebContentsCreateParams(
content::WebContents::CreateParams* params) override;
bool OnGuestAttached(content::WebContentsView* guest_view,
content::WebContentsView* parent_view) override;
bool OnGuestDetached(content::WebContentsView* guest_view,
content::WebContentsView* parent_view) override;
bool CreateViewForWidget(
content::WebContentsView* guest_view,
content::RenderWidgetHost* render_widget_host) override;
void AttachHelpers() override;
bool HandleContextMenu(content::WebContents* web_contents,
const content::ContextMenuParams& params) override;
private:
MimeHandlerViewGuest* guest_; // Owns us.
DISALLOW_COPY_AND_ASSIGN(CefMimeHandlerViewGuestDelegate);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_MIME_HANDLER_VIEW_GUEST_DELEGATE_H_

View File

@ -0,0 +1,54 @@
// Copyright 2015 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/pdf_extension_util.h"
#include "base/strings/string_util.h"
#include "chrome/common/chrome_switches.h"
#include "grit/cef_resources.h"
#include "ui/base/resource/resource_bundle.h"
namespace extensions {
namespace pdf_extension_util {
namespace {
// Tags in the manifest to be replaced.
const char kNameTag[] = "<NAME>";
const char kIndexTag[] = "<INDEX>";
// The index html pages to load for the material and non-material version of
// the viewer.
const char kRegularIndex[] = "index.html";
const char kMaterialIndex[] = "index-material.html";
} // namespace
// These should match the keys for the Chrome and Chromium PDF Viewer entries in
// chrome/browser/resources/plugin_metadata/plugins_*.json.
#if defined(GOOGLE_CHROME_BUILD)
const char kPdfResourceIdentifier[] = "google-chrome-pdf";
#else
const char kPdfResourceIdentifier[] = "chromium-pdf";
#endif
const char kPdfPluginName[] = "Chromium PDF Viewer";
std::string GetManifest() {
std::string manifest_contents =
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_PDF_MANIFEST).as_string();
DCHECK(manifest_contents.find(kNameTag) != std::string::npos);
ReplaceFirstSubstringAfterOffset(
&manifest_contents, 0, kNameTag, kPdfPluginName);
DCHECK(manifest_contents.find(kIndexTag) != std::string::npos);
std::string index = switches::PdfMaterialUIEnabled() ?
kMaterialIndex : kRegularIndex;
ReplaceSubstringsAfterOffset(&manifest_contents, 0, kIndexTag, index);
return manifest_contents;
}
} // namespace pdf_extension_util
} // namespace extensions

View File

@ -0,0 +1,27 @@
// Copyright 2015 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_PDF_EXTENSION_UTIL_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_
#include <string>
namespace extensions {
namespace pdf_extension_util {
// The ResourceIdentifier for the PDF Viewer plugin.
extern const char kPdfResourceIdentifier[];
// The name of the PDF Viewer plugin.
extern const char kPdfPluginName[];
// Return the extensions manifest for PDF. The manifest is loaded from
// browser_resources.grd and certain fields are replaced based on what chrome
// flags are enabled.
std::string GetManifest();
} // namespace pdf_extension_util
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_

View File

@ -0,0 +1,32 @@
// 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/pdf_web_contents_helper_client.h"
namespace extensions {
CefPDFWebContentsHelperClient::CefPDFWebContentsHelperClient() {
}
CefPDFWebContentsHelperClient::~CefPDFWebContentsHelperClient() {
}
void CefPDFWebContentsHelperClient::UpdateLocationBar(
content::WebContents* contents) {
}
void CefPDFWebContentsHelperClient::UpdateContentRestrictions(
content::WebContents* contents,
int content_restrictions) {
}
void CefPDFWebContentsHelperClient::OnPDFHasUnsupportedFeature(
content::WebContents* contents) {
}
void CefPDFWebContentsHelperClient::OnSaveURL(
content::WebContents* contents) {
}
} // namespace extensions

View File

@ -0,0 +1,35 @@
// 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_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
#include "base/macros.h"
#include "components/pdf/browser/pdf_web_contents_helper_client.h"
namespace extensions {
class CefPDFWebContentsHelperClient
: public pdf::PDFWebContentsHelperClient {
public:
CefPDFWebContentsHelperClient();
~CefPDFWebContentsHelperClient() override;
private:
// pdf::PDFWebContentsHelperClient:
void UpdateLocationBar(content::WebContents* contents) override;
void UpdateContentRestrictions(content::WebContents* contents,
int content_restrictions) override;
void OnPDFHasUnsupportedFeature(content::WebContents* contents) override;
void OnSaveURL(content::WebContents* contents) override;
DISALLOW_COPY_AND_ASSIGN(CefPDFWebContentsHelperClient);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_WEB_CONTENTS_HELPER_CLIENT_H_

View File

@ -0,0 +1,217 @@
// Copyright 2015 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/plugin_info_message_filter.h"
#include "libcef/common/cef_messages.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/plugin_service_filter.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "url/gurl.h"
using content::PluginService;
using content::WebPluginInfo;
namespace extensions {
namespace {
#if defined(OS_WIN) || defined(OS_MACOSX)
// These are the mime-types of plugins which are known to have PPAPI versions.
const char* kPepperPluginMimeTypes[] = {
"application/pdf",
"application/x-google-chrome-pdf",
"application/x-nacl",
"application/x-pnacl",
"application/vnd.chromium.remoting-viewer",
"application/x-shockwave-flash",
"application/futuresplash",
};
#endif
} // namespace
CefPluginInfoMessageFilter::Context::Context(
int render_process_id,
content::BrowserContext* browser_context)
: render_process_id_(render_process_id),
resource_context_(browser_context->GetResourceContext()) {
}
CefPluginInfoMessageFilter::Context::~Context() {
}
CefPluginInfoMessageFilter::CefPluginInfoMessageFilter(
int render_process_id,
content::BrowserContext* browser_context)
: BrowserMessageFilter(ExtensionMsgStart),
context_(render_process_id, browser_context),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
weak_ptr_factory_(this) {
}
bool CefPluginInfoMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(CefPluginInfoMessageFilter, message)
IPC_MESSAGE_HANDLER_DELAY_REPLY(CefViewHostMsg_GetPluginInfo,
OnGetPluginInfo)
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
void CefPluginInfoMessageFilter::OnDestruct() const {
const_cast<CefPluginInfoMessageFilter*>(this)->
weak_ptr_factory_.InvalidateWeakPtrs();
// Destroy on the UI thread because we contain a |PrefMember|.
content::BrowserThread::DeleteOnUIThread::Destruct(this);
}
CefPluginInfoMessageFilter::~CefPluginInfoMessageFilter() {}
struct CefPluginInfoMessageFilter::GetPluginInfo_Params {
int render_frame_id;
GURL url;
GURL top_origin_url;
std::string mime_type;
};
void CefPluginInfoMessageFilter::OnGetPluginInfo(
int render_frame_id,
const GURL& url,
const GURL& top_origin_url,
const std::string& mime_type,
IPC::Message* reply_msg) {
GetPluginInfo_Params params = {
render_frame_id,
url,
top_origin_url,
mime_type
};
PluginService::GetInstance()->GetPlugins(
base::Bind(&CefPluginInfoMessageFilter::PluginsLoaded,
weak_ptr_factory_.GetWeakPtr(),
params, reply_msg));
}
void CefPluginInfoMessageFilter::PluginsLoaded(
const GetPluginInfo_Params& params,
IPC::Message* reply_msg,
const std::vector<WebPluginInfo>& plugins) {
CefViewHostMsg_GetPluginInfo_Output output;
// This also fills in |actual_mime_type|.
if (context_.FindEnabledPlugin(params.render_frame_id, params.url,
params.top_origin_url, params.mime_type,
&output.status, &output.plugin,
&output.actual_mime_type)) {
context_.DecidePluginStatus(params, output.plugin, &output.status);
}
CefViewHostMsg_GetPluginInfo::WriteReplyParams(reply_msg, output);
Send(reply_msg);
}
void CefPluginInfoMessageFilter::Context::DecidePluginStatus(
const GetPluginInfo_Params& params,
const WebPluginInfo& plugin,
CefViewHostMsg_GetPluginInfo_Status* status) const {
if (plugin.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
// NPAPI plugins are not supported inside <webview> guests.
if (extensions::WebViewRendererState::GetInstance()->IsGuest(
render_process_id_)) {
*status = CefViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported;
return;
}
}
// Check if the plugin is crashing too much.
if (PluginService::GetInstance()->IsPluginUnstable(plugin.path)) {
*status = CefViewHostMsg_GetPluginInfo_Status::kUnauthorized;
return;
}
if (*status == CefViewHostMsg_GetPluginInfo_Status::kAllowed) {
// Allow an embedder of <webview> to block a plugin from being loaded inside
// the guest. In order to do this, set the status to 'Unauthorized' here,
// and update the status as appropriate depending on the response from the
// embedder.
if (extensions::WebViewRendererState::GetInstance()->IsGuest(
render_process_id_)) {
*status = CefViewHostMsg_GetPluginInfo_Status::kUnauthorized;
}
}
}
bool CefPluginInfoMessageFilter::Context::FindEnabledPlugin(
int render_frame_id,
const GURL& url,
const GURL& top_origin_url,
const std::string& mime_type,
CefViewHostMsg_GetPluginInfo_Status* status,
WebPluginInfo* plugin,
std::string* actual_mime_type) const {
*status = CefViewHostMsg_GetPluginInfo_Status::kAllowed;
bool allow_wildcard = true;
std::vector<WebPluginInfo> matching_plugins;
std::vector<std::string> mime_types;
PluginService::GetInstance()->GetPluginInfoArray(
url, mime_type, allow_wildcard, &matching_plugins, &mime_types);
if (matching_plugins.empty()) {
*status = CefViewHostMsg_GetPluginInfo_Status::kNotFound;
#if defined(OS_WIN) || defined(OS_MACOSX)
if (!PluginService::GetInstance()->NPAPIPluginsSupported()) {
// At this point it is not known for sure this is an NPAPI plugin as it
// could be a not-yet-installed Pepper plugin. To avoid notifying on
// these types, bail early based on a blacklist of pepper mime types.
for (auto pepper_mime_type : kPepperPluginMimeTypes)
if (pepper_mime_type == mime_type)
return false;
}
#endif
return false;
}
content::PluginServiceFilter* filter =
PluginService::GetInstance()->GetFilter();
size_t i = 0;
for (; i < matching_plugins.size(); ++i) {
if (!filter || filter->IsPluginAvailable(render_process_id_,
render_frame_id,
resource_context_,
url,
top_origin_url,
&matching_plugins[i])) {
break;
}
}
// If we broke out of the loop, we have found an enabled plugin.
bool enabled = i < matching_plugins.size();
if (!enabled) {
// Otherwise, we only found disabled plugins, so we take the first one.
i = 0;
*status = CefViewHostMsg_GetPluginInfo_Status::kDisabled;
}
*plugin = matching_plugins[i];
*actual_mime_type = mime_types[i];
return enabled;
}
} // namespace extensions

View File

@ -0,0 +1,96 @@
// Copyright 2015 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.
#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_PLUGIN_INFO_MESSAGE_FILTER_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_PLUGIN_INFO_MESSAGE_FILTER_H_
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_member.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/public/browser/browser_message_filter.h"
struct CefViewHostMsg_GetPluginInfo_Output;
enum class CefViewHostMsg_GetPluginInfo_Status;
class GURL;
namespace content {
class BrowserContext;
class ResourceContext;
struct WebPluginInfo;
}
namespace extensions {
// This class filters out incoming IPC messages requesting plugin information.
class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
public:
struct GetPluginInfo_Params;
// Contains all the information needed by the CefPluginInfoMessageFilter.
class Context {
public:
Context(int render_process_id, content::BrowserContext* browser_context);
~Context();
void DecidePluginStatus(
const GetPluginInfo_Params& params,
const content::WebPluginInfo& plugin,
CefViewHostMsg_GetPluginInfo_Status* status) const;
bool FindEnabledPlugin(int render_frame_id,
const GURL& url,
const GURL& top_origin_url,
const std::string& mime_type,
CefViewHostMsg_GetPluginInfo_Status* status,
content::WebPluginInfo* plugin,
std::string* actual_mime_type) const;
private:
int render_process_id_;
content::ResourceContext* resource_context_;
};
CefPluginInfoMessageFilter(int render_process_id,
content::BrowserContext* browser_context);
// content::BrowserMessageFilter methods:
bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() const override;
private:
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
friend class base::DeleteHelper<CefPluginInfoMessageFilter>;
~CefPluginInfoMessageFilter() override;
void OnGetPluginInfo(int render_frame_id,
const GURL& url,
const GURL& top_origin_url,
const std::string& mime_type,
IPC::Message* reply_msg);
// |params| wraps the parameters passed to |OnGetPluginInfo|, because
// |base::Bind| doesn't support the required arity <http://crbug.com/98542>.
void PluginsLoaded(const GetPluginInfo_Params& params,
IPC::Message* reply_msg,
const std::vector<content::WebPluginInfo>& plugins);
Context context_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
base::WeakPtrFactory<CefPluginInfoMessageFilter> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CefPluginInfoMessageFilter);
};
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_PLUGIN_INFO_MESSAGE_FILTER_H_

View File

@ -0,0 +1,165 @@
// Copyright 2015 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/url_request_util.h"
#include <string>
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "extensions/browser/component_extension_resource_manager.h"
#include "extensions/browser/extension_protocols.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/info_map.h"
#include "extensions/browser/url_request_util.h"
#include "extensions/common/file_util.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_simple_job.h"
#include "ui/base/resource/resource_bundle.h"
using content::BrowserThread;
using content::ResourceType;
using extensions::ExtensionsBrowserClient;
namespace {
// A request for an extension resource in a Chrome .pak file. These are used
// by component extensions.
class URLRequestResourceBundleJob : public net::URLRequestSimpleJob {
public:
URLRequestResourceBundleJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& filename,
int resource_id,
const std::string& content_security_policy,
bool send_cors_header)
: net::URLRequestSimpleJob(request, network_delegate),
filename_(filename),
resource_id_(resource_id),
weak_factory_(this) {
// Leave cache headers out of resource bundle requests.
response_info_.headers = extensions::BuildHttpHeaders(
content_security_policy, send_cors_header, base::Time());
}
// Overridden from URLRequestSimpleJob:
int GetRefCountedData(
std::string* mime_type,
std::string* charset,
scoped_refptr<base::RefCountedMemory>* data,
const net::CompletionCallback& callback) const override {
const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
*data = rb.LoadDataResourceBytes(resource_id_);
// Add the Content-Length header now that we know the resource length.
response_info_.headers->AddHeader(
base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentLength,
base::UintToString((*data)->size()).c_str()));
std::string* read_mime_type = new std::string;
bool posted = base::PostTaskAndReplyWithResult(
BrowserThread::GetBlockingPool(), FROM_HERE,
base::Bind(&net::GetMimeTypeFromFile, filename_,
base::Unretained(read_mime_type)),
base::Bind(&URLRequestResourceBundleJob::OnMimeTypeRead,
weak_factory_.GetWeakPtr(), mime_type, charset, *data,
base::Owned(read_mime_type), callback));
DCHECK(posted);
return net::ERR_IO_PENDING;
}
void GetResponseInfo(net::HttpResponseInfo* info) override {
*info = response_info_;
}
private:
~URLRequestResourceBundleJob() override {}
void OnMimeTypeRead(std::string* out_mime_type,
std::string* charset,
scoped_refptr<base::RefCountedMemory> data,
std::string* read_mime_type,
const net::CompletionCallback& callback,
bool read_result) {
*out_mime_type = *read_mime_type;
if (StartsWithASCII(*read_mime_type, "text/", false)) {
// All of our HTML files should be UTF-8 and for other resource types
// (like images), charset doesn't matter.
DCHECK(base::IsStringUTF8(base::StringPiece(
reinterpret_cast<const char*>(data->front()), data->size())));
*charset = "utf-8";
}
int result = read_result ? net::OK : net::ERR_INVALID_URL;
callback.Run(result);
}
// We need the filename of the resource to determine the mime type.
base::FilePath filename_;
// The resource bundle id to load.
int resource_id_;
net::HttpResponseInfo response_info_;
mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_;
};
} // namespace
namespace extensions {
namespace url_request_util {
net::URLRequestJob* MaybeCreateURLRequestResourceBundleJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& directory_path,
const std::string& content_security_policy,
bool send_cors_header) {
base::FilePath resources_path;
base::FilePath relative_path;
// Try to load extension resources from chrome resource file if
// directory_path is a descendant of resources_path. This path structure is
// set up by CefExtensionSystem::ComponentExtensionInfo.
if (PathService::Get(chrome::DIR_RESOURCES, &resources_path) &&
// Since component extension resources are included in
// component_extension_resources.pak file in resources_path, calculate
// extension relative path against resources_path.
resources_path.AppendRelativePath(directory_path, &relative_path)) {
base::FilePath request_path =
extensions::file_util::ExtensionURLToRelativeFilePath(request->url());
int resource_id = 0;
if (ExtensionsBrowserClient::Get()
->GetComponentExtensionResourceManager()
->IsComponentExtensionResource(
directory_path, request_path, &resource_id)) {
relative_path = relative_path.Append(request_path);
relative_path = relative_path.NormalizePathSeparators();
return new URLRequestResourceBundleJob(request,
network_delegate,
relative_path,
resource_id,
content_security_policy,
send_cors_header);
}
}
return NULL;
}
} // namespace url_request_util
} // namespace extensions

View File

@ -0,0 +1,42 @@
// Copyright 2015 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_URL_REQUEST_UTIL_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_URL_REQUEST_UTIL_H_
#include <string>
namespace base {
class FilePath;
}
namespace net {
class NetworkDelegate;
class URLRequest;
class URLRequestJob;
}
namespace extensions {
class Extension;
class InfoMap;
// Utilities related to URLRequest jobs for extension resources. Based on
// chrome/browser/extensions/chrome_url_request_util.cc.
namespace url_request_util {
// Creates a URLRequestJob for loading component extension resources out of
// a CEF resource bundle. Returns NULL if the requested resource is not a
// component extension resource.
net::URLRequestJob* MaybeCreateURLRequestResourceBundleJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const base::FilePath& directory_path,
const std::string& content_security_policy,
bool send_cors_header);
} // namespace url_request_util
} // namespace extensions
#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_URL_REQUEST_UTIL_H_

View File

@ -4,29 +4,33 @@
// found in the LICENSE file.
#include "libcef/browser/internal_scheme_handler.h"
#include <string>
#include "libcef/common/content_client.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/mime_util.h"
#include "ui/base/resource/resource_bundle.h"
namespace scheme {
namespace {
base::FilePath FilePathFromASCII(const std::string& str) {
#if defined(OS_WIN)
return base::FilePath(base::ASCIIToUTF16(str));
#else
return base::FilePath(str);
#endif
}
static std::string GetMimeType(const std::string& filename) {
if (EndsWith(filename, ".html", false)) {
return "text/html";
} else if (EndsWith(filename, ".css", false)) {
return "text/css";
} else if (EndsWith(filename, ".jpg", false)) {
return "image/jpeg";
} else if (EndsWith(filename, ".js", false)) {
return "application/javascript";
} else if (EndsWith(filename, ".png", false)) {
return "image/png";
} else if (EndsWith(filename, ".gif", false)) {
return "image/gif";
}
std::string mime_type;
if (net::GetMimeTypeFromFile(FilePathFromASCII(filename), &mime_type))
return mime_type;
NOTREACHED() << "No known mime type for file: " << filename.c_str();
return "text/plain";
}

View File

@ -33,8 +33,12 @@ CefString GetLabel(int message_id) {
} // namespace
CefMenuCreator::CefMenuCreator(CefBrowserHostImpl* browser)
: browser_(browser) {
CefMenuCreator::CefMenuCreator(content::WebContents* web_contents,
CefBrowserHostImpl* browser)
: content::WebContentsObserver(web_contents),
browser_(browser) {
DCHECK(web_contents);
DCHECK(browser_);
model_ = new CefMenuModelImpl(this);
}
@ -45,10 +49,10 @@ CefMenuCreator::~CefMenuCreator() {
}
bool CefMenuCreator::IsShowingContextMenu() {
content::WebContents* web_contents = browser_->GetWebContents();
if (!web_contents)
if (!web_contents())
return false;
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
content::RenderWidgetHostView* view =
web_contents()->GetRenderWidgetHostView();
return (view && view->IsShowingContextMenu());
}
@ -162,12 +166,12 @@ void CefMenuCreator::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
if (source.get() != model_.get())
return;
content::WebContents* web_contents = browser_->GetWebContents();
if (!web_contents)
if (!web_contents())
return;
// Notify the host before showing the context menu.
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
content::RenderWidgetHostView* view =
web_contents()->GetRenderWidgetHostView();
if (view)
view->SetShowingContextMenu(true);
}
@ -187,14 +191,13 @@ void CefMenuCreator::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
}
}
if (IsShowingContextMenu()) {
if (IsShowingContextMenu() && web_contents()) {
// Notify the host after closing the context menu.
content::WebContents* web_contents = browser_->GetWebContents();
content::RenderWidgetHostView* view =
web_contents->GetRenderWidgetHostView();
web_contents()->GetRenderWidgetHostView();
if (view)
view->SetShowingContextMenu(false);
web_contents->NotifyContextMenuClosed(params_.custom_context);
web_contents()->NotifyContextMenuClosed(params_.custom_context);
}
}

View File

@ -9,15 +9,18 @@
#include "libcef/browser/menu_model_impl.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/context_menu_params.h"
namespace content {
class RenderFrameHost;
class WebContents;
};
class CefBrowserHostImpl;
class CefMenuCreator : public CefMenuModelImpl::Delegate {
class CefMenuCreator : public CefMenuModelImpl::Delegate,
public content::WebContentsObserver {
public:
// Used for OS-specific menu implementations.
class Runner {
@ -28,7 +31,8 @@ class CefMenuCreator : public CefMenuModelImpl::Delegate {
virtual bool FormatLabel(base::string16& label) { return false; }
};
explicit CefMenuCreator(CefBrowserHostImpl* browser);
CefMenuCreator(content::WebContents* web_contents,
CefBrowserHostImpl* browser);
~CefMenuCreator() override;
// Returns true if the context menu is currently showing.

View File

@ -56,5 +56,6 @@ scoped_ptr<ResourceHost> CefBrowserPepperHostFactory::CreateResourceHost(
}
}
NOTREACHED() << "Unhandled message type: " << message.type();
return scoped_ptr<ResourceHost>();
}

View File

@ -18,12 +18,6 @@ namespace {
base::StaticAtomicSequenceNumber g_next_id;
CefRefPtr<CefBrowserContextImpl> GetImpl(CefRefPtr<CefBrowserContext> context) {
if (context->IsProxy())
return static_cast<CefBrowserContextProxy*>(context.get())->parent();
return static_cast<CefBrowserContextImpl*>(context.get());
}
} // namespace
@ -106,7 +100,8 @@ scoped_refptr<CefBrowserContext> CefRequestContextImpl::GetBrowserContext() {
if (other_.get()) {
// Share storage with |other_|.
parent = GetImpl(other_->GetBrowserContext());
parent = CefBrowserContextImpl::GetForContext(
other_->GetBrowserContext().get());
}
if (!parent.get()) {
@ -136,6 +131,7 @@ scoped_refptr<CefBrowserContext> CefRequestContextImpl::GetBrowserContext() {
// Use a proxy that will execute handler callbacks where appropriate and
// otherwise forward all requests to the parent implementation.
browser_context_ = new CefBrowserContextProxy(handler_, parent);
browser_context_->Initialize();
} else {
// Use the parent implementation directly.
browser_context_ = parent;
@ -152,7 +148,9 @@ scoped_refptr<CefBrowserContext> CefRequestContextImpl::GetBrowserContext() {
}
if (!request_context_impl_) {
request_context_impl_ = GetImpl(browser_context_)->request_context().get();
request_context_impl_ =
CefBrowserContextImpl::GetForContext(browser_context_.get())->
request_context().get();
DCHECK(request_context_impl_);
}

View File

@ -20,7 +20,11 @@
#include "net/ssl/client_cert_store_mac.h"
#endif
CefResourceContext::CefResourceContext() {
CefResourceContext::CefResourceContext(
bool is_off_the_record,
extensions::InfoMap* extension_info_map)
: is_off_the_record_(is_off_the_record),
extension_info_map_(extension_info_map) {
}
CefResourceContext::~CefResourceContext() {

View File

@ -7,6 +7,7 @@
#pragma once
#include "content/public/browser/resource_context.h"
#include "extensions/browser/info_map.h"
class CefURLRequestContextGetter;
@ -20,7 +21,8 @@ class CefURLRequestContextGetter;
// See browser_context.h for an object relationship diagram.
class CefResourceContext : public content::ResourceContext {
public:
CefResourceContext();
CefResourceContext(bool is_off_the_record,
extensions::InfoMap* extension_info_map);
~CefResourceContext() override;
// ResourceContext implementation.
@ -31,9 +33,18 @@ class CefResourceContext : public content::ResourceContext {
void set_url_request_context_getter(
scoped_refptr<CefURLRequestContextGetter> getter);
// State transferred from the BrowserContext for use on the IO thread.
bool IsOffTheRecord() const { return is_off_the_record_; }
const extensions::InfoMap* GetExtensionInfoMap() const {
return extension_info_map_.get();
}
private:
scoped_refptr<CefURLRequestContextGetter> getter_;
bool is_off_the_record_;
scoped_refptr<extensions::InfoMap> extension_info_map_;
DISALLOW_COPY_AND_ASSIGN(CefResourceContext);
};

View File

@ -1,18 +1,30 @@
// Copyright (c) 2012 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.
// Copyright 2015 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/resource_dispatcher_host_delegate.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/extensions/api/streams_private/streams_private_api.h"
#include "libcef/browser/origin_whitelist_impl.h"
#include "libcef/browser/resource_context.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/extensions/extensions_util.h"
#include "base/guid.h"
#include "base/memory/scoped_vector.h"
#include "components/navigation_interception/intercept_navigation_resource_throttle.h"
#include "components/navigation_interception/navigation_params.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/plugin_service_filter.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/stream_info.h"
#include "content/public/common/resource_response.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
@ -29,7 +41,6 @@ bool NavigationOnUIThread(
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForContents(source);
DCHECK(browser.get());
if (browser.get()) {
CefRefPtr<CefClient> client = browser->GetClient();
if (client.get()) {
@ -50,6 +61,72 @@ bool NavigationOnUIThread(
return ignore_navigation;
}
// TODO(raymes): This won't return the right result if plugins haven't been
// loaded yet. Fixing this properly really requires fixing crbug.com/443466.
bool IsPluginEnabledForExtension(const extensions::Extension* extension,
const content::ResourceRequestInfo* info,
const std::string& mime_type,
const GURL& url) {
content::PluginService* service = content::PluginService::GetInstance();
std::vector<content::WebPluginInfo> plugins;
service->GetPluginInfoArray(url, mime_type, true, &plugins, nullptr);
content::PluginServiceFilter* filter = service->GetFilter();
for (auto& plugin : plugins) {
// Check that the plugin is running the extension.
if (plugin.path !=
base::FilePath::FromUTF8Unsafe(extension->url().spec())) {
continue;
}
// Check that the plugin is actually enabled.
if (!filter || filter->IsPluginAvailable(info->GetChildID(),
info->GetRenderFrameID(),
info->GetContext(),
url,
GURL(),
&plugin)) {
return true;
}
}
return false;
}
void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamInfo> stream,
int64 expected_content_size,
int render_process_id,
int render_frame_id,
const std::string& extension_id,
const std::string& view_id,
bool embedded) {
CEF_REQUIRE_UIT();
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForFrame(render_process_id,
render_frame_id);
if (!browser.get())
return;
content::WebContents* web_contents = browser->web_contents();
if (!web_contents)
return;
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
extensions::StreamsPrivateAPI* streams_private =
extensions::StreamsPrivateAPI::Get(browser_context);
if (!streams_private)
return;
// A |tab_id| value of -1 disables zoom management in the PDF extension.
// Otherwise we need to implement chrome.tabs zoom handling. See
// chrome/browser/resources/pdf/browser_api.js.
int tab_id = -1;
streams_private->ExecuteMimeTypeHandler(
extension_id, tab_id, stream.Pass(), view_id, expected_content_size,
embedded, render_process_id, render_frame_id);
}
} // namespace
CefResourceDispatcherHostDelegate::CefResourceDispatcherHostDelegate() {
@ -103,6 +180,82 @@ bool CefResourceDispatcherHostDelegate::HandleExternalProtocol(
return false;
}
// Implementation based on
// ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream.
bool CefResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
net::URLRequest* request,
const std::string& mime_type,
GURL* origin,
std::string* payload) {
if (!extensions::ExtensionsEnabled())
return false;
const content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
CefResourceContext* context =
static_cast<CefResourceContext*>(info->GetContext());
bool profile_is_off_the_record = context->IsOffTheRecord();
const scoped_refptr<const extensions::InfoMap> extension_info_map(
context->GetExtensionInfoMap());
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
// Go through the white-listed extensions and try to use them to intercept
// the URL request.
for (const std::string& extension_id : whitelist) {
const extensions::Extension* extension =
extension_info_map->extensions().GetByID(extension_id);
// The white-listed extension may not be installed, so we have to NULL check
// |extension|.
if (!extension ||
(profile_is_off_the_record &&
!extension_info_map->IsIncognitoEnabled(extension_id))) {
continue;
}
MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
if (handler && handler->CanHandleMIMEType(mime_type)) {
StreamTargetInfo target_info;
*origin = extensions::Extension::GetBaseURLFromExtensionId(extension_id);
target_info.extension_id = extension_id;
if (!handler->handler_url().empty()) {
// This is reached in the case of MimeHandlerViews. If the
// MimeHandlerView plugin is disabled, then we shouldn't intercept the
// stream.
if (!IsPluginEnabledForExtension(extension, info, mime_type,
request->url())) {
continue;
}
target_info.view_id = base::GenerateGUID();
*payload = target_info.view_id;
}
stream_target_info_[request] = target_info;
return true;
}
}
return false;
}
// Implementation based on
// ChromeResourceDispatcherHostDelegate::OnStreamCreated.
void CefResourceDispatcherHostDelegate::OnStreamCreated(
net::URLRequest* request,
scoped_ptr<content::StreamInfo> stream) {
DCHECK(extensions::ExtensionsEnabled());
const content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
std::map<net::URLRequest*, StreamTargetInfo>::iterator ix =
stream_target_info_.find(request);
CHECK(ix != stream_target_info_.end());
bool embedded = info->GetResourceType() != content::RESOURCE_TYPE_MAIN_FRAME;
CEF_POST_TASK(CEF_UIT,
base::Bind(&SendExecuteMimeTypeHandlerEvent, base::Passed(&stream),
request->GetExpectedContentSize(), info->GetChildID(),
info->GetRenderFrameID(), ix->second.extension_id,
ix->second.view_id, embedded));
stream_target_info_.erase(request);
}
void CefResourceDispatcherHostDelegate::OnRequestRedirected(
const GURL& redirect_url,
net::URLRequest* request,

View File

@ -1,11 +1,14 @@
// Copyright (c) 2012 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.
// Copyright 2015 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_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#define CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#pragma once
#include <map>
#include "base/compiler_specific.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@ -29,6 +32,12 @@ class CefResourceDispatcherHostDelegate
bool is_main_frame,
ui::PageTransition page_transition,
bool has_user_gesture) override;
bool ShouldInterceptResourceAsStream(net::URLRequest* request,
const std::string& mime_type,
GURL* origin,
std::string* payload) override;
void OnStreamCreated(net::URLRequest* request,
scoped_ptr<content::StreamInfo> stream) override;
void OnRequestRedirected(
const GURL& redirect_url,
net::URLRequest* request,
@ -36,6 +45,12 @@ class CefResourceDispatcherHostDelegate
content::ResourceResponse* response) override;
private:
struct StreamTargetInfo {
std::string extension_id;
std::string view_id;
};
std::map<net::URLRequest*, StreamTargetInfo> stream_target_info_;
DISALLOW_COPY_AND_ASSIGN(CefResourceDispatcherHostDelegate);
};

View File

@ -8,11 +8,17 @@
#include "libcef/browser/render_widget_host_view_osr.h"
#include "libcef/common/drag_data_impl.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/user_metrics.h"
CefWebContentsViewOSR::CefWebContentsViewOSR()
: web_contents_(NULL),
view_(NULL) {
view_(NULL),
guest_(NULL) {
}
CefWebContentsViewOSR::~CefWebContentsViewOSR() {
@ -24,6 +30,11 @@ void CefWebContentsViewOSR::set_web_contents(
web_contents_ = web_contents;
}
void CefWebContentsViewOSR::set_guest(content::BrowserPluginGuest* guest) {
DCHECK(!guest_);
guest_ = guest;
}
gfx::NativeView CefWebContentsViewOSR::GetNativeView() const {
return gfx::NativeView();
}
@ -37,10 +48,32 @@ gfx::NativeWindow CefWebContentsViewOSR::GetTopLevelNativeWindow() const {
}
void CefWebContentsViewOSR::GetContainerBounds(gfx::Rect* out) const {
if (guest_) {
// Based on WebContentsViewGuest::GetContainerBounds.
if (guest_->embedder_web_contents()) {
// We need embedder container's bounds to calculate our bounds.
guest_->embedder_web_contents()->GetView()->GetContainerBounds(out);
gfx::Point guest_coordinates = guest_->GetScreenCoordinates(gfx::Point());
out->Offset(guest_coordinates.x(), guest_coordinates.y());
} else {
out->set_origin(gfx::Point());
}
out->set_size(size_);
return;
}
*out = GetViewBounds();
}
void CefWebContentsViewOSR::SizeContents(const gfx::Size& size) {
if (guest_) {
// Based on WebContentsViewGuest::SizeContents.
size_ = size;
content::RenderWidgetHostView* rwhv =
web_contents_->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetSize(size);
}
}
void CefWebContentsViewOSR::Focus() {
@ -60,11 +93,20 @@ content::DropData* CefWebContentsViewOSR::GetDropData() const {
}
gfx::Rect CefWebContentsViewOSR::GetViewBounds() const {
if (guest_) {
// Based on WebContentsViewGuest::GetViewBounds.
return gfx::Rect(size_);
}
return view_ ? view_->GetViewBounds() : gfx::Rect();
}
void CefWebContentsViewOSR::CreateView(const gfx::Size& initial_size,
gfx::NativeView context) {
if (guest_) {
// Based on WebContentsViewGuest::CreateView.
size_ = initial_size;
}
}
content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
@ -75,6 +117,16 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
render_widget_host->GetView());
}
if (guest_) {
// Based on WebContentsViewGuest::CreateViewForWidget.
CefRenderWidgetHostViewOSR* platform_widget =
new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
return new content::RenderWidgetHostViewGuest(
render_widget_host,
guest_,
platform_widget->GetWeakPtr());
}
view_ = new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
return view_;
}
@ -123,6 +175,28 @@ void CefWebContentsViewOSR::StartDragging(
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const content::DragEventSourceInfo& event_info) {
if (guest_) {
// Based on WebContentsViewGuest::StartDragging.
content::WebContentsImpl* embedder_web_contents =
guest_->embedder_web_contents();
embedder_web_contents->GetBrowserPluginEmbedder()->StartDrag(guest_);
content::RenderViewHostImpl* embedder_render_view_host =
static_cast<content::RenderViewHostImpl*>(
embedder_web_contents->GetRenderViewHost());
CHECK(embedder_render_view_host);
content::RenderViewHostDelegateView* view =
embedder_render_view_host->GetDelegate()->GetDelegateView();
if (view) {
content::RecordAction(
base::UserMetricsAction("BrowserPlugin.Guest.StartDrag"));
view->StartDragging(drop_data, allowed_ops, image, image_offset,
event_info);
} else {
embedder_web_contents->SystemDragEnded();
}
return;
}
CefRefPtr<CefBrowserHostImpl> browser;
CefRefPtr<CefRenderHandler> handler;
bool handled = false;
@ -150,6 +224,19 @@ void CefWebContentsViewOSR::StartDragging(
void CefWebContentsViewOSR::UpdateDragCursor(
blink::WebDragOperation operation) {
if (guest_) {
// Based on WebContentsViewGuest::UpdateDragCursor.
content::RenderViewHostImpl* embedder_render_view_host =
static_cast<content::RenderViewHostImpl*>(
guest_->embedder_web_contents()->GetRenderViewHost());
CHECK(embedder_render_view_host);
content::RenderViewHostDelegateView* view =
embedder_render_view_host->GetDelegate()->GetDelegateView();
if (view)
view->UpdateDragCursor(operation);
return;
}
CefRefPtr<CefBrowserHostImpl> browser;
CefRefPtr<CefRenderHandler> handler;
CefRenderWidgetHostViewOSR* view =

View File

@ -10,6 +10,7 @@
#include "content/browser/web_contents/web_contents_view.h"
namespace content {
class BrowserPluginGuest;
class WebContents;
class WebContentsViewDelegate;
}
@ -24,6 +25,7 @@ class CefWebContentsViewOSR : public content::WebContentsView,
~CefWebContentsViewOSR() override;
void set_web_contents(content::WebContents* web_contents);
void set_guest(content::BrowserPluginGuest* guest);
// WebContentsView methods.
gfx::NativeView GetNativeView() const override;
@ -69,6 +71,9 @@ class CefWebContentsViewOSR : public content::WebContentsView,
content::WebContents* web_contents_;
CefRenderWidgetHostViewOSR* view_;
content::BrowserPluginGuest* guest_;
gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(CefWebContentsViewOSR);
};

View File

@ -15,13 +15,46 @@
#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ipc/ipc_message_macros.h"
// Singly-included section for enums and custom IPC traits.
#ifndef CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
#define CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
// Based on ChromeViewHostMsg_GetPluginInfo_Status.
enum class CefViewHostMsg_GetPluginInfo_Status {
kAllowed,
kBlocked,
kBlockedByPolicy,
kDisabled,
kNotFound,
kNPAPINotSupported,
kOutdatedBlocked,
kOutdatedDisallowed,
kPlayImportantContent,
kUnauthorized,
};
namespace IPC {
// Extracted from chrome/common/automation_messages.h.
template <>
struct ParamTraits<scoped_refptr<net::UploadData> > {
typedef scoped_refptr<net::UploadData> param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
} // namespace IPC
#endif // CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
// TODO(cef): Re-using the message start for extensions may be problematic in
// the future. It would be better if ipc_message_utils.h contained a value
// reserved for consumers of the content API.
// See: http://crbug.com/110911
#define IPC_MESSAGE_START ExtensionMsgStart
// Common types.
// Parameters structure for a request.
@ -130,6 +163,11 @@ IPC_MESSAGE_ROUTED1(CefMsg_Response,
IPC_MESSAGE_ROUTED1(CefMsg_ResponseAck,
int /* request_id */)
// Sent on process startup to indicate whether this process is running in
// incognito mode. Based on ChromeViewMsg_SetIsIncognitoProcess.
IPC_MESSAGE_CONTROL1(CefProcessMsg_SetIsIncognitoProcess,
bool /* is_incognito_processs */)
// Sent to child processes to add or remove a cross-origin whitelist entry.
IPC_MESSAGE_CONTROL2(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
bool /* add */,
@ -159,6 +197,7 @@ IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewBrowserInfo_Params)
IPC_STRUCT_MEMBER(int, browser_id)
IPC_STRUCT_MEMBER(bool, is_popup)
IPC_STRUCT_MEMBER(bool, is_windowless)
IPC_STRUCT_MEMBER(bool, is_mime_handler_view)
IPC_STRUCT_END()
// Retrieve information about a newly created browser.
@ -168,6 +207,29 @@ IPC_SYNC_MESSAGE_CONTROL2_1(
int /* render_frame_routing_id */,
CefProcessHostMsg_GetNewBrowserInfo_Params /* params*/)
IPC_ENUM_TRAITS_MAX_VALUE(CefViewHostMsg_GetPluginInfo_Status,
CefViewHostMsg_GetPluginInfo_Status::kUnauthorized)
// Output parameters for CefViewHostMsg_GetPluginInfo message.
IPC_STRUCT_BEGIN(CefViewHostMsg_GetPluginInfo_Output)
IPC_STRUCT_MEMBER(CefViewHostMsg_GetPluginInfo_Status, status)
IPC_STRUCT_MEMBER(content::WebPluginInfo, plugin)
IPC_STRUCT_MEMBER(std::string, actual_mime_type)
IPC_STRUCT_MEMBER(std::string, group_identifier)
IPC_STRUCT_MEMBER(base::string16, group_name)
IPC_STRUCT_END()
// Return information about a plugin for the given URL and MIME type.
// In contrast to ViewHostMsg_GetPluginInfo in content/, this IPC call knows
// about specific reasons why a plugin can't be used, for example because it's
// disabled. Based on ChromeViewHostMsg_GetPluginInfo.
IPC_SYNC_MESSAGE_CONTROL4_1(CefViewHostMsg_GetPluginInfo,
int /* render_frame_id */,
GURL /* url */,
GURL /* top origin url */,
std::string /* mime_type */,
CefViewHostMsg_GetPluginInfo_Output /* output */)
// Sent when a frame is identified for the first time.
IPC_MESSAGE_ROUTED3(CefHostMsg_FrameIdentified,
int64 /* frame_id */,
@ -198,23 +260,3 @@ IPC_MESSAGE_ROUTED1(CefHostMsg_ResponseAck,
// Sent by the renderer when the draggable regions are updated.
IPC_MESSAGE_ROUTED1(CefHostMsg_UpdateDraggableRegions,
std::vector<Cef_DraggableRegion_Params> /* regions */)
// Singly-included section for struct and custom IPC traits.
#ifndef CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
#define CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
namespace IPC {
// Extracted from chrome/common/automation_messages.h.
template <>
struct ParamTraits<scoped_refptr<net::UploadData> > {
typedef scoped_refptr<net::UploadData> param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
} // namespace IPC
#endif // CEF_LIBCEF_COMMON_CEF_MESSAGES_H_

View File

@ -100,4 +100,7 @@ const char kEnableSystemFlash[] = "enable-system-flash";
// Disable scroll bounce (rubber-banding) on OS X Lion and newer.
const char kDisableScrollBounce[] = "disable-scroll-bounce";
// Disable the PDF extension.
const char kDisablePdfExtension[] = "disable-pdf-extension";
} // namespace switches

View File

@ -43,6 +43,7 @@ extern const char kEnableSpellingService[];
extern const char kOverrideSpellCheckLang[];
extern const char kEnableSystemFlash[];
extern const char kDisableScrollBounce[];
extern const char kDisablePdfExtension[];
} // namespace switches

View File

@ -1,4 +1,5 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright 2015 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.
@ -6,7 +7,9 @@
#include "include/cef_stream.h"
#include "include/cef_version.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/extensions/pdf_extension_util.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/scheme_registrar_impl.h"
#include "libcef/common/scheme_registration.h"
@ -28,16 +31,54 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/user_agent.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "ui/base/resource/resource_bundle.h"
namespace {
CefContentClient* g_content_client = NULL;
// The following Flash-related methods are from
// The following plugin-related methods are from
// chrome/common/chrome_content_client.cc
const char kPDFPluginExtension[] = "pdf";
const char kPDFPluginDescription[] = "Portable Document Format";
const char kPDFPluginOutOfProcessMimeType[] =
"application/x-google-chrome-pdf";
const uint32 kPDFPluginPermissions = ppapi::PERMISSION_PRIVATE |
ppapi::PERMISSION_DEV;
content::PepperPluginInfo::GetInterfaceFunc g_pdf_get_interface;
content::PepperPluginInfo::PPP_InitializeModuleFunc g_pdf_initialize_module;
content::PepperPluginInfo::PPP_ShutdownModuleFunc g_pdf_shutdown_module;
// Appends the known built-in plugins to the given vector. Some built-in
// plugins are "internal" which means they are compiled into the Chrome binary,
// and some are extra shared libraries distributed with the browser (these are
// not marked internal, aside from being automatically registered, they're just
// regular plugins).
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
if (extensions::PdfExtensionEnabled()) {
content::PepperPluginInfo pdf_info;
pdf_info.is_internal = true;
pdf_info.is_out_of_process = true;
pdf_info.name = extensions::pdf_extension_util::kPdfPluginName;
pdf_info.description = kPDFPluginDescription;
pdf_info.path =
base::FilePath::FromUTF8Unsafe(CefContentClient::kPDFPluginPath);
content::WebPluginMimeType pdf_mime_type(
kPDFPluginOutOfProcessMimeType,
kPDFPluginExtension,
kPDFPluginDescription);
pdf_info.mime_types.push_back(pdf_mime_type);
pdf_info.internal_entry_points.get_interface = g_pdf_get_interface;
pdf_info.internal_entry_points.initialize_module = g_pdf_initialize_module;
pdf_info.internal_entry_points.shutdown_module = g_pdf_shutdown_module;
pdf_info.permissions = kPDFPluginPermissions;
plugins->push_back(pdf_info);
}
}
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
const std::string& version) {
content::PepperPluginInfo plugin;
@ -162,6 +203,8 @@ bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) {
} // namespace
const char CefContentClient::kPDFPluginPath[] = "internal-pdf-viewer";
CefContentClient::CefContentClient(CefRefPtr<CefApp> application)
: application_(application),
pack_loading_disabled_(false),
@ -182,6 +225,7 @@ CefContentClient* CefContentClient::Get() {
void CefContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
ComputeBuiltInPlugins(plugins);
AddPepperFlashFromCommandLine(plugins);
content::PepperPluginInfo plugin;
@ -205,7 +249,7 @@ void CefContentClient::AddAdditionalSchemes(
DCHECK(schemeRegistrar->VerifyRefCount());
}
scheme::AddInternalSchemes(standard_schemes);
scheme::AddInternalSchemes(standard_schemes, savable_schemes);
scheme_info_list_locked_ = true;
}
@ -289,6 +333,16 @@ bool CefContentClient::HasCustomScheme(const std::string& scheme_name) {
return false;
}
// static
void CefContentClient::SetPDFEntryFunctions(
content::PepperPluginInfo::GetInterfaceFunc get_interface,
content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module) {
g_pdf_get_interface = get_interface;
g_pdf_initialize_module = initialize_module;
g_pdf_shutdown_module = shutdown_module;
}
base::FilePath CefContentClient::GetPathForResourcePack(
const base::FilePath& pack_path,
ui::ScaleFactor scale_factor) {

View File

@ -1,4 +1,5 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright 2015 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.
@ -14,11 +15,14 @@
#include "base/compiler_specific.h"
#include "content/public/common/content_client.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ui/base/resource/resource_bundle.h"
class CefContentClient : public content::ContentClient,
public ui::ResourceBundle::Delegate {
public:
static const char kPDFPluginPath[];
explicit CefContentClient(CefRefPtr<CefApp> application);
~CefContentClient() override;
@ -41,6 +45,7 @@ class CefContentClient : public content::ContentClient,
struct SchemeInfo {
std::string scheme_name;
bool is_standard;
bool is_savable;
bool is_local;
bool is_display_isolated;
};
@ -57,6 +62,11 @@ class CefContentClient : public content::ContentClient,
bool pack_loading_disabled() const { return pack_loading_disabled_; }
void set_allow_pack_file_load(bool val) { allow_pack_file_load_ = val; }
static void SetPDFEntryFunctions(
content::PepperPluginInfo::GetInterfaceFunc get_interface,
content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module);
private:
// ui::ResourceBundle::Delegate methods.
base::FilePath GetPathForResourcePack(

View File

@ -0,0 +1,37 @@
This directory provides Mojo API definitions for CEF.
To add a new Mojo API:
<api> is the name of the API definition (e.g. 'streams_private').
<class> is the name of the class implementation (e.g. 'StreamsPrivateAPI').
1. Add libcef/common/extensions/api/<api>.idl file which defines the API.
2. Add <api>.idl to the 'schema_files' list in
libcef/common/extensions/api/schemas.gypi. Serialization code will be
generated based on this list in step 5.
3. Add an entry to libcef/common/extensions/api/_api_features.json if
necessary [1].
4. Add libcef/browser/extensions/api/<api>/<api>_api.[h|cc] class implementation
files and associated entries to the 'libcef_static' target in cef.gyp.
5. Run the cef_create_projects script and build to generate the
cef/libcef/common/extensions/api/<api>.h file and other serialization code
required by the extensions system.
6. Call `<class>::GetInstance();` or `<class>Factory::GetFactoryInstance();` [2]
from EnsureBrowserContextKeyedServiceFactoriesBuilt in
libcef/browser/extensions/browser_context_keyed_service_factories.cc.
7. Call `DependsOn(<class>Factory::GetInstance());` from
CefExtensionSystemFactory::CefExtensionSystemFactory in
libcef/browser/extensions/extension_system_factory.cc if necessary [2].
See https://www.chromium.org/developers/design-documents/mojo for more
information.
[1] A feature can optionally express requirements for where it can be accessed.
See the _api_features.json file for additional details.
[2] Some Mojo APIs use singleton Factory objects that create a one-to-one
relationship between a service and a BrowserContext. This is used primarily
to control shutdown/destruction order and implementors must explicitly state
which services are depended on. See comments in
components/keyed_service/content/browser_context_keyed_service_factory.h
for additional details.

View File

@ -0,0 +1,18 @@
// 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.
// This file defines extension APIs implemented in CEF.
// See extensions/common/features/* to understand this file, in particular
// feature.h, simple_feature.h, and base_feature_provider.h.
{
// From chrome/common/extensions/api/_api_features.json.
// Required by the PDF extension which is hosted in a guest view.
"mimeHandlerViewGuestInternal": {
"internal": true,
"contexts": "all",
"channel": "stable",
"matches": ["<all_urls>"]
}
}

View File

@ -0,0 +1,19 @@
# 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.
{
'targets': [
{
'target_name': 'cef_api',
'type': 'static_library',
# TODO(jschuh): http://crbug.com/167187 size_t -> int
'msvs_disabled_warnings': [ 4267 ],
'includes': [
'../../../../../build/json_schema_bundle_compile.gypi',
'../../../../../build/json_schema_compile.gypi',
'schemas.gypi',
],
},
],
}

View File

@ -0,0 +1,22 @@
# 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.
{
'sources': [
'<@(schema_files)',
],
'variables': {
'schema_files': [
'streams_private.idl',
],
'non_compiled_schema_files': [
],
'chromium_code': 1,
'cc_dir': 'cef/libcef/common/extensions/api',
# Match the Chrome namespace to minimize code changes.
'root_namespace': 'extensions::api::%(namespace)s',
'impl_dir_': 'cef/libcef/browser/extensions/api',
},
}

View File

@ -0,0 +1,57 @@
// 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.
// Streams Private API.
namespace streamsPrivate {
dictionary StreamInfo {
// The MIME type of the intercepted URL request.
DOMString mimeType;
// The original URL that was intercepted.
DOMString originalUrl;
// The URL that the stream can be read from.
DOMString streamUrl;
// The ID of the tab that opened the stream. If the stream is not opened in
// a tab, it will be -1.
long tabId;
// The ID of the view that will render the stream, if the viewer was opened
// in a plugin.
DOMString? viewId;
// The amount of data the Stream should contain, if known. If there is no
// information on the size it will be -1.
long expectedContentSize;
// The HTTP response headers of the intercepted request stored as a
// dictionary mapping header name to header value. If a header name appears
// multiple times, the header values are merged in the dictionary and
// separated by a ", ".
object responseHeaders;
// Whether the stream is embedded within another document.
boolean embedded;
};
callback AbortCallback = void ();
interface Functions {
// Abort the URL request on the given stream.
// |streamUrl| : The URL of the stream to abort.
// |callback| : Called when the stream URL is guaranteed to be invalid. The
// underlying URL request may not yet have been aborted when this is run.
static void abort(DOMString streamUrl,
optional AbortCallback callback);
};
interface Events {
// Fired when a resource is fetched which matches a mime type handled by
// this extension. The resource request is cancelled, and the extension is
// expected to handle the request. The event is restricted to a small number
// of white-listed extensions.
static void onExecuteMimeTypeHandler(StreamInfo streamInfo);
};
};

View File

@ -0,0 +1,243 @@
// Copyright 2015 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/common/extensions/extensions_client.h"
#include "libcef/common/cef_switches.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "cef/libcef/common/extensions/api/generated_schemas.h"
#include "extensions/common/api/generated_schemas.h"
#include "extensions/common/common_manifest_handlers.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/features/api_feature.h"
#include "extensions/common/features/base_feature_provider.h"
#include "extensions/common/features/behavior_feature.h"
#include "extensions/common/features/json_feature_provider_source.h"
#include "extensions/common/features/manifest_feature.h"
#include "extensions/common/features/permission_feature.h"
#include "extensions/common/features/simple_feature.h"
#include "extensions/common/manifest_handler.h"
#include "extensions/common/permissions/permission_message_provider.h"
#include "extensions/common/permissions/permissions_info.h"
#include "extensions/common/permissions/permissions_provider.h"
#include "extensions/common/url_pattern_set.h"
#include "grit/cef_resources.h"
#include "grit/extensions_resources.h"
namespace extensions {
namespace {
template <class FeatureClass>
SimpleFeature* CreateFeature() {
return new FeatureClass;
}
// TODO(jamescook): Refactor ChromePermissionsMessageProvider so we can share
// code. For now, this implementation does nothing.
class CefPermissionMessageProvider : public PermissionMessageProvider {
public:
CefPermissionMessageProvider() {}
~CefPermissionMessageProvider() override {}
// PermissionMessageProvider implementation.
PermissionMessageIDs GetLegacyPermissionMessageIDs(
const PermissionSet* permissions,
Manifest::Type extension_type) const override {
return PermissionMessageIDs();
}
CoalescedPermissionMessages GetCoalescedPermissionMessages(
const PermissionIDSet& permissions) const override {
return CoalescedPermissionMessages();
}
std::vector<base::string16> GetLegacyWarningMessages(
const PermissionSet* permissions,
Manifest::Type extension_type) const override {
return std::vector<base::string16>();
}
std::vector<base::string16> GetLegacyWarningMessagesDetails(
const PermissionSet* permissions,
Manifest::Type extension_type) const override {
return std::vector<base::string16>();
}
bool IsPrivilegeIncrease(const PermissionSet* old_permissions,
const PermissionSet* new_permissions,
Manifest::Type extension_type) const override {
// Ensure we implement this before shipping.
CHECK(false);
return false;
}
PermissionIDSet GetAllPermissionIDs(
const PermissionSet* permissions,
Manifest::Type extension_type) const override {
return PermissionIDSet();
}
private:
DISALLOW_COPY_AND_ASSIGN(CefPermissionMessageProvider);
};
base::LazyInstance<CefPermissionMessageProvider>
g_permission_message_provider = LAZY_INSTANCE_INITIALIZER;
} // namespace
CefExtensionsClient::CefExtensionsClient()
: extensions_api_permissions_(ExtensionsAPIPermissions()) {
}
CefExtensionsClient::~CefExtensionsClient() {
}
void CefExtensionsClient::Initialize() {
RegisterCommonManifestHandlers();
ManifestHandler::FinalizeRegistration();
// TODO(jamescook): Do we need to whitelist any extensions?
PermissionsInfo::GetInstance()->AddProvider(extensions_api_permissions_);
}
const PermissionMessageProvider&
CefExtensionsClient::GetPermissionMessageProvider() const {
NOTIMPLEMENTED();
return g_permission_message_provider.Get();
}
const std::string CefExtensionsClient::GetProductName() {
return "cef";
}
scoped_ptr<FeatureProvider> CefExtensionsClient::CreateFeatureProvider(
const std::string& name) const {
scoped_ptr<FeatureProvider> provider;
scoped_ptr<JSONFeatureProviderSource> source(
CreateFeatureProviderSource(name));
if (name == "api") {
provider.reset(new BaseFeatureProvider(source->dictionary(),
CreateFeature<APIFeature>));
} else if (name == "manifest") {
provider.reset(new BaseFeatureProvider(source->dictionary(),
CreateFeature<ManifestFeature>));
} else if (name == "permission") {
provider.reset(new BaseFeatureProvider(source->dictionary(),
CreateFeature<PermissionFeature>));
} else if (name == "behavior") {
provider.reset(new BaseFeatureProvider(source->dictionary(),
CreateFeature<BehaviorFeature>));
} else {
NOTREACHED();
}
return provider.Pass();
}
scoped_ptr<JSONFeatureProviderSource>
CefExtensionsClient::CreateFeatureProviderSource(
const std::string& name) const {
scoped_ptr<JSONFeatureProviderSource> source(
new JSONFeatureProviderSource(name));
if (name == "api") {
source->LoadJSON(IDR_EXTENSION_API_FEATURES);
// Extension API features specific to CEF. See
// libcef/common/extensions/api/README.txt for additional details.
source->LoadJSON(IDR_CEF_EXTENSION_API_FEATURES);
} else if (name == "manifest") {
source->LoadJSON(IDR_EXTENSION_MANIFEST_FEATURES);
} else if (name == "permission") {
source->LoadJSON(IDR_EXTENSION_PERMISSION_FEATURES);
} else if (name == "behavior") {
source->LoadJSON(IDR_EXTENSION_BEHAVIOR_FEATURES);
} else {
NOTREACHED();
source.reset();
}
return source.Pass();
}
void CefExtensionsClient::FilterHostPermissions(
const URLPatternSet& hosts,
URLPatternSet* new_hosts,
std::set<PermissionMessage>* messages) const {
NOTIMPLEMENTED();
}
void CefExtensionsClient::FilterHostPermissions(
const URLPatternSet& hosts,
URLPatternSet* new_hosts,
PermissionIDSet* permissions) const {
NOTIMPLEMENTED();
}
void CefExtensionsClient::SetScriptingWhitelist(
const ScriptingWhitelist& whitelist) {
scripting_whitelist_ = whitelist;
}
const ExtensionsClient::ScriptingWhitelist&
CefExtensionsClient::GetScriptingWhitelist() const {
// TODO(jamescook): Real whitelist.
return scripting_whitelist_;
}
URLPatternSet CefExtensionsClient::GetPermittedChromeSchemeHosts(
const Extension* extension,
const APIPermissionSet& api_permissions) const {
return URLPatternSet();
}
bool CefExtensionsClient::IsScriptableURL(const GURL& url,
std::string* error) const {
return true;
}
bool CefExtensionsClient::IsAPISchemaGenerated(
const std::string& name) const {
return core_api::GeneratedSchemas::IsGenerated(name) ||
api::GeneratedSchemas::IsGenerated(name);
}
base::StringPiece CefExtensionsClient::GetAPISchema(
const std::string& name) const {
// Schema for CEF-only APIs.
if (api::GeneratedSchemas::IsGenerated(name))
return api::GeneratedSchemas::Get(name);
// Core extensions APIs.
return core_api::GeneratedSchemas::Get(name);
}
void CefExtensionsClient::RegisterAPISchemaResources(
ExtensionAPI* api) const {
}
bool CefExtensionsClient::ShouldSuppressFatalErrors() const {
return true;
}
void CefExtensionsClient::RecordDidSuppressFatalError() {
}
std::string CefExtensionsClient::GetWebstoreBaseURL() const {
return extension_urls::kChromeWebstoreBaseURL;
}
std::string CefExtensionsClient::GetWebstoreUpdateURL() const {
return extension_urls::kChromeWebstoreUpdateURL;
}
bool CefExtensionsClient::IsBlacklistUpdateURL(const GURL& url) const {
// TODO(rockot): Maybe we want to do something else here. For now we accept
// any URL as a blacklist URL because we don't really care.
return true;
}
} // namespace extensions

View File

@ -0,0 +1,63 @@
// Copyright 2015 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_COMMON_EXTENSIONS_EXTENSIONS_CLIENT_H_
#define CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_CLIENT_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "extensions/common/extensions_client.h"
#include "extensions/common/permissions/extensions_api_permissions.h"
namespace extensions {
// The CEF implementation of ExtensionsClient.
class CefExtensionsClient : public ExtensionsClient {
public:
CefExtensionsClient();
~CefExtensionsClient() override;
// ExtensionsClient overrides:
void Initialize() override;
const PermissionMessageProvider& GetPermissionMessageProvider()
const override;
const std::string GetProductName() override;
scoped_ptr<FeatureProvider> CreateFeatureProvider(
const std::string& name) const override;
scoped_ptr<JSONFeatureProviderSource> CreateFeatureProviderSource(
const std::string& name) const override;
void FilterHostPermissions(
const URLPatternSet& hosts,
URLPatternSet* new_hosts,
std::set<PermissionMessage>* messages) const override;
void FilterHostPermissions(const URLPatternSet& hosts,
URLPatternSet* new_hosts,
PermissionIDSet* permissions) const override;
void SetScriptingWhitelist(const ScriptingWhitelist& whitelist) override;
const ScriptingWhitelist& GetScriptingWhitelist() const override;
URLPatternSet GetPermittedChromeSchemeHosts(
const Extension* extension,
const APIPermissionSet& api_permissions) const override;
bool IsScriptableURL(const GURL& url, std::string* error) const override;
bool IsAPISchemaGenerated(const std::string& name) const override;
base::StringPiece GetAPISchema(const std::string& name) const override;
void RegisterAPISchemaResources(ExtensionAPI* api) const override;
bool ShouldSuppressFatalErrors() const override;
void RecordDidSuppressFatalError() override;
std::string GetWebstoreBaseURL() const override;
std::string GetWebstoreUpdateURL() const override;
bool IsBlacklistUpdateURL(const GURL& url) const override;
private:
const ExtensionsAPIPermissions extensions_api_permissions_;
ScriptingWhitelist scripting_whitelist_;
DISALLOW_COPY_AND_ASSIGN(CefExtensionsClient);
};
} // namespace extensions
#endif // CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_CLIENT_H_

View File

@ -0,0 +1,28 @@
// Copyright 2015 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/common/extensions/extensions_util.h"
#include "libcef/common/cef_switches.h"
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
namespace extensions {
bool ExtensionsEnabled() {
static bool enabled = !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableExtensions);
return enabled;
}
bool PdfExtensionEnabled() {
static bool enabled =
ExtensionsEnabled() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisablePdfExtension);
return enabled;
}
} // namespace extensions

View File

@ -0,0 +1,18 @@
// Copyright 2015 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_COMMON_EXTENSIONS_EXTENSIONS_UTIL_H_
#define CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_UTIL_H_
namespace extensions {
// Returns true if extensions have not been disabled via the command-line.
bool ExtensionsEnabled();
// Returns true if the PDF extension has not been disabled via the command-line.
bool PdfExtensionEnabled();
} // namespace extensions
#endif // CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_UTIL_H_

View File

@ -8,6 +8,7 @@
#include "libcef/common/cef_switches.h"
#include "libcef/common/command_line_impl.h"
#include "libcef/common/crash_reporter_client.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/renderer/content_renderer_client.h"
#include "libcef/utility/content_utility_client.h"
@ -21,12 +22,14 @@
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "chrome/child/pdf_child_init.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "pdf/pdf.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
@ -524,6 +527,14 @@ void CefMainDelegate::PreSandboxStartup() {
content_client_.set_pack_loading_disabled(true);
InitializeResourceBundle();
chrome::InitializePDF();
}
void CefMainDelegate::SandboxInitialized(const std::string& process_type) {
CefContentClient::SetPDFEntryFunctions(
chrome_pdf::PPP_GetInterface,
chrome_pdf::PPP_InitializeModule,
chrome_pdf::PPP_ShutdownModule);
}
int CefMainDelegate::RunProcess(
@ -608,23 +619,28 @@ void CefMainDelegate::InitializeResourceBundle() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
base::FilePath cef_pak_file, cef_100_percent_pak_file,
cef_200_percent_pak_file, devtools_pak_file, locales_dir;
cef_200_percent_pak_file, cef_extensions_pak_file,
devtools_pak_file, locales_dir;
base::FilePath resources_dir;
if (command_line->HasSwitch(switches::kResourcesDirPath)) {
resources_dir =
command_line->GetSwitchValuePath(switches::kResourcesDirPath);
}
if (resources_dir.empty())
resources_dir = GetResourcesFilePath();
if (!resources_dir.empty())
PathService::Override(chrome::DIR_RESOURCES, resources_dir);
if (!content_client_.pack_loading_disabled()) {
base::FilePath resources_dir;
if (command_line->HasSwitch(switches::kResourcesDirPath)) {
resources_dir =
command_line->GetSwitchValuePath(switches::kResourcesDirPath);
}
if (resources_dir.empty())
resources_dir = GetResourcesFilePath();
if (!resources_dir.empty()) {
cef_pak_file = resources_dir.Append(FILE_PATH_LITERAL("cef.pak"));
cef_100_percent_pak_file =
resources_dir.Append(FILE_PATH_LITERAL("cef_100_percent.pak"));
cef_200_percent_pak_file =
resources_dir.Append(FILE_PATH_LITERAL("cef_200_percent.pak"));
cef_extensions_pak_file =
resources_dir.Append(FILE_PATH_LITERAL("cef_extensions.pak"));
devtools_pak_file =
resources_dir.Append(FILE_PATH_LITERAL("devtools_resources.pak"));
}
@ -685,6 +701,15 @@ void CefMainDelegate::InitializeResourceBundle() {
}
}
if (extensions::ExtensionsEnabled()) {
if (base::PathExists(cef_extensions_pak_file)) {
resource_bundle.AddDataPackFromPath(
cef_extensions_pak_file, ui::SCALE_FACTOR_NONE);
} else {
LOG(ERROR) << "Could not load cef_extensions.pak";
}
}
if (base::PathExists(devtools_pak_file)) {
resource_bundle.AddDataPackFromPath(
devtools_pak_file, ui::SCALE_FACTOR_NONE);

View File

@ -34,6 +34,7 @@ class CefMainDelegate : public content::ContentMainDelegate {
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
void SandboxInitialized(const std::string& process_type) override;
int RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) override;

View File

@ -6,20 +6,26 @@
#include "libcef/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#include "url/url_constants.h"
namespace scheme {
void AddInternalSchemes(std::vector<std::string>* standard_schemes) {
void AddInternalSchemes(std::vector<std::string>* standard_schemes,
std::vector<std::string>* savable_schemes) {
static CefContentClient::SchemeInfo schemes[] = {
{ content::kChromeUIScheme, true, true, true },
{ content::kChromeDevToolsScheme, true, false, true }
{ content::kChromeUIScheme, true, false, true, true },
{ content::kChromeDevToolsScheme, true, false, false, true },
{ extensions::kExtensionScheme, true, true, true, true },
{ extensions::kExtensionResourceScheme, true, true, false, true },
};
CefContentClient* client = CefContentClient::Get();
for (size_t i = 0; i < sizeof(schemes) / sizeof(schemes[0]); ++i) {
if (schemes[0].is_standard)
if (schemes[i].is_standard)
standard_schemes->push_back(schemes[i].scheme_name);
if (schemes[i].is_savable)
savable_schemes->push_back(schemes[i].scheme_name);
client->AddCustomScheme(schemes[i]);
}
}
@ -29,6 +35,8 @@ bool IsInternalHandledScheme(const std::string& scheme) {
url::kBlobScheme,
content::kChromeDevToolsScheme,
content::kChromeUIScheme,
extensions::kExtensionScheme,
extensions::kExtensionResourceScheme,
url::kDataScheme,
url::kFileScheme,
url::kFileSystemScheme,
@ -49,6 +57,8 @@ bool IsInternalProtectedScheme(const std::string& scheme) {
static const char* schemes[] = {
url::kBlobScheme,
content::kChromeUIScheme,
extensions::kExtensionScheme,
extensions::kExtensionResourceScheme,
url::kDataScheme,
url::kFileScheme,
url::kFileSystemScheme,

View File

@ -12,7 +12,8 @@
namespace scheme {
// Add internal schemes.
void AddInternalSchemes(std::vector<std::string>* standard_schemes);
void AddInternalSchemes(std::vector<std::string>* standard_schemes,
std::vector<std::string>* savable_schemes);
// Returns true if the specified |scheme| is handled internally.
bool IsInternalHandledScheme(const std::string& scheme);

View File

@ -9,9 +9,13 @@
#include "libcef/common/cef_messages.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h"
#include "libcef/common/extensions/extensions_client.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/values_impl.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/extensions/extensions_renderer_client.h"
#include "libcef/renderer/extensions/print_web_view_helper_delegate.h"
#include "libcef/renderer/pepper/pepper_helper.h"
#include "libcef/renderer/render_frame_observer.h"
#include "libcef/renderer/render_message_filter.h"
@ -24,9 +28,12 @@
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/pepper_permission_util.h"
#include "chrome/renderer/loadtimes_extension_bindings.h"
#include "chrome/renderer/pepper/chrome_pdf_print_client.h"
#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/renderer/spellchecker/spellcheck_provider.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/printing/renderer/print_web_view_helper.h"
#include "components/web_cache/renderer/web_cache_render_process_observer.h"
#include "content/child/worker_task_runner.h"
@ -41,6 +48,13 @@
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_view_visitor.h"
#include "content/renderer/render_frame_impl.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/dispatcher_delegate.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/guest_view/extensions_guest_view_container.h"
#include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
#include "ipc/ipc_sync_channel.h"
#include "media/base/media.h"
#include "third_party/WebKit/public/platform/WebPrerenderingSupport.h"
@ -135,31 +149,40 @@ class CefWebWorkerTaskRunner : public base::SequencedTaskRunner,
int worker_id_;
};
class CefPrintWebViewHelperDelegate :
public printing::PrintWebViewHelper::Delegate {
public:
CefPrintWebViewHelperDelegate() {}
void IsGuestViewApiAvailableToScriptContext(
bool* api_is_available,
extensions::ScriptContext* context) {
if (context->GetAvailability("guestViewInternal").is_available()) {
*api_is_available = true;
}
}
bool CancelPrerender(content::RenderView* render_view,
int routing_id) override {
return false;
void AppendParams(const std::vector<base::string16>& additional_names,
const std::vector<base::string16>& additional_values,
blink::WebVector<blink::WebString>* existing_names,
blink::WebVector<blink::WebString>* existing_values) {
DCHECK(additional_names.size() == additional_values.size());
DCHECK(existing_names->size() == existing_values->size());
size_t existing_size = existing_names->size();
size_t total_size = existing_size + additional_names.size();
blink::WebVector<blink::WebString> names(total_size);
blink::WebVector<blink::WebString> values(total_size);
for (size_t i = 0; i < existing_size; ++i) {
names[i] = (*existing_names)[i];
values[i] = (*existing_values)[i];
}
blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override {
return blink::WebElement();
for (size_t i = 0; i < additional_names.size(); ++i) {
names[existing_size + i] = additional_names[i];
values[existing_size + i] = additional_values[i];
}
bool IsPrintPreviewEnabled() override {
return false;
}
bool OverridePrint(blink::WebLocalFrame* frame) override {
return false;
}
private:
DISALLOW_COPY_AND_ASSIGN(CefPrintWebViewHelperDelegate);
};
existing_names->swap(names);
existing_values->swap(values);
}
} // namespace
@ -456,6 +479,32 @@ void CefContentRendererClient::RenderThreadStarted() {
}
#endif // defined(OS_MACOSX)
if (extensions::PdfExtensionEnabled()) {
pdf_print_client_.reset(new ChromePDFPrintClient());
pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get());
}
if (extensions::ExtensionsEnabled()) {
extensions_client_.reset(new extensions::CefExtensionsClient);
extensions::ExtensionsClient::Set(extensions_client_.get());
extensions_renderer_client_.reset(
new extensions::CefExtensionsRendererClient);
extensions::ExtensionsRendererClient::Set(
extensions_renderer_client_.get());
extension_dispatcher_delegate_.reset(new extensions::DispatcherDelegate());
// Must be initialized after ExtensionsRendererClient.
extension_dispatcher_.reset(
new extensions::Dispatcher(extension_dispatcher_delegate_.get()));
thread->AddObserver(extension_dispatcher_.get());
guest_view_container_dispatcher_.reset(
new extensions::ExtensionsGuestViewContainerDispatcher());
thread->AddObserver(guest_view_container_dispatcher_.get());
}
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
@ -474,11 +523,33 @@ void CefContentRendererClient::RenderFrameCreated(
content::RenderFrame* render_frame) {
new CefRenderFrameObserver(render_frame);
new CefPepperHelper(render_frame);
if (extensions::ExtensionsEnabled()) {
new extensions::ExtensionFrameHelper(render_frame,
extension_dispatcher_.get());
extension_dispatcher_->OnRenderFrameCreated(render_frame);
}
BrowserCreated(render_frame->GetRenderView(), render_frame);
}
void CefContentRendererClient::RenderViewCreated(
content::RenderView* render_view) {
new CefPrerendererClient(render_view);
new printing::PrintWebViewHelper(
render_view,
make_scoped_ptr<printing::PrintWebViewHelper::Delegate>(
new extensions::CefPrintWebViewHelperDelegate()));
if (extensions::ExtensionsEnabled()) {
new extensions::ExtensionHelper(render_view, extension_dispatcher_.get());
}
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kDisableSpellChecking))
new SpellCheckProvider(render_view, spellcheck_.get());
BrowserCreated(render_view, render_view->GetMainRenderFrame());
}
@ -487,62 +558,29 @@ bool CefContentRendererClient::OverrideCreatePlugin(
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params,
blink::WebPlugin** plugin) {
CefRefPtr<CefBrowserImpl> browser =
CefBrowserImpl::GetBrowserForMainFrame(frame->top());
if (!browser.get() || !browser->is_windowless())
if (!extensions::ExtensionsEnabled())
return false;
#if defined(ENABLE_PLUGINS)
if (base::UTF16ToASCII(params.mimeType) == content::kBrowserPluginMimeType)
return false;
content::RenderFrameImpl* render_frame_impl =
static_cast<content::RenderFrameImpl*>(render_frame);
content::WebPluginInfo info;
std::string mime_type;
bool found = false;
render_frame_impl->Send(
new FrameHostMsg_GetPluginInfo(
render_frame_impl->GetRoutingID(),
params.url,
frame->top()->document().url(),
params.mimeType.utf8(),
&found,
&info,
&mime_type));
if (!found)
return false;
bool silverlight = StartsWithASCII(mime_type,
"application/x-silverlight", false);
if (silverlight) {
// Force Flash and Silverlight plugins to use windowless mode.
blink::WebPluginParams params_to_use = params;
params_to_use.mimeType = blink::WebString::fromUTF8(mime_type);
size_t size = params.attributeNames.size();
blink::WebVector<blink::WebString> new_names(size+1),
new_values(size+1);
for (size_t i = 0; i < size; ++i) {
new_names[i] = params.attributeNames[i];
new_values[i] = params.attributeValues[i];
}
new_names[size] = "windowless";
new_values[size] = "true";
params_to_use.attributeNames.swap(new_names);
params_to_use.attributeValues.swap(new_values);
*plugin = render_frame_impl->CreatePlugin(
frame, info, params_to_use, nullptr);
return true;
// Based on ChromeContentRendererClient::OverrideCreatePlugin.
std::string orig_mime_type = params.mimeType.utf8();
if (orig_mime_type == content::kBrowserPluginMimeType) {
bool guest_view_api_available = false;
extension_dispatcher_->script_context_set().ForEach(
render_frame->GetRenderView(),
base::Bind(&IsGuestViewApiAvailableToScriptContext,
&guest_view_api_available));
if (guest_view_api_available)
return false;
}
#endif // defined(ENABLE_PLUGINS)
return false;
GURL url(params.url);
CefViewHostMsg_GetPluginInfo_Output output;
render_frame->Send(new CefViewHostMsg_GetPluginInfo(
render_frame->GetRoutingID(), url, frame->top()->document().url(),
orig_mime_type, &output));
*plugin = CreatePlugin(render_frame, frame, params, output);
return true;
}
bool CefContentRendererClient::HandleNavigation(
@ -561,7 +599,6 @@ bool CefContentRendererClient::HandleNavigation(
if (handler.get()) {
CefRefPtr<CefBrowserImpl> browserPtr =
CefBrowserImpl::GetBrowserForMainFrame(frame->top());
DCHECK(browserPtr.get());
if (browserPtr.get()) {
CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
CefRefPtr<CefRequest> requestPtr(CefRequest::Create());
@ -604,17 +641,37 @@ bool CefContentRendererClient::HandleNavigation(
return false;
}
content::BrowserPluginDelegate*
CefContentRendererClient::CreateBrowserPluginDelegate(
content::RenderFrame* render_frame,
const std::string& mime_type,
const GURL& original_url) {
DCHECK(extensions::ExtensionsEnabled());
if (mime_type == content::kBrowserPluginMimeType) {
return new extensions::ExtensionsGuestViewContainer(render_frame);
} else {
return new extensions::MimeHandlerViewContainer(
render_frame, mime_type, original_url);
}
}
void CefContentRendererClient::WillDestroyCurrentMessageLoop() {
base::AutoLock lock_scope(single_process_cleanup_lock_);
single_process_cleanup_complete_ = true;
}
bool CefContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
const GURL& url, const std::set<std::string>& whitelist) {
DCHECK(extensions::ExtensionsEnabled());
const extensions::ExtensionSet* extension_set =
CefContentRendererClient::Get()->extension_dispatcher_->extensions();
return chrome::IsExtensionOrSharedModuleWhitelisted(url, extension_set,
whitelist);
}
void CefContentRendererClient::BrowserCreated(
content::RenderView* render_view,
content::RenderFrame* render_frame) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
// Retrieve the browser information synchronously. This will also register
// the routing ids with the browser info object in the browser process.
CefProcessHostMsg_GetNewBrowserInfo_Params params;
@ -625,6 +682,11 @@ void CefContentRendererClient::BrowserCreated(
&params));
DCHECK_GT(params.browser_id, 0);
if (params.is_mime_handler_view) {
// Don't create a CefBrowser for mime handler views.
return;
}
// Don't create another browser object if one already exists for the view.
if (GetBrowserForView(render_view).get())
return;
@ -643,15 +705,6 @@ void CefContentRendererClient::BrowserCreated(
params.is_windowless);
browsers_.insert(std::make_pair(render_view, browser));
new CefPrerendererClient(render_view);
new printing::PrintWebViewHelper(
render_view,
make_scoped_ptr<printing::PrintWebViewHelper::Delegate>(
new CefPrintWebViewHelperDelegate()));
if (!command_line->HasSwitch(switches::kDisableSpellChecking))
new SpellCheckProvider(render_view, spellcheck_.get());
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
@ -690,3 +743,57 @@ void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() {
if (!CefContext::Get()->settings().multi_threaded_message_loop)
delete host;
}
blink::WebPlugin* CefContentRendererClient::CreatePlugin(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& original_params,
const CefViewHostMsg_GetPluginInfo_Output& output) {
const content::WebPluginInfo& info = output.plugin;
const std::string& actual_mime_type = output.actual_mime_type;
CefViewHostMsg_GetPluginInfo_Status status = output.status;
GURL url(original_params.url);
std::string orig_mime_type = original_params.mimeType.utf8();
// If the browser plugin is to be enabled, this should be handled by the
// renderer, so the code won't reach here due to the early exit in
// OverrideCreatePlugin.
if (status == CefViewHostMsg_GetPluginInfo_Status::kNotFound ||
orig_mime_type == content::kBrowserPluginMimeType) {
return NULL;
} else {
// TODO(bauerb): This should be in content/.
blink::WebPluginParams params(original_params);
for (size_t i = 0; i < info.mime_types.size(); ++i) {
if (info.mime_types[i].mime_type == actual_mime_type) {
AppendParams(info.mime_types[i].additional_param_names,
info.mime_types[i].additional_param_values,
&params.attributeNames, &params.attributeValues);
break;
}
}
if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) {
// Webkit might say that mime type is null while we already know the
// actual mime type via CefViewHostMsg_GetPluginInfo. In that case
// we should use what we know since WebpluginDelegateProxy does some
// specific initializations based on this information.
params.mimeType = blink::WebString::fromUTF8(actual_mime_type.c_str());
}
switch (status) {
case CefViewHostMsg_GetPluginInfo_Status::kNotFound: {
NOTREACHED();
break;
}
case CefViewHostMsg_GetPluginInfo_Status::kAllowed:
case CefViewHostMsg_GetPluginInfo_Status::kPlayImportantContent: {
// TODO(cef): Maybe supply a throttler based on power settings.
return render_frame->CreatePlugin(frame, info, params, nullptr);
}
default:
// TODO(cef): Provide a placeholder for the various failure conditions.
break;
}
}
return NULL;
}

View File

@ -20,12 +20,22 @@
#include "base/sequenced_task_runner.h"
#include "content/public/renderer/content_renderer_client.h"
namespace extensions {
class Dispatcher;
class DispatcherDelegate;
class ExtensionsClient;
class ExtensionsGuestViewContainerDispatcher;
class ExtensionsRendererClient;
}
namespace web_cache {
class WebCacheRenderProcessObserver;
}
class CefRenderProcessObserver;
struct Cef_CrossOriginWhiteListEntry_Params;
struct CefViewHostMsg_GetPluginInfo_Output;
class ChromePDFPrintClient;
class SpellCheck;
class CefContentRendererClient : public content::ContentRendererClient,
@ -94,10 +104,17 @@ class CefContentRendererClient : public content::ContentRendererClient,
blink::WebNavigationType type,
blink::WebNavigationPolicy default_policy,
bool is_redirect) override;
content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
content::RenderFrame* render_frame,
const std::string& mime_type,
const GURL& original_url) override;
// MessageLoop::DestructionObserver implementation.
void WillDestroyCurrentMessageLoop() override;
static bool IsExtensionOrSharedModuleWhitelisted(
const GURL& url, const std::set<std::string>& whitelist);
private:
void BrowserCreated(content::RenderView* render_view,
content::RenderFrame* render_frame);
@ -105,6 +122,12 @@ class CefContentRendererClient : public content::ContentRendererClient,
// Perform cleanup work for single-process mode.
void RunSingleProcessCleanupOnUIThread();
static blink::WebPlugin* CreatePlugin(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params,
const CefViewHostMsg_GetPluginInfo_Output& output);
scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
scoped_ptr<CefRenderProcessObserver> observer_;
scoped_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
@ -118,6 +141,15 @@ class CefContentRendererClient : public content::ContentRendererClient,
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
CrossOriginList cross_origin_whitelist_entries_;
scoped_ptr<ChromePDFPrintClient> pdf_print_client_;
scoped_ptr<extensions::ExtensionsClient> extensions_client_;
scoped_ptr<extensions::ExtensionsRendererClient> extensions_renderer_client_;
scoped_ptr<extensions::DispatcherDelegate> extension_dispatcher_delegate_;
scoped_ptr<extensions::Dispatcher> extension_dispatcher_;
scoped_ptr<extensions::ExtensionsGuestViewContainerDispatcher>
guest_view_container_dispatcher_;
int devtools_agent_count_;
int uncaught_exception_stack_size_;

View File

@ -0,0 +1,27 @@
// 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/renderer/extensions/extensions_renderer_client.h"
#include "libcef/renderer/render_process_observer.h"
namespace extensions {
CefExtensionsRendererClient::CefExtensionsRendererClient() {
}
CefExtensionsRendererClient::~CefExtensionsRendererClient() {
}
bool CefExtensionsRendererClient::IsIncognitoProcess() const {
return CefRenderProcessObserver::is_incognito_process();
}
int CefExtensionsRendererClient::GetLowestIsolatedWorldId() const {
// CEF doesn't need to reserve world IDs for anything other than extensions,
// so we always return 1. Note that 0 is reserved for the global world.
return 1;
}
} // namespace extensions

View File

@ -0,0 +1,28 @@
// 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_RENDERER_EXTENSIONS_EXTENSIONS_RENDERER_CLIENT_H_
#define CEF_LIBCEF_RENDERER_EXTENSIONS_EXTENSIONS_RENDERER_CLIENT_H_
#include "base/macros.h"
#include "extensions/renderer/extensions_renderer_client.h"
namespace extensions {
class CefExtensionsRendererClient : public ExtensionsRendererClient {
public:
CefExtensionsRendererClient();
~CefExtensionsRendererClient() override;
// ExtensionsRendererClient implementation.
bool IsIncognitoProcess() const override;
int GetLowestIsolatedWorldId() const override;
private:
DISALLOW_COPY_AND_ASSIGN(CefExtensionsRendererClient);
};
} // namespace extensions
#endif // CEF_LIBCEF_RENDERER_EXTENSIONS_EXTENSIONS_RENDERER_CLIENT_H_

View File

@ -0,0 +1,71 @@
// Copyright 2015 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/renderer/extensions/print_web_view_helper_delegate.h"
#include <vector>
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/constants.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
namespace extensions {
CefPrintWebViewHelperDelegate::~CefPrintWebViewHelperDelegate(){
}
bool CefPrintWebViewHelperDelegate::CancelPrerender(
content::RenderView* render_view, int routing_id) {
return false;
}
// Return the PDF object element if |frame| is the out of process PDF extension.
blink::WebElement CefPrintWebViewHelperDelegate::GetPdfElement(
blink::WebLocalFrame* frame) {
GURL url = frame->document().url();
if (url.SchemeIs(extensions::kExtensionScheme) &&
url.host() == extension_misc::kPdfExtensionId) {
// <object> with id="plugin" is created in
// chrome/browser/resources/pdf/pdf.js.
auto plugin_element = frame->document().getElementById("plugin");
if (!plugin_element.isNull()) {
return plugin_element;
}
NOTREACHED();
}
return blink::WebElement();
}
bool CefPrintWebViewHelperDelegate::IsPrintPreviewEnabled() {
return false;
}
bool CefPrintWebViewHelperDelegate::OverridePrint(
blink::WebLocalFrame* frame) {
if (!frame->document().isPluginDocument())
return false;
std::vector<extensions::MimeHandlerViewContainer*> mime_handlers =
extensions::MimeHandlerViewContainer::FromRenderFrame(
content::RenderFrame::FromWebFrame(frame));
if (!mime_handlers.empty()) {
// This message is handled in chrome/browser/resources/pdf/pdf.js and
// instructs the PDF plugin to print. This is to make window.print() on a
// PDF plugin document correctly print the PDF. See
// https://crbug.com/448720.
base::DictionaryValue message;
message.SetString("type", "print");
mime_handlers.front()->PostMessageFromValue(message);
return true;
}
return false;
}
} // namespace extensions

View File

@ -0,0 +1,26 @@
// Copyright 2015 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_RENDERER_EXTENSIONS_PRINT_WEB_VIEW_HELPER_DELEGATE_H_
#define CEF_LIBCEF_RENDERER_EXTENSIONS_PRINT_WEB_VIEW_HELPER_DELEGATE_H_
#include "components/printing/renderer/print_web_view_helper.h"
namespace extensions {
class CefPrintWebViewHelperDelegate
: public printing::PrintWebViewHelper::Delegate {
public:
~CefPrintWebViewHelperDelegate() override;
bool CancelPrerender(content::RenderView* render_view,
int routing_id) override;
blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override;
bool IsPrintPreviewEnabled() override;
bool OverridePrint(blink::WebLocalFrame* frame) override;
};
} // namespace extensions
#endif // CEF_LIBCEF_RENDERER_EXTENSIONS_PRINT_WEB_VIEW_HELPER_DELEGATE_H_

View File

@ -0,0 +1,214 @@
// 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 "chrome/renderer/pepper/pepper_uma_host.h"
#include "libcef/common/cef_messages.h"
#include "libcef/common/content_client.h"
#include "libcef/renderer/content_renderer_client.h"
#include "base/metrics/histogram.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/renderer/pepper_plugin_instance.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
#if defined(ENABLE_EXTENSIONS)
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#endif // defined(ENABLE_EXTENSIONS)
namespace {
const char* const kPredefinedAllowedUMAOrigins[] = {
"6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see http://crbug.com/317833
"4EB74897CB187C7633357C2FE832E0AD6A44883A", // see http://crbug.com/317833
};
const char* const kWhitelistedHistogramPrefixes[] = {
"22F67DA2061FFC4DC9A4974036348D9C38C22919", // see http://crbug.com/390221
};
const char* const kWhitelistedPluginBaseNames[] = {
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
kWidevineCdmAdapterFileName, // see http://crbug.com/368743
// and http://crbug.com/410630
#endif
CefContentClient::kPDFPluginPath,
};
std::string HashPrefix(const std::string& histogram) {
const std::string id_hash =
base::SHA1HashString(histogram.substr(0, histogram.find('.')));
DCHECK_EQ(id_hash.length(), base::kSHA1Length);
return base::HexEncode(id_hash.c_str(), id_hash.length());
}
} // namespace
PepperUMAHost::PepperUMAHost(content::RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
document_url_(host->GetDocumentURL(instance)),
is_plugin_in_process_(host->IsRunningInProcess()) {
if (host->GetPluginInstance(instance)) {
plugin_base_name_ =
host->GetPluginInstance(instance)->GetModulePath().BaseName();
}
for (size_t i = 0; i < arraysize(kPredefinedAllowedUMAOrigins); ++i)
allowed_origins_.insert(kPredefinedAllowedUMAOrigins[i]);
for (size_t i = 0; i < arraysize(kWhitelistedHistogramPrefixes); ++i)
allowed_histogram_prefixes_.insert(kWhitelistedHistogramPrefixes[i]);
for (size_t i = 0; i < arraysize(kWhitelistedPluginBaseNames); ++i)
allowed_plugin_base_names_.insert(kWhitelistedPluginBaseNames[i]);
}
PepperUMAHost::~PepperUMAHost() {}
int32_t PepperUMAHost::OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) {
PPAPI_BEGIN_MESSAGE_MAP(PepperUMAHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomTimes,
OnHistogramCustomTimes)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomCounts,
OnHistogramCustomCounts)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration,
OnHistogramEnumeration)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
PpapiHostMsg_UMA_IsCrashReportingEnabled, OnIsCrashReportingEnabled)
PPAPI_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
bool PepperUMAHost::IsPluginWhitelisted() {
#if defined(ENABLE_EXTENSIONS)
return CefContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
document_url_, allowed_origins_);
#else
return false;
#endif
}
bool PepperUMAHost::IsHistogramAllowed(const std::string& histogram) {
if (is_plugin_in_process_ && histogram.find("NaCl.") == 0) {
return true;
}
if (IsPluginWhitelisted() &&
ContainsKey(allowed_histogram_prefixes_, HashPrefix(histogram))) {
return true;
}
if (ContainsKey(allowed_plugin_base_names_,
plugin_base_name_.MaybeAsASCII())) {
return true;
}
LOG(ERROR) << "Host or histogram name is not allowed to use the UMA API.";
return false;
}
#define RETURN_IF_BAD_ARGS(_min, _max, _buckets) \
do { \
if (_min >= _max || _buckets <= 1) \
return PP_ERROR_BADARGUMENT; \
} while (0)
int32_t PepperUMAHost::OnHistogramCustomTimes(
ppapi::host::HostMessageContext* context,
const std::string& name,
int64_t sample,
int64_t min,
int64_t max,
uint32_t bucket_count) {
if (!IsHistogramAllowed(name)) {
return PP_ERROR_NOACCESS;
}
RETURN_IF_BAD_ARGS(min, max, bucket_count);
base::HistogramBase* counter = base::Histogram::FactoryTimeGet(
name,
base::TimeDelta::FromMilliseconds(min),
base::TimeDelta::FromMilliseconds(max),
bucket_count,
base::HistogramBase::kUmaTargetedHistogramFlag);
// The histogram can be NULL if it is constructed with bad arguments. Ignore
// that data for this API. An error message will be logged.
if (counter)
counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
return PP_OK;
}
int32_t PepperUMAHost::OnHistogramCustomCounts(
ppapi::host::HostMessageContext* context,
const std::string& name,
int32_t sample,
int32_t min,
int32_t max,
uint32_t bucket_count) {
if (!IsHistogramAllowed(name)) {
return PP_ERROR_NOACCESS;
}
RETURN_IF_BAD_ARGS(min, max, bucket_count);
base::HistogramBase* counter = base::Histogram::FactoryGet(
name,
min,
max,
bucket_count,
base::HistogramBase::kUmaTargetedHistogramFlag);
// The histogram can be NULL if it is constructed with bad arguments. Ignore
// that data for this API. An error message will be logged.
if (counter)
counter->Add(sample);
return PP_OK;
}
int32_t PepperUMAHost::OnHistogramEnumeration(
ppapi::host::HostMessageContext* context,
const std::string& name,
int32_t sample,
int32_t boundary_value) {
if (!IsHistogramAllowed(name)) {
return PP_ERROR_NOACCESS;
}
RETURN_IF_BAD_ARGS(0, boundary_value, boundary_value + 1);
base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
name,
1,
boundary_value,
boundary_value + 1,
base::HistogramBase::kUmaTargetedHistogramFlag);
// The histogram can be NULL if it is constructed with bad arguments. Ignore
// that data for this API. An error message will be logged.
if (counter)
counter->Add(sample);
return PP_OK;
}
int32_t PepperUMAHost::OnIsCrashReportingEnabled(
ppapi::host::HostMessageContext* context) {
if (!IsPluginWhitelisted())
return PP_ERROR_NOACCESS;
// TODO(extensions): Chrome uses ChromeViewHostMsg_IsCrashReportingEnabled to
// retrieve this value. Explore whether it's useful for CEF clients when crash
// reporting is enabled.
bool enabled = false;
if (enabled)
return PP_OK;
return PP_ERROR_FAILED;
}

View File

@ -10,6 +10,8 @@
#include "chrome/renderer/pepper/pepper_flash_fullscreen_host.h"
#include "chrome/renderer/pepper/pepper_flash_menu_host.h"
#include "chrome/renderer/pepper/pepper_flash_renderer_host.h"
#include "chrome/renderer/pepper/pepper_uma_host.h"
#include "components/pdf/renderer/pepper_pdf_host.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/host/resource_host.h"
@ -83,5 +85,27 @@ scoped_ptr<ResourceHost> CefRendererPepperHostFactory::CreateResourceHost(
}
}
if (host_->GetPpapiHost()->permissions().HasPermission(
ppapi::PERMISSION_PRIVATE)) {
switch (message.type()) {
case PpapiHostMsg_PDF_Create::ID: {
return scoped_ptr<ResourceHost>(
new pdf::PepperPDFHost(host_, instance, resource));
}
}
}
// Permissions for the following interfaces will be checked at the
// time of the corresponding instance's method calls. Currently these
// interfaces are available only for whitelisted apps which may not have
// access to the other private interfaces.
switch (message.type()) {
case PpapiHostMsg_UMA_Create::ID: {
return scoped_ptr<ResourceHost>(
new PepperUMAHost(host_, instance, resource));
}
}
NOTREACHED() << "Unhandled message type: " << message.type();
return scoped_ptr<ResourceHost>();
}

View File

@ -38,10 +38,16 @@ void CefRenderFrameObserver::DidCreateScriptContext(
CefRefPtr<CefBrowserImpl> browserPtr =
CefBrowserImpl::GetBrowserForMainFrame(frame->top());
DCHECK(browserPtr.get());
if (!browserPtr.get())
return;
CefRefPtr<CefRenderProcessHandler> handler;
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get())
handler = application->GetRenderProcessHandler();
if (!handler.get())
return;
CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
v8::Isolate* isolate = blink::mainThreadIsolate();
@ -51,14 +57,7 @@ void CefRenderFrameObserver::DidCreateScriptContext(
CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get())
handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
}
handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
}
void CefRenderFrameObserver::WillReleaseScriptContext(
@ -66,16 +65,14 @@ void CefRenderFrameObserver::WillReleaseScriptContext(
int world_id) {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get()) {
CefRefPtr<CefBrowserImpl> browserPtr =
CefBrowserImpl::GetBrowserForMainFrame(frame->top());
DCHECK(browserPtr.get());
if (browserPtr.get()) {
CefRefPtr<CefBrowserImpl> browserPtr =
CefBrowserImpl::GetBrowserForMainFrame(frame->top());
if (browserPtr.get()) {
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get()) {
CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
v8::Isolate* isolate = blink::mainThreadIsolate();

View File

@ -13,6 +13,8 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
bool CefRenderProcessObserver::is_incognito_process_ = false;
CefRenderProcessObserver::CefRenderProcessObserver() {
net::NetModule::SetResourceProvider(NetResourceProvider);
}
@ -24,6 +26,8 @@ bool CefRenderProcessObserver::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CefRenderProcessObserver, message)
IPC_MESSAGE_HANDLER(CefProcessMsg_SetIsIncognitoProcess,
OnSetIsIncognitoProcess)
IPC_MESSAGE_HANDLER(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
OnModifyCrossOriginWhitelistEntry)
IPC_MESSAGE_HANDLER(CefProcessMsg_ClearCrossOriginWhitelist,
@ -41,6 +45,11 @@ void CefRenderProcessObserver::OnRenderProcessShutdown() {
CefContentRendererClient::Get()->OnRenderProcessShutdown();
}
void CefRenderProcessObserver::OnSetIsIncognitoProcess(
bool is_incognito_process) {
is_incognito_process_ = is_incognito_process;
}
void CefRenderProcessObserver::OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params) {

View File

@ -17,6 +17,8 @@ class CefRenderProcessObserver : public content::RenderProcessObserver {
CefRenderProcessObserver();
~CefRenderProcessObserver() override;
static bool is_incognito_process() { return is_incognito_process_; }
// RenderProcessObserver implementation.
bool OnControlMessageReceived(const IPC::Message& message) override;
void WebKitInitialized() override;
@ -24,11 +26,14 @@ class CefRenderProcessObserver : public content::RenderProcessObserver {
private:
// Message handlers called on the render thread.
void OnSetIsIncognitoProcess(bool is_incognito_process);
void OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params);
void OnClearCrossOriginWhitelist();
static bool is_incognito_process_;
DISALLOW_COPY_AND_ASSIGN(CefRenderProcessObserver);
};

View File

@ -14,6 +14,12 @@
<include name="IDR_CEF_CREDITS_JS" file="..\..\..\chrome\browser\resources\about_credits.js" type="BINDATA" />
<include name="IDR_CEF_LICENSE_TXT" file="..\..\LICENSE.txt" type="BINDATA" />
<include name="IDR_CEF_VERSION_HTML" file="about_version.html" type="BINDATA" />
<!-- Features specific to CEF. -->
<include name="IDR_CEF_EXTENSION_API_FEATURES" file="..\common\extensions\api\_api_features.json" type="BINDATA" />
<!-- Manifest files for built-in extensions. -->
<include name="IDR_PDF_MANIFEST" file="..\..\..\chrome\browser\resources\pdf\manifest.json" type="BINDATA" />
</includes>
</release>
</grit>

View File

@ -90,6 +90,26 @@ patches = [
'name': 'ui_webview_1257',
'path': '../ui/views/controls/webview/',
},
{
# Allow specification of a custom WebContentsView.
# http://code.google.com/p/chromiumembedded/issues/detail?id=1257
'name': 'extensions_1257',
'path': '../extensions/',
},
{
# Allow specification of a custom WebContentsViewGuest implementation for
# MimeHandlerView.
# https://bitbucket.org/chromiumembedded/cef/issues/1565
'name': 'mime_handler_view_1565',
'path': '../extensions/browser/guest_view/mime_handler_view/',
},
{
# Allow specification of a custom WebContentsViewGuest implementation for
# BrowserPluginGuest.
# https://bitbucket.org/chromiumembedded/cef/issues/1565
'name': 'browser_plugin_guest_1565',
'path': '../content/',
},
{
# Allow customization of the WebView background color.
# http://code.google.com/p/chromiumembedded/issues/detail?id=1161

View File

@ -0,0 +1,119 @@
diff --git browser/browser_plugin/browser_plugin_guest.cc browser/browser_plugin/browser_plugin_guest.cc
index f438805..d199c6b 100644
--- browser/browser_plugin/browser_plugin_guest.cc
+++ browser/browser_plugin/browser_plugin_guest.cc
@@ -19,7 +19,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_view_guest.h"
+#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_constants_internal.h"
@@ -262,15 +262,16 @@ void BrowserPluginGuest::InitInternal(
guest_window_rect_ = params.view_rect;
if (owner_web_contents_ != owner_web_contents) {
- WebContentsViewGuest* new_view =
- static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
- if (owner_web_contents_)
- new_view->OnGuestDetached(owner_web_contents_->GetView());
+ if (owner_web_contents_) {
+ delegate_->OnGuestDetached(GetWebContents()->GetView(),
+ owner_web_contents_->GetView());
+ }
// Once a BrowserPluginGuest has an embedder WebContents, it's considered to
// be attached.
owner_web_contents_ = owner_web_contents;
- new_view->OnGuestAttached(owner_web_contents_->GetView());
+ delegate_->OnGuestAttached(GetWebContents()->GetView(),
+ owner_web_contents_->GetView());
}
RendererPreferences* renderer_prefs =
@@ -656,12 +657,9 @@ void BrowserPluginGuest::OnWillAttachComplete(
// This will trigger a callback to RenderViewReady after a round-trip IPC.
static_cast<RenderViewHostImpl*>(
GetWebContents()->GetRenderViewHost())->Init();
- WebContentsViewGuest* web_contents_view =
- static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
- if (!web_contents()->GetRenderViewHost()->GetView()) {
- web_contents_view->CreateViewForWidget(
- web_contents()->GetRenderViewHost(), true);
- }
+ if (!web_contents()->GetRenderViewHost()->GetView())
+ delegate_->CreateViewForWidget(GetWebContents()->GetView(),
+ web_contents()->GetRenderViewHost());
}
InitInternal(params, embedder_web_contents);
diff --git public/browser/browser_plugin_guest_delegate.cc public/browser/browser_plugin_guest_delegate.cc
index fd7dec4..49d4f99 100644
--- public/browser/browser_plugin_guest_delegate.cc
+++ public/browser/browser_plugin_guest_delegate.cc
@@ -4,6 +4,8 @@
#include "content/public/browser/browser_plugin_guest_delegate.h"
+#include "content/browser/web_contents/web_contents_view_guest.h"
+
namespace content {
bool BrowserPluginGuestDelegate::CanRunInDetachedState() const {
@@ -30,4 +32,23 @@ bool BrowserPluginGuestDelegate::StopFinding(StopFindAction action) {
return false;
}
+void BrowserPluginGuestDelegate::OnGuestAttached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ static_cast<WebContentsViewGuest*>(guest_view)->OnGuestAttached(parent_view);
+}
+
+void BrowserPluginGuestDelegate::OnGuestDetached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ static_cast<WebContentsViewGuest*>(guest_view)->OnGuestAttached(parent_view);
+}
+
+void BrowserPluginGuestDelegate::CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host) {
+ static_cast<WebContentsViewGuest*>(guest_view)->CreateViewForWidget(
+ render_widget_host, true);
+}
+
} // namespace content
diff --git public/browser/browser_plugin_guest_delegate.h public/browser/browser_plugin_guest_delegate.h
index 000e3b6..ced8765 100644
--- public/browser/browser_plugin_guest_delegate.h
+++ public/browser/browser_plugin_guest_delegate.h
@@ -21,6 +21,8 @@ class Size;
namespace content {
class GuestHost;
+class RenderWidgetHost;
+class WebContentsView;
// Objects implement this interface to get notified about changes in the guest
// WebContents and to provide necessary functionality.
@@ -86,6 +88,17 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
// Provides the delegate with an interface with which to communicate with the
// content module.
virtual void SetGuestHost(GuestHost* guest_host) {}
+
+ // Called when a guest is attached or detached.
+ virtual void OnGuestAttached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view);
+ virtual void OnGuestDetached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view);
+
+ // Called to create the view for the widget.
+ virtual void CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host);
};
} // namespace content

View File

@ -0,0 +1,30 @@
diff --git browser/guest_view/extension_options/extension_options_guest.cc browser/guest_view/extension_options/extension_options_guest.cc
index c882315..ff6d25f 100644
--- browser/guest_view/extension_options/extension_options_guest.cc
+++ browser/guest_view/extension_options/extension_options_guest.cc
@@ -208,7 +208,9 @@ bool ExtensionOptionsGuest::ShouldCreateWebContents(
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) {
+ content::SessionStorageNamespace* session_storage_namespace,
+ content::WebContentsView** view,
+ content::RenderViewHostDelegateView** delegate_view) {
// This method handles opening links from within the guest. Since this guest
// view is used for displaying embedded extension options, we want any
// external links to be opened in a new tab, not in a new guest view.
diff --git browser/guest_view/extension_options/extension_options_guest.h browser/guest_view/extension_options/extension_options_guest.h
index b62d81a..8176f84 100644
--- browser/guest_view/extension_options/extension_options_guest.h
+++ browser/guest_view/extension_options/extension_options_guest.h
@@ -54,7 +54,9 @@ class ExtensionOptionsGuest
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) override;
+ content::SessionStorageNamespace* session_storage_namespace,
+ content::WebContentsView** view,
+ content::RenderViewHostDelegateView** delegate_view) override;
// content::WebContentsObserver implementation.
void DidNavigateMainFrame(

View File

@ -0,0 +1,130 @@
diff --git mime_handler_view_guest.cc mime_handler_view_guest.cc
index 61fd142..ed9a58d 100644
--- mime_handler_view_guest.cc
+++ mime_handler_view_guest.cc
@@ -142,6 +142,8 @@ void MimeHandlerViewGuest::CreateWebContents(
WebContents::CreateParams params(browser_context(),
guest_site_instance.get());
params.guest_delegate = this;
+ if (delegate_)
+ delegate_->OverrideWebContentsCreateParams(&params);
callback.Run(WebContents::Create(params));
}
@@ -183,6 +185,30 @@ bool MimeHandlerViewGuest::StopFinding(content::StopFindAction action) {
return false;
}
+void MimeHandlerViewGuest::OnGuestAttached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ if (!delegate_ || !delegate_->OnGuestAttached(guest_view, parent_view))
+ BrowserPluginGuestDelegate::OnGuestAttached(guest_view, parent_view);
+}
+
+void MimeHandlerViewGuest::OnGuestDetached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ if (!delegate_ || !delegate_->OnGuestDetached(guest_view, parent_view))
+ BrowserPluginGuestDelegate::OnGuestDetached(guest_view, parent_view);
+}
+
+void MimeHandlerViewGuest::CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host) {
+ if (!delegate_ ||
+ !delegate_->CreateViewForWidget(guest_view, render_widget_host)) {
+ BrowserPluginGuestDelegate::CreateViewForWidget(guest_view,
+ render_widget_host);
+ }
+}
+
content::WebContents* MimeHandlerViewGuest::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
diff --git mime_handler_view_guest.h mime_handler_view_guest.h
index f95aab7..fe4944e 100644
--- mime_handler_view_guest.h
+++ mime_handler_view_guest.h
@@ -76,6 +76,13 @@ class MimeHandlerViewGuest : public guest_view::GuestView<MimeHandlerViewGuest>,
const base::string16& search_text,
const blink::WebFindOptions& options) override;
bool StopFinding(content::StopFindAction action) override;
+ void OnGuestAttached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) override;
+ void OnGuestDetached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) override;
+ void CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host) override;
// WebContentsDelegate implementation.
content::WebContents* OpenURLFromTab(
diff --git mime_handler_view_guest_delegate.cc mime_handler_view_guest_delegate.cc
index 63b81b8..0f63f48 100644
--- mime_handler_view_guest_delegate.cc
+++ mime_handler_view_guest_delegate.cc
@@ -6,6 +6,24 @@
namespace extensions {
+bool MimeHandlerViewGuestDelegate::OnGuestAttached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ return false;
+}
+
+bool MimeHandlerViewGuestDelegate::OnGuestDetached(
+ content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view) {
+ return false;
+}
+
+bool MimeHandlerViewGuestDelegate::CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host) {
+ return false;
+}
+
bool MimeHandlerViewGuestDelegate::HandleContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params) {
diff --git mime_handler_view_guest_delegate.h mime_handler_view_guest_delegate.h
index b9a6fe3..6a2c3b0 100644
--- mime_handler_view_guest_delegate.h
+++ mime_handler_view_guest_delegate.h
@@ -6,10 +6,11 @@
#define EXTENSIONS_BROWSER_GUEST_VIEW_MIME_HANDLER_VIEW_MIME_HANDLER_VIEW_GUEST_DELEGATE_H_
#include "base/macros.h"
+#include "content/public/browser/web_contents.h"
namespace content {
-class WebContents;
struct ContextMenuParams;
+class RenderWidgetHost;
} // namespace content
namespace extensions {
@@ -22,6 +23,21 @@ class MimeHandlerViewGuestDelegate {
explicit MimeHandlerViewGuestDelegate(MimeHandlerViewGuest* guest) {}
virtual ~MimeHandlerViewGuestDelegate() {}
+ // Provides an opportunity to supply a custom view implementation.
+ virtual void OverrideWebContentsCreateParams(
+ content::WebContents::CreateParams* params) {}
+
+ // Called when a guest is attached or detached.
+ virtual bool OnGuestAttached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view);
+ virtual bool OnGuestDetached(content::WebContentsView* guest_view,
+ content::WebContentsView* parent_view);
+
+ // Called to create the view for the widget.
+ virtual bool CreateViewForWidget(
+ content::WebContentsView* guest_view,
+ content::RenderWidgetHost* render_widget_host);
+
// Attaches helpers upon initializing the WebContents.
virtual void AttachHelpers() {}

View File

@ -44,19 +44,20 @@
#define ID_TESTS_PRINT_TO_PDF 32716
#define ID_TESTS_LAST 32716
#define IDC_STATIC -1
#define IDS_BINDING 1000
#define IDS_DIALOGS 1001
#define IDS_LOCALSTORAGE 1002
#define IDS_LOGO 1003
#define IDS_LOGOBALL 1004
#define IDS_OSRTEST 1005
#define IDS_OTHER_TESTS 1006
#define IDS_PERFORMANCE 1007
#define IDS_PERFORMANCE2 1008
#define IDS_TRANSPARENCY 1009
#define IDS_URLREQUEST 1010
#define IDS_WINDOW 1011
#define IDS_XMLHTTPREQUEST 1012
#define IDS_BINDING_HTML 1000
#define IDS_DIALOGS_HTML 1001
#define IDS_LOCALSTORAGE_HTML 1002
#define IDS_LOGO_PNG 1003
#define IDS_OSRTEST_HTML 1004
#define IDS_OTHER_TESTS_HTML 1005
#define IDS_PDF_HTML 1006
#define IDS_PDF_PDF 1007
#define IDS_PERFORMANCE_HTML 1008
#define IDS_PERFORMANCE2_HTML 1009
#define IDS_TRANSPARENCY_HTML 1010
#define IDS_URLREQUEST_HTML 1011
#define IDS_WINDOW_HTML 1012
#define IDS_XMLHTTPREQUEST_HTML 1013
// Next default values for new objects
//

View File

@ -37,18 +37,20 @@ int GetResourceId(const char* resource_name) {
char* name;
int id;
} resource_map[] = {
{"binding.html", IDS_BINDING},
{"dialogs.html", IDS_DIALOGS},
{"localstorage.html", IDS_LOCALSTORAGE},
{"logo.png", IDS_LOGO},
{"osr_test.html", IDS_OSRTEST},
{"other_tests.html", IDS_OTHER_TESTS},
{"performance.html", IDS_PERFORMANCE},
{"performance2.html", IDS_PERFORMANCE2},
{"transparency.html", IDS_TRANSPARENCY},
{"urlrequest.html", IDS_URLREQUEST},
{"window.html", IDS_WINDOW},
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST},
{"binding.html", IDS_BINDING_HTML},
{"dialogs.html", IDS_DIALOGS_HTML},
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
{"logo.png", IDS_LOGO_PNG},
{"osr_test.html", IDS_OSRTEST_HTML},
{"other_tests.html", IDS_OTHER_TESTS_HTML},
{"pdf.html", IDS_PDF_HTML},
{"pdf.pdf", IDS_PDF_PDF},
{"performance.html", IDS_PERFORMANCE_HTML},
{"performance2.html", IDS_PERFORMANCE2_HTML},
{"transparency.html", IDS_TRANSPARENCY_HTML},
{"urlrequest.html", IDS_URLREQUEST_HTML},
{"window.html", IDS_WINDOW_HTML},
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML},
};
for (int i = 0; i < sizeof(resource_map)/sizeof(_resource_map); ++i) {

View File

@ -19,6 +19,8 @@
<li><a href="http://tests/performance2">JavaScript Performance (2) Tests</a></li>
<li><a href="http://tests/window">JavaScript Window Manipulation</a></li>
<li><a href="http://tests/localstorage">Local Storage</a></li>
<li><a href="http://tests/pdf.pdf">PDF Viewer direct</a></li>
<li><a href="http://tests/pdf">PDF Viewer iframe</a></li>
<li><a href="http://mrdoob.com/lab/javascript/requestanimationframe/">requestAnimationFrame</a></li>
<li><a href="client://tests/handler.html">Scheme Handler</a></li>
<li><a href="https://www.google.com/intl/en/chrome/demos/speech.html">Speech Input</a> - requires "enable-speech-input" flag</li>

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>PDF Test</title>
</head>
<body bgcolor="white">
<iframe src="pdf.pdf" width="500" height="500"></iframe>
<iframe src="pdf.pdf" width="500" height="500"></iframe>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More