Commit 755211fe authored by kalman@chromium.org's avatar kalman@chromium.org

Refactor guest view availability to be API based not permission based.

This is a step towards allowing WebUI to directly embed guest views. 

BUG=386838
R=fsamuel@chromium.org

Review URL: https://codereview.chromium.org/426593007

Cr-Commit-Position: refs/heads/master@{#288407}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288407 0039d316-1c4b-4281-b951-d872f2087c98
parent 14522ce4
......@@ -35,7 +35,7 @@ bool GuestViewInternalCreateGuestFunction::RunAsync() {
this);
guest_view_manager->CreateGuest(view_type,
extension_id(),
render_view_host()->GetProcess()->GetID(),
GetAssociatedWebContents(),
*create_params,
callback);
......
......@@ -6,6 +6,10 @@
namespace appview {
// API namespace for the embedder.
const char kEmbedderAPINamespace[] = "appViewEmbedderInternal";
// Parameters/properties on events.
const char kAppID[] = "appId";
const char kEmbedderID[] ="embedderId";
const char kGuestInstanceID[] = "guestInstanceId";
......
......@@ -9,6 +9,9 @@
namespace appview {
// API namespace for the *embedder*. The embedder and guest use different APIs.
extern const char kEmbedderAPINamespace[];
// Parameters/properties on events.
extern const char kAppID[];
extern const char kEmbedderID[];
......
......@@ -17,13 +17,11 @@
#include "extensions/browser/api/app_runtime/app_runtime_api.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/lazy_background_task_queue.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/api/app_runtime.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_message_macros.h"
namespace app_runtime = extensions::core_api::app_runtime;
......@@ -137,16 +135,8 @@ bool AppViewGuest::HandleContextMenu(const content::ContextMenuParams& params) {
return true;
}
bool AppViewGuest::CanEmbedderUseGuestView(
const std::string& embedder_extension_id) {
const extensions::Extension* embedder_extension =
extensions::ExtensionRegistry::Get(browser_context())
->enabled_extensions()
.GetByID(embedder_extension_id);
if (!embedder_extension)
return false;
return embedder_extension->permissions_data()->HasAPIPermission(
extensions::APIPermission::kAppView);
const char* AppViewGuest::GetAPINamespace() {
return appview::kEmbedderAPINamespace;
}
void AppViewGuest::CreateWebContents(
......
......@@ -47,8 +47,7 @@ class AppViewGuest : public GuestView<AppViewGuest>,
const content::ContextMenuParams& params) OVERRIDE;
// GuestViewBase implementation.
virtual bool CanEmbedderUseGuestView(
const std::string& embedder_extension_id) OVERRIDE;
virtual const char* GetAPINamespace() OVERRIDE;
virtual void CreateWebContents(
const std::string& embedder_extension_id,
int embedder_render_process_id,
......
......@@ -6,6 +6,9 @@
namespace extensionoptions {
// API namespace.
extern const char kAPINamespace[] = "extensionOptionsInternal";
// Attributes.
const char kAttributeAutoSize[] = "autosize";
const char kAttributeMaxHeight[] = "maxheight";
......
......@@ -7,6 +7,9 @@
namespace extensionoptions {
// API namespace.
extern const char kAPINamespace[];
// Attributes.
extern const char kAttributeAutoSize[];
extern const char kAttributeMaxHeight[];
......
......@@ -36,16 +36,8 @@ ExtensionOptionsGuest::ExtensionOptionsGuest(
ExtensionOptionsGuest::~ExtensionOptionsGuest() {
}
bool ExtensionOptionsGuest::CanEmbedderUseGuestView(
const std::string& embedder_extension_id) {
const extensions::Extension* embedder_extension =
extensions::ExtensionRegistry::Get(browser_context())
->enabled_extensions()
.GetByID(embedder_extension_id);
if (!embedder_extension)
return false;
return embedder_extension->permissions_data()->HasAPIPermission(
extensions::APIPermission::kEmbeddedExtensionOptions);
const char* ExtensionOptionsGuest::GetAPINamespace() {
return extensionoptions::kAPINamespace;
}
// static
......
......@@ -23,8 +23,7 @@ class ExtensionOptionsGuest
int guest_instance_id);
// GuestViewBase implementation.
virtual bool CanEmbedderUseGuestView(
const std::string& embedder_extension_id) OVERRIDE;
virtual const char* GetAPINamespace() OVERRIDE;
virtual void CreateWebContents(
const std::string& embedder_extension_id,
int embedder_render_process_id,
......
......@@ -18,6 +18,10 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_map.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/features/feature_provider.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
using content::WebContents;
......@@ -97,27 +101,48 @@ GuestViewBase::GuestViewBase(content::BrowserContext* browser_context,
weak_ptr_factory_(this) {
}
void GuestViewBase::Init(
const std::string& embedder_extension_id,
int embedder_render_process_id,
void GuestViewBase::Init(const std::string& embedder_extension_id,
content::WebContents* embedder_web_contents,
const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback) {
if (initialized_)
return;
initialized_ = true;
if (!CanEmbedderUseGuestView(embedder_extension_id)) {
extensions::Feature* feature =
extensions::FeatureProvider::GetAPIFeatures()->GetFeature(
GetAPINamespace());
CHECK(feature);
extensions::ProcessMap* process_map =
extensions::ProcessMap::Get(browser_context());
CHECK(process_map);
const extensions::Extension* embedder_extension =
extensions::ExtensionRegistry::Get(browser_context_)
->enabled_extensions()
.GetByID(embedder_extension_id);
int embedder_process_id =
embedder_web_contents->GetRenderProcessHost()->GetID();
extensions::Feature::Availability availability =
feature->IsAvailableToContext(
embedder_extension,
process_map->GetMostLikelyContextType(embedder_extension,
embedder_process_id),
embedder_web_contents->GetLastCommittedURL());
if (!availability.is_available()) {
callback.Run(NULL);
return;
}
CreateWebContents(embedder_extension_id,
embedder_render_process_id,
embedder_process_id,
create_params,
base::Bind(&GuestViewBase::CompleteInit,
AsWeakPtr(),
embedder_extension_id,
embedder_render_process_id,
embedder_process_id,
callback));
}
......
......@@ -141,11 +141,13 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
// to destruction.
virtual void WillDestroy() {}
// This method is to be implemented by the derived class. It determines
// whether the guest view type of the derived class can be used by the
// provided embedder extension ID.
virtual bool CanEmbedderUseGuestView(
const std::string& embedder_extension_id) = 0;
// This method is to be implemented by the derived class. Access to guest
// views are determined by the availability of the internal extension API
// used to implement the guest view.
//
// This should be the name of the API as it appears in the _api_features.json
// file.
virtual const char* GetAPINamespace() = 0;
// This method is to be implemented by the derived class. Given a set of
// initialization parameters, a concrete subclass of GuestViewBase can
......@@ -161,7 +163,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
// This creates a WebContents and initializes |this| GuestViewBase to use the
// newly created WebContents.
void Init(const std::string& embedder_extension_id,
int embedder_render_process_id,
content::WebContents* embedder_web_contents,
const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback);
......
......@@ -62,10 +62,9 @@ int GuestViewManager::GetNextInstanceID() {
return ++current_instance_id_;
}
void GuestViewManager::CreateGuest(
const std::string& view_type,
void GuestViewManager::CreateGuest(const std::string& view_type,
const std::string& embedder_extension_id,
int embedder_render_process_id,
content::WebContents* embedder_web_contents,
const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback) {
int guest_instance_id = GetNextInstanceID();
......@@ -75,10 +74,8 @@ void GuestViewManager::CreateGuest(
callback.Run(NULL);
return;
}
guest->Init(embedder_extension_id,
embedder_render_process_id,
create_params,
callback);
guest->Init(
embedder_extension_id, embedder_web_contents, create_params, callback);
}
content::WebContents* GuestViewManager::CreateGuestWithWebContentsParams(
......
......@@ -20,6 +20,7 @@ class GURL;
namespace content {
class BrowserContext;
class WebContents;
} // namespace content
class GuestViewManager : public content::BrowserPluginGuestManager,
......@@ -48,10 +49,9 @@ class GuestViewManager : public content::BrowserPluginGuestManager,
typedef base::Callback<void(content::WebContents*)>
WebContentsCreatedCallback;
void CreateGuest(
const std::string& view_type,
void CreateGuest(const std::string& view_type,
const std::string& embedder_extension_id,
int embedder_render_process_id,
content::WebContents* embedder_web_contents,
const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback);
......
......@@ -13,6 +13,9 @@ const char kAttributeMaxWidth[] = "maxwidth";
const char kAttributeMinHeight[] = "minheight";
const char kAttributeMinWidth[] = "minwidth";
// API namespace.
const char kAPINamespace[] = "webViewInternal";
// Events.
const char kEventClose[] = "webViewInternal.onClose";
const char kEventConsoleMessage[] = "webViewInternal.onConsoleMessage";
......
......@@ -16,6 +16,10 @@ extern const char kAttributeMaxWidth[];
extern const char kAttributeMinHeight[];
extern const char kAttributeMinWidth[];
// API namespace.
// TODO(kalman): Consolidate this with the other API constants.
extern const char kAPINamespace[];
// Events.
extern const char kEventClose[];
extern const char kEventConsoleMessage[];
......
......@@ -48,10 +48,8 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/stop_find_action.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
......@@ -226,16 +224,8 @@ scoped_ptr<base::ListValue> WebViewGuest::MenuModelToValue(
return items.Pass();
}
bool WebViewGuest::CanEmbedderUseGuestView(
const std::string& embedder_extension_id) {
const extensions::Extension* embedder_extension =
extensions::ExtensionRegistry::Get(browser_context())
->enabled_extensions()
.GetByID(embedder_extension_id);
if (!embedder_extension)
return false;
return embedder_extension->permissions_data()->HasAPIPermission(
extensions::APIPermission::kWebView);
const char* WebViewGuest::GetAPINamespace() {
return webview::kAPINamespace;
}
void WebViewGuest::CreateWebContents(
......@@ -570,13 +560,13 @@ void WebViewGuest::CreateNewGuestWebViewWindow(
base::DictionaryValue create_params;
create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
guest_manager->CreateGuest(
WebViewGuest::Type,
guest_manager->CreateGuest(WebViewGuest::Type,
embedder_extension_id(),
embedder_web_contents()->GetRenderProcessHost()->GetID(),
embedder_web_contents(),
create_params,
base::Bind(&WebViewGuest::NewGuestWebViewCallback,
base::Unretained(this), params));
base::Unretained(this),
params));
}
void WebViewGuest::NewGuestWebViewCallback(
......
......@@ -83,8 +83,7 @@ class WebViewGuest : public GuestView<WebViewGuest>,
void SetZoom(double zoom_factor);
// GuestViewBase implementation.
virtual bool CanEmbedderUseGuestView(
const std::string& embedder_extension_id) OVERRIDE;
virtual const char* GetAPINamespace() OVERRIDE;
virtual void CreateWebContents(
const std::string& embedder_extension_id,
int embedder_render_process_id,
......
......@@ -56,6 +56,14 @@
// Any webpage can use the app API.
"matches": ["<all_urls>"]
},
// The API for the *embedder* of appview. Appview has both an embedder and
// guest API, which are different.
"appViewEmbedderInternal": {
"internal": true,
"contexts": ["blessed_extension"],
"dependencies": ["permission:appview"]
},
// TODO(fsamuel,kalman): Rename this appViewGuestInternal.
"appViewInternal": {
"internal": true,
"channel": "dev",
......
......@@ -539,7 +539,8 @@ void EventRouter::DispatchEventToProcess(const std::string& extension_id,
BrowserContext* listener_context = process->GetBrowserContext();
ProcessMap* process_map = ProcessMap::Get(listener_context);
// TODO(kalman): Convert this method to use ProcessMap::GuessContextType.
// TODO(kalman): Convert this method to use
// ProcessMap::GetMostLikelyContextType.
const Extension* extension =
ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
......
......@@ -455,7 +455,7 @@ ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
function->set_response_callback(callback);
function->set_source_tab_id(params.source_tab_id);
function->set_source_context_type(
process_map.GuessContextType(extension, requesting_process_id));
process_map.GetMostLikelyContextType(extension, requesting_process_id));
return function;
}
......
......@@ -123,7 +123,8 @@ std::set<std::string> ProcessMap::GetExtensionsInProcess(int process_id) const {
return result;
}
Feature::Context ProcessMap::GuessContextType(const Extension* extension,
Feature::Context ProcessMap::GetMostLikelyContextType(
const Extension* extension,
int process_id) const {
// WARNING: This logic must match Dispatcher::ClassifyJavaScriptContext, as
// much as possible.
......
......@@ -95,23 +95,35 @@ class ProcessMap : public KeyedService {
std::set<std::string> GetExtensionsInProcess(int process_id) const;
// Guesses the most permissive context type for the process with ID
// |process_id|. Context types are renderer (JavaScript) concepts but the
// browser can do a decent job in guessing what the process hosts.
// Gets the most likely context type for the process with ID |process_id|
// which hosts Extension |extension|, if any (may be NULL). Context types are
// renderer (JavaScript) concepts but the browser can do a decent job in
// guessing what the process hosts.
//
// |extension| is the funky part - unfortunately we need to trust the
// caller of this method to be correct that indeed the context does feature
// an extension. This matters for iframes, where an extension could be
// hosted in another extension's process (privilege level needs to be
// downgraded) or in a web page's process (privilege level needs to be
// upgraded).
//
// The latter of these is slightly problematic from a security perspective;
// if a web page renderer gets owned it could try to pretend it's an
// extension and get access to some unprivileged APIs. Luckly, when OOP
// iframes lauch, it won't be an issue.
//
// Anyhow, the expected behaviour is:
// - For hosted app processes, this will be blessed_web_page.
// - For other extension processes, this will be blessed_extension.
// - For WebUI processes, this will be a webui.
// - For anything else we have the choice of unblessed_extension or
// - For any other extension we have the choice of unblessed_extension or
// content_script. Since content scripts are more common, guess that.
// We *could* in theory track which web processes have extension frames
// in them, and those would be unblessed_extension, but we don't at the
// moment, and once OOP iframes exist then there won't even be such a
// thing as an unblessed_extension context.
//
// |extension| isn't used to upgrade the process trust level, but rather used
// as a tiebreaker if a process is found to contain multiple extensions.
Feature::Context GuessContextType(const Extension* extension,
// - For anything else, web_page.
Feature::Context GetMostLikelyContextType(const Extension* extension,
int process_id) const;
private:
......
......@@ -1174,7 +1174,7 @@ Feature::Context Dispatcher::ClassifyJavaScriptContext(
int extension_group,
const GURL& url,
const blink::WebSecurityOrigin& origin) {
// WARNING: This logic must match ProcessMap::GuessContextType, as much as
// WARNING: This logic must match ProcessMap::GetContextType, as much as
// possible.
DCHECK_GE(extension_group, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment