mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add is_main_frame argument to CefRequestContextHandler::OnBeforePluginLoad (issue #2015)
This commit is contained in:
@@ -138,7 +138,8 @@ CefPluginInfoMessageFilter::Context::Context(
|
||||
int render_process_id,
|
||||
CefBrowserContext* profile)
|
||||
: render_process_id_(render_process_id),
|
||||
resource_context_(profile->GetResourceContext()),
|
||||
resource_context_(
|
||||
static_cast<CefResourceContext*>(profile->GetResourceContext())),
|
||||
host_content_settings_map_(profile->GetHostContentSettingsMap()) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
if (extensions::ExtensionsEnabled())
|
||||
@@ -198,6 +199,7 @@ CefPluginInfoMessageFilter::~CefPluginInfoMessageFilter() {}
|
||||
struct CefPluginInfoMessageFilter::GetPluginInfo_Params {
|
||||
int render_frame_id;
|
||||
GURL url;
|
||||
bool is_main_frame;
|
||||
url::Origin main_frame_origin;
|
||||
std::string mime_type;
|
||||
};
|
||||
@@ -205,12 +207,14 @@ struct CefPluginInfoMessageFilter::GetPluginInfo_Params {
|
||||
void CefPluginInfoMessageFilter::OnGetPluginInfo(
|
||||
int render_frame_id,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
const std::string& mime_type,
|
||||
IPC::Message* reply_msg) {
|
||||
GetPluginInfo_Params params = {
|
||||
render_frame_id,
|
||||
url,
|
||||
is_main_frame,
|
||||
main_frame_origin,
|
||||
mime_type
|
||||
};
|
||||
@@ -225,12 +229,10 @@ void CefPluginInfoMessageFilter::PluginsLoaded(
|
||||
IPC::Message* reply_msg,
|
||||
const std::vector<WebPluginInfo>& plugins) {
|
||||
CefViewHostMsg_GetPluginInfo_Output output;
|
||||
CefRefPtr<CefRequestContextHandler> handler =
|
||||
browser_context_->GetHandler();
|
||||
|
||||
// This also fills in |actual_mime_type|.
|
||||
std::unique_ptr<PluginMetadata> plugin_metadata;
|
||||
context_.FindEnabledPlugin(params, handler.get(),
|
||||
context_.FindEnabledPlugin(params,
|
||||
&output.status, &output.plugin,
|
||||
&output.actual_mime_type,
|
||||
&plugin_metadata);
|
||||
@@ -383,7 +385,6 @@ void CefPluginInfoMessageFilter::Context::DecidePluginStatus(
|
||||
|
||||
bool CefPluginInfoMessageFilter::Context::FindEnabledPlugin(
|
||||
const GetPluginInfo_Params& params,
|
||||
CefRequestContextHandler* handler,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status,
|
||||
WebPluginInfo* plugin,
|
||||
std::string* actual_mime_type,
|
||||
@@ -414,8 +415,10 @@ bool CefPluginInfoMessageFilter::Context::FindEnabledPlugin(
|
||||
*plugin_metadata = PluginFinder::GetInstance()->GetPluginMetadata(*plugin);
|
||||
|
||||
DecidePluginStatus(params, *plugin, (*plugin_metadata).get(), status);
|
||||
if (filter->IsPluginAvailable(handler,
|
||||
if (filter->IsPluginAvailable(render_process_id_,
|
||||
resource_context_,
|
||||
params.url,
|
||||
params.is_main_frame,
|
||||
params.main_frame_origin,
|
||||
plugin,
|
||||
status)) {
|
||||
|
@@ -22,13 +22,12 @@
|
||||
#include "ppapi/features/features.h"
|
||||
|
||||
class CefBrowserContext;
|
||||
class CefRequestContextHandler;
|
||||
class CefResourceContext;
|
||||
struct CefViewHostMsg_GetPluginInfo_Output;
|
||||
enum class CefViewHostMsg_GetPluginInfo_Status;
|
||||
class GURL;
|
||||
|
||||
namespace content {
|
||||
class ResourceContext;
|
||||
struct WebPluginInfo;
|
||||
}
|
||||
|
||||
@@ -59,7 +58,6 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
||||
CefViewHostMsg_GetPluginInfo_Status* status) const;
|
||||
bool FindEnabledPlugin(
|
||||
const GetPluginInfo_Params& params,
|
||||
CefRequestContextHandler* handler,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status,
|
||||
content::WebPluginInfo* plugin,
|
||||
std::string* actual_mime_type,
|
||||
@@ -75,7 +73,7 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
||||
|
||||
private:
|
||||
int render_process_id_;
|
||||
content::ResourceContext* resource_context_;
|
||||
CefResourceContext* resource_context_;
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
extensions::ExtensionRegistry* extension_registry_;
|
||||
#endif
|
||||
@@ -101,6 +99,7 @@ class CefPluginInfoMessageFilter : public content::BrowserMessageFilter {
|
||||
|
||||
void OnGetPluginInfo(int render_frame_id,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
const std::string& mime_type,
|
||||
IPC::Message* reply_msg);
|
||||
|
@@ -22,27 +22,37 @@ bool CefPluginServiceFilter::IsPluginAvailable(
|
||||
int render_frame_id,
|
||||
const void* context,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
content::WebPluginInfo* plugin) {
|
||||
CefResourceContext* resource_context = const_cast<CefResourceContext*>(
|
||||
reinterpret_cast<const CefResourceContext*>(context));
|
||||
|
||||
bool allow_load = true;
|
||||
if (resource_context->HasPluginLoadDecision(render_process_id, plugin->path,
|
||||
&allow_load)) {
|
||||
return allow_load;
|
||||
}
|
||||
|
||||
CefRefPtr<CefRequestContextHandler> handler = resource_context->GetHandler();
|
||||
CefViewHostMsg_GetPluginInfo_Status status =
|
||||
CefViewHostMsg_GetPluginInfo_Status::kAllowed;
|
||||
allow_load = IsPluginAvailable(handler.get(), url, main_frame_origin, plugin,
|
||||
&status);
|
||||
|
||||
resource_context->AddPluginLoadDecision(render_process_id, plugin->path,
|
||||
allow_load);
|
||||
// Perform origin check here because we're passing an empty origin value to
|
||||
// IsPluginAvailable() below.
|
||||
const GURL& policy_url = main_frame_origin.GetURL();
|
||||
if (!policy_url.is_empty() &&
|
||||
policy_url.scheme() == extensions::kExtensionScheme) {
|
||||
// Always allow extension origins to load plugins.
|
||||
// TODO(extensions): Revisit this decision once CEF supports more than just
|
||||
// the PDF extension.
|
||||
return true;
|
||||
}
|
||||
|
||||
return allow_load;
|
||||
// Blink requires this method to return a consistent value during renderer
|
||||
// process initialization and page load, so we always call IsPluginAvailable()
|
||||
// with an empty origin. If we return false then the plugin will not be listed
|
||||
// in navigator.plugins and navigating to the plugin mime type will trigger
|
||||
// the download code path. If we return true then individual plugin instance
|
||||
// loads will be evaluated in CefContentRendererClient::OverrideCreatePlugin,
|
||||
// which will result in a call to CefPluginInfoMessageFilter::PluginsLoaded to
|
||||
// retrieve the actual load decision with a non-empty origin. That will
|
||||
// determine whether the plugin load is allowed or the plugin placeholder is
|
||||
// displayed.
|
||||
return IsPluginAvailable(render_process_id, resource_context, url,
|
||||
is_main_frame, url::Origin(), plugin, &status);
|
||||
}
|
||||
|
||||
bool CefPluginServiceFilter::CanLoadPlugin(int render_process_id,
|
||||
@@ -51,8 +61,10 @@ bool CefPluginServiceFilter::CanLoadPlugin(int render_process_id,
|
||||
}
|
||||
|
||||
bool CefPluginServiceFilter::IsPluginAvailable(
|
||||
CefRequestContextHandler* handler,
|
||||
int render_process_id,
|
||||
CefResourceContext* resource_context,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
content::WebPluginInfo* plugin,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status) {
|
||||
@@ -78,54 +90,70 @@ bool CefPluginServiceFilter::IsPluginAvailable(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
CefRefPtr<CefWebPluginInfoImpl> pluginInfo(
|
||||
new CefWebPluginInfoImpl(*plugin));
|
||||
CefRefPtr<CefRequestContextHandler> handler = resource_context->GetHandler();
|
||||
if (!handler) {
|
||||
// No handler so go with the default plugin load decision.
|
||||
return *status != CefViewHostMsg_GetPluginInfo_Status::kDisabled;
|
||||
}
|
||||
|
||||
cef_plugin_policy_t plugin_policy = PLUGIN_POLICY_ALLOW;
|
||||
switch (*status) {
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kAllowed:
|
||||
plugin_policy = PLUGIN_POLICY_ALLOW;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kBlocked:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kUnauthorized:
|
||||
plugin_policy = PLUGIN_POLICY_BLOCK;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kDisabled:
|
||||
plugin_policy = PLUGIN_POLICY_DISABLE;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kPlayImportantContent:
|
||||
plugin_policy = PLUGIN_POLICY_DETECT_IMPORTANT;
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
// Check for a cached plugin load decision.
|
||||
if (resource_context->HasPluginLoadDecision(
|
||||
render_process_id, plugin->path,
|
||||
is_main_frame, main_frame_origin, status)) {
|
||||
return *status != CefViewHostMsg_GetPluginInfo_Status::kDisabled;
|
||||
}
|
||||
|
||||
if (handler->OnBeforePluginLoad(plugin->mime_types[0].mime_type,
|
||||
url.possibly_invalid_spec(),
|
||||
policy_url.possibly_invalid_spec(),
|
||||
pluginInfo.get(),
|
||||
&plugin_policy)) {
|
||||
switch (plugin_policy) {
|
||||
case PLUGIN_POLICY_ALLOW:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kAllowed;
|
||||
break;
|
||||
case PLUGIN_POLICY_DETECT_IMPORTANT:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
|
||||
break;
|
||||
case PLUGIN_POLICY_BLOCK:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kBlocked;
|
||||
break;
|
||||
case PLUGIN_POLICY_DISABLE:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kDisabled;
|
||||
break;
|
||||
}
|
||||
CefRefPtr<CefWebPluginInfoImpl> pluginInfo(new CefWebPluginInfoImpl(*plugin));
|
||||
|
||||
cef_plugin_policy_t plugin_policy = PLUGIN_POLICY_ALLOW;
|
||||
switch (*status) {
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kAllowed:
|
||||
plugin_policy = PLUGIN_POLICY_ALLOW;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kBlocked:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed:
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kUnauthorized:
|
||||
plugin_policy = PLUGIN_POLICY_BLOCK;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kDisabled:
|
||||
plugin_policy = PLUGIN_POLICY_DISABLE;
|
||||
break;
|
||||
case CefViewHostMsg_GetPluginInfo_Status::kPlayImportantContent:
|
||||
plugin_policy = PLUGIN_POLICY_DETECT_IMPORTANT;
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler->OnBeforePluginLoad(plugin->mime_types[0].mime_type,
|
||||
url.possibly_invalid_spec(),
|
||||
is_main_frame,
|
||||
policy_url.possibly_invalid_spec(),
|
||||
pluginInfo.get(),
|
||||
&plugin_policy)) {
|
||||
switch (plugin_policy) {
|
||||
case PLUGIN_POLICY_ALLOW:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kAllowed;
|
||||
break;
|
||||
case PLUGIN_POLICY_DETECT_IMPORTANT:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
|
||||
break;
|
||||
case PLUGIN_POLICY_BLOCK:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kBlocked;
|
||||
break;
|
||||
case PLUGIN_POLICY_DISABLE:
|
||||
*status = CefViewHostMsg_GetPluginInfo_Status::kDisabled;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (*status != CefViewHostMsg_GetPluginInfo_Status::kDisabled);
|
||||
// Cache the plugin load decision.
|
||||
resource_context->AddPluginLoadDecision(
|
||||
render_process_id, plugin->path,
|
||||
is_main_frame, main_frame_origin, *status);
|
||||
|
||||
return *status != CefViewHostMsg_GetPluginInfo_Status::kDisabled;
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
|
||||
class CefRequestContextHandler;
|
||||
class CefResourceContext;
|
||||
enum class CefViewHostMsg_GetPluginInfo_Status;
|
||||
|
||||
class CefPluginServiceFilter : public content::PluginServiceFilter {
|
||||
@@ -25,6 +25,7 @@ class CefPluginServiceFilter : public content::PluginServiceFilter {
|
||||
int render_frame_id,
|
||||
const void* context,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
content::WebPluginInfo* plugin) override;
|
||||
|
||||
@@ -34,8 +35,10 @@ class CefPluginServiceFilter : public content::PluginServiceFilter {
|
||||
// Returns false if the plugin is not found or disabled. May call
|
||||
// CefRequestContextHandler::OnBeforePluginLoad if possible/necessary.
|
||||
// See related discussion in issue #2015.
|
||||
bool IsPluginAvailable(CefRequestContextHandler* handler,
|
||||
bool IsPluginAvailable(int render_process_id,
|
||||
CefResourceContext* resource_context,
|
||||
const GURL& url,
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
content::WebPluginInfo* plugin,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status);
|
||||
|
@@ -124,31 +124,38 @@ void CefResourceContext::set_parent(CefResourceContext* parent) {
|
||||
void CefResourceContext::AddPluginLoadDecision(
|
||||
int render_process_id,
|
||||
const base::FilePath& plugin_path,
|
||||
bool allow_load) {
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
CefViewHostMsg_GetPluginInfo_Status status) {
|
||||
CEF_REQUIRE_IOT();
|
||||
DCHECK_GE(render_process_id, 0);
|
||||
DCHECK(!plugin_path.empty());
|
||||
|
||||
plugin_load_decision_map_.insert(
|
||||
std::make_pair(std::make_pair(render_process_id, plugin_path),
|
||||
allow_load));
|
||||
std::make_pair(
|
||||
std::make_pair(std::make_pair(render_process_id, plugin_path),
|
||||
std::make_pair(is_main_frame, main_frame_origin)),
|
||||
status));
|
||||
}
|
||||
|
||||
bool CefResourceContext::HasPluginLoadDecision(
|
||||
int render_process_id,
|
||||
const base::FilePath& plugin_path,
|
||||
bool* allow_load) const {
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status) const {
|
||||
CEF_REQUIRE_IOT();
|
||||
DCHECK_GE(render_process_id, 0);
|
||||
DCHECK(!plugin_path.empty());
|
||||
|
||||
PluginLoadDecisionMap::const_iterator it =
|
||||
plugin_load_decision_map_.find(
|
||||
std::make_pair(render_process_id, plugin_path));
|
||||
std::make_pair(std::make_pair(render_process_id, plugin_path),
|
||||
std::make_pair(is_main_frame, main_frame_origin)));
|
||||
if (it == plugin_load_decision_map_.end())
|
||||
return false;
|
||||
|
||||
*allow_load = it->second;
|
||||
*status = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,7 +167,7 @@ void CefResourceContext::ClearPluginLoadDecision(int render_process_id) {
|
||||
} else {
|
||||
PluginLoadDecisionMap::iterator it = plugin_load_decision_map_.begin();
|
||||
while (it != plugin_load_decision_map_.end()) {
|
||||
if (it->first.first == render_process_id)
|
||||
if (it->first.first.first == render_process_id)
|
||||
it = plugin_load_decision_map_.erase(it);
|
||||
else
|
||||
++it;
|
||||
|
@@ -12,8 +12,10 @@
|
||||
#include "content/public/browser/resource_context.h"
|
||||
#include "extensions/browser/info_map.h"
|
||||
#include "net/ssl/client_cert_store.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
class CefURLRequestContextGetter;
|
||||
enum class CefViewHostMsg_GetPluginInfo_Status;
|
||||
|
||||
// Acts as a bridge for resource loading. Life span is controlled by
|
||||
// CefBrowserContext. Created on the UI thread but accessed and destroyed on the
|
||||
@@ -46,15 +48,16 @@ class CefResourceContext : public content::ResourceContext {
|
||||
|
||||
// Remember the plugin load decision for plugin status requests that arrive
|
||||
// via CefPluginServiceFilter::IsPluginAvailable.
|
||||
// TODO(cef): Per-frame decisions are not currently supported because
|
||||
// Chromium does not pipe the frame id through to RenderFrameMessageFilter::
|
||||
// GetPluginsCallback. Fix this once https://crbug.com/626728#c15 is resolved.
|
||||
void AddPluginLoadDecision(int render_process_id,
|
||||
const base::FilePath& plugin_path,
|
||||
bool allow_load);
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
CefViewHostMsg_GetPluginInfo_Status status);
|
||||
bool HasPluginLoadDecision(int render_process_id,
|
||||
const base::FilePath& plugin_path,
|
||||
bool* allow_load) const;
|
||||
bool is_main_frame,
|
||||
const url::Origin& main_frame_origin,
|
||||
CefViewHostMsg_GetPluginInfo_Status* status) const;
|
||||
|
||||
// Clear the plugin load decisions associated with |render_process_id|, or all
|
||||
// plugin load decisions if |render_process_id| is -1.
|
||||
@@ -80,8 +83,11 @@ class CefResourceContext : public content::ResourceContext {
|
||||
scoped_refptr<extensions::InfoMap> extension_info_map_;
|
||||
CefRefPtr<CefRequestContextHandler> handler_;
|
||||
|
||||
// Map (render_process_id, plugin_path) to plugin load decision.
|
||||
typedef std::map<std::pair<int, base::FilePath>, bool>
|
||||
// Map (render_process_id, plugin_path, is_main_frame, main_frame_origin) to
|
||||
// plugin load decision.
|
||||
typedef std::map<std::pair<std::pair<int, base::FilePath>,
|
||||
std::pair<bool, url::Origin>>,
|
||||
CefViewHostMsg_GetPluginInfo_Status>
|
||||
PluginLoadDecisionMap;
|
||||
PluginLoadDecisionMap plugin_load_decision_map_;
|
||||
|
||||
|
@@ -231,10 +231,11 @@ IPC_STRUCT_END()
|
||||
// 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,
|
||||
IPC_SYNC_MESSAGE_CONTROL5_1(CefViewHostMsg_GetPluginInfo,
|
||||
int /* render_frame_id */,
|
||||
GURL /* url */,
|
||||
url::Origin /* top origin url */,
|
||||
bool /* is_main_frame */,
|
||||
url::Origin /* top_origin_url */,
|
||||
std::string /* mime_type */,
|
||||
CefViewHostMsg_GetPluginInfo_Output /* output */)
|
||||
|
||||
|
@@ -507,8 +507,8 @@ bool CefContentRendererClient::OverrideCreatePlugin(
|
||||
GURL url(params.url);
|
||||
CefViewHostMsg_GetPluginInfo_Output output;
|
||||
render_frame->Send(new CefViewHostMsg_GetPluginInfo(
|
||||
render_frame->GetRoutingID(), url, frame->top()->getSecurityOrigin(),
|
||||
orig_mime_type, &output));
|
||||
render_frame->GetRoutingID(), url, render_frame->IsMainFrame(),
|
||||
frame->top()->getSecurityOrigin(), orig_mime_type, &output));
|
||||
|
||||
*plugin = CreatePlugin(render_frame, frame, params, output);
|
||||
return true;
|
||||
|
@@ -182,6 +182,7 @@ void CefPluginPlaceholder::PluginListChanged() {
|
||||
std::string mime_type(GetPluginParams().mimeType.utf8());
|
||||
render_frame()->Send(new CefViewHostMsg_GetPluginInfo(
|
||||
routing_id(), GURL(GetPluginParams().url),
|
||||
GetFrame()->parent() == nullptr,
|
||||
GetFrame()->top()->getSecurityOrigin(), mime_type, &output));
|
||||
if (output.status == status_)
|
||||
return;
|
||||
|
Reference in New Issue
Block a user