Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Unified Diff: content/browser/browser_plugin/browser_plugin_guest.cc

Issue 272573005: <webview>: Move NewWindow API to chrome (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@guestview_manager_rename
Patch Set: Merge with ToT Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/browser_plugin/browser_plugin_guest.cc
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 301fa0647581969a7533b58424880edcbb1a4f32..d9b86594d2bde61efa51f4b9767510e981b2c720 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -55,103 +55,7 @@ namespace content {
// static
BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
-// Parent class for the various types of permission requests, each of which
-// should be able to handle the response to their permission request.
-class BrowserPluginGuest::PermissionRequest :
- public base::RefCounted<BrowserPluginGuest::PermissionRequest> {
- public:
- void Respond(bool should_allow, const std::string& user_input) {
- if (!guest_)
- return;
- RespondImpl(should_allow, user_input);
- }
- virtual bool AllowedByDefault() const {
- return false;
- }
- protected:
- explicit PermissionRequest(const base::WeakPtr<BrowserPluginGuest>& guest)
- : guest_(guest) {
- RecordAction(
- base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
- }
- virtual ~PermissionRequest() {}
-
- virtual void RespondImpl(bool should_allow,
- const std::string& user_input) = 0;
- // Friend RefCounted so that the dtor can be non-public.
- friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>;
-
- base::WeakPtr<BrowserPluginGuest> guest_;
-};
-
-class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
- public:
- NewWindowRequest(const base::WeakPtr<BrowserPluginGuest>& guest,
- int instance_id)
- : PermissionRequest(guest),
- instance_id_(instance_id) {
- RecordAction(
- base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow"));
- }
-
- virtual void RespondImpl(bool should_allow,
- const std::string& user_input) OVERRIDE {
- int embedder_render_process_id =
- guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
- guest_->GetBrowserPluginGuestManager()->
- MaybeGetGuestByInstanceIDOrKill(
- instance_id_,
- embedder_render_process_id,
- base::Bind(&BrowserPluginGuest::NewWindowRequest::RespondInternal,
- base::Unretained(this),
- should_allow));
- }
-
- private:
- virtual ~NewWindowRequest() {}
-
- void RespondInternal(bool should_allow,
- WebContents* guest_web_contents) {
- if (!guest_web_contents) {
- VLOG(0) << "Guest not found. Instance ID: " << instance_id_;
- return;
- }
-
- BrowserPluginGuest* guest =
- static_cast<WebContentsImpl*>(guest_web_contents)->
- GetBrowserPluginGuest();
- DCHECK(guest);
- // If we do not destroy the guest then we allow the new window.
- if (!should_allow)
- guest->Destroy();
- }
-
- int instance_id_;
-};
-
namespace {
-std::string WindowOpenDispositionToString(
- WindowOpenDisposition window_open_disposition) {
- switch (window_open_disposition) {
- case IGNORE_ACTION:
- return "ignore";
- case SAVE_TO_DISK:
- return "save_to_disk";
- case CURRENT_TAB:
- return "current_tab";
- case NEW_BACKGROUND_TAB:
- return "new_background_tab";
- case NEW_FOREGROUND_TAB:
- return "new_foreground_tab";
- case NEW_WINDOW:
- return "new_window";
- case NEW_POPUP:
- return "new_popup";
- default:
- NOTREACHED() << "Unknown Window Open Disposition";
- return "ignore";
- }
-}
} // namespace
@@ -201,7 +105,6 @@ BrowserPluginGuest::BrowserPluginGuest(
embedder_visible_(true),
auto_size_enabled_(false),
copy_request_id_(0),
- next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
has_render_view_(has_render_view),
last_seen_auto_size_enabled_(false),
is_in_destruction_(false),
@@ -225,116 +128,9 @@ bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
return true;
}
-void BrowserPluginGuest::DestroyUnattachedWindows() {
- // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
- // pending_new_windows_ set. To avoid mutating the set while iterating, we
- // create a copy of the pending new windows set and iterate over the copy.
- PendingWindowMap pending_new_windows(pending_new_windows_);
- // Clean up unattached new windows opened by this guest.
- for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
- it != pending_new_windows.end(); ++it) {
- it->first->Destroy();
- }
- // All pending windows should be removed from the set after Destroy() is
- // called on all of them.
- DCHECK(pending_new_windows_.empty());
-}
-
-void BrowserPluginGuest::LoadURLWithParams(const GURL& url,
- const Referrer& referrer,
- PageTransition transition_type,
- WebContents* web_contents) {
- NavigationController::LoadURLParams load_url_params(url);
- load_url_params.referrer = referrer;
- load_url_params.transition_type = transition_type;
- load_url_params.extra_headers = std::string();
- if (delegate_ && delegate_->IsOverridingUserAgent()) {
- load_url_params.override_user_agent =
- NavigationController::UA_OVERRIDE_TRUE;
- }
- web_contents->GetController().LoadURLWithParams(load_url_params);
-}
-
-void BrowserPluginGuest::RespondToPermissionRequest(
- int request_id,
- bool should_allow,
- const std::string& user_input) {
- RequestMap::iterator request_itr = permission_request_map_.find(request_id);
- if (request_itr == permission_request_map_.end()) {
- VLOG(0) << "Not a valid request ID.";
- return;
- }
- request_itr->second->Respond(should_allow, user_input);
- permission_request_map_.erase(request_itr);
-}
-
-void BrowserPluginGuest::RequestPermission(
- BrowserPluginPermissionType permission_type,
- scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
- const base::DictionaryValue& request_info) {
- if (!delegate_) {
- // Let the stack unwind before we deny the permission request so that
- // objects held by the permission request are not destroyed immediately
- // after creation. This is to allow those same objects to be accessed again
- // in the same scope without fear of use after freeing.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserPluginGuest::PermissionRequest::Respond,
- request, false, ""));
- }
-
- int request_id = ++next_permission_request_id_;
- permission_request_map_[request_id] = request;
-
- BrowserPluginGuestDelegate::PermissionResponseCallback callback =
- base::Bind(&BrowserPluginGuest::RespondToPermissionRequest,
- AsWeakPtr(),
- request_id);
- delegate_->RequestPermission(
- permission_type, request_info, callback, request->AllowedByDefault());
-}
-
-BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
- const OpenURLParams& params) {
- BrowserPluginGuestManager* guest_manager =
- GetBrowserPluginGuestManager();
-
- // Allocate a new instance ID for the new guest.
- int instance_id = guest_manager->GetNextInstanceID();
-
- // Set the attach params to use the same partition as the opener.
- // We pull the partition information from the site's URL, which is of the form
- // guest://site/{persist}?{partition_name}.
- const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
-
- // The new guest gets a copy of this guest's extra params so that the content
- // embedder exposes the same API for this guest as its opener.
- scoped_ptr<base::DictionaryValue> extra_params(
- extra_attach_params_->DeepCopy());
- const std::string& storage_partition_id = site_url.query();
- bool persist_storage =
- site_url.path().find("persist") != std::string::npos;
- WebContents* new_guest_web_contents =
- guest_manager->CreateGuest(GetWebContents()->GetSiteInstance(),
- instance_id,
- storage_partition_id,
- persist_storage,
- extra_params.Pass());
- BrowserPluginGuest* new_guest =
- static_cast<WebContentsImpl*>(new_guest_web_contents)->
- GetBrowserPluginGuest();
- if (new_guest->delegate_)
- new_guest->delegate_->SetOpener(GetWebContents());
-
- // Take ownership of |new_guest|.
- pending_new_windows_.insert(
- std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
-
- // Request permission to show the new window.
- RequestNewWindowPermission(params.disposition, gfx::Rect(),
- params.user_gesture, new_guest->GetWebContents());
-
- return new_guest;
+void BrowserPluginGuest::WillDestroy(WebContents* web_contents) {
+ DCHECK_EQ(web_contents, GetWebContents());
+ is_in_destruction_ = true;
}
base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
@@ -356,11 +152,9 @@ void BrowserPluginGuest::EmbedderDestroyed() {
}
void BrowserPluginGuest::Destroy() {
- is_in_destruction_ = true;
- if (!attached() && GetOpener())
- GetOpener()->pending_new_windows_.erase(this);
- DestroyUnattachedWindows();
- delete GetWebContents();
+ if (!delegate_)
+ return;
+ delegate_->Destroy();
}
bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
@@ -464,10 +258,9 @@ void BrowserPluginGuest::Initialize(
if (!params.src.empty()) {
// params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
OnNavigateGuest(instance_id_, params.src);
+ has_render_view_ = true;
}
- has_render_view_ = true;
-
WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
prefs.navigate_on_drag_drop = false;
GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
@@ -508,39 +301,37 @@ BrowserPluginGuest* BrowserPluginGuest::Create(
int instance_id,
SiteInstance* guest_site_instance,
WebContentsImpl* web_contents,
- scoped_ptr<base::DictionaryValue> extra_params) {
+ scoped_ptr<base::DictionaryValue> extra_params,
+ BrowserPluginGuest* opener) {
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
BrowserPluginGuest* guest = NULL;
if (factory_) {
guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents);
} else {
- guest = new BrowserPluginGuest(instance_id, false, web_contents);
+ guest = new BrowserPluginGuest(instance_id,
+ web_contents->opener() != NULL,
+ web_contents);
}
- guest->extra_attach_params_.reset(extra_params->DeepCopy());
- web_contents->SetBrowserPluginGuest(guest);
- BrowserPluginGuestDelegate* delegate = NULL;
- GetContentClient()->browser()->GuestWebContentsCreated(
- guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass());
- guest->SetDelegate(delegate);
- return guest;
-}
-
-// static
-BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
- int instance_id,
- bool has_render_view,
- WebContentsImpl* web_contents,
- BrowserPluginGuest* opener) {
- BrowserPluginGuest* guest =
- new BrowserPluginGuest(
- instance_id, has_render_view, web_contents);
web_contents->SetBrowserPluginGuest(guest);
+ WebContents* opener_web_contents = NULL;
+ if (opener) {
+ opener_web_contents = opener->GetWebContents();
+ guest_site_instance = opener_web_contents->GetSiteInstance();
+ }
BrowserPluginGuestDelegate* delegate = NULL;
GetContentClient()->browser()->GuestWebContentsCreated(
- opener->GetWebContents()->GetSiteInstance(),
- web_contents, opener->GetWebContents(), &delegate,
- scoped_ptr<base::DictionaryValue>());
- guest->SetDelegate(delegate);
+ instance_id,
+ guest_site_instance,
+ web_contents,
+ opener_web_contents,
+ &delegate,
+ extra_params.Pass());
+ if (delegate) {
+ delegate->RegisterDestructionCallback(
+ base::Bind(&BrowserPluginGuest::WillDestroy,
+ base::Unretained(guest)));
+ guest->SetDelegate(delegate);
+ }
return guest;
}
@@ -550,17 +341,6 @@ RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
return embedder_web_contents_->GetRenderWidgetHostView();
}
-BrowserPluginGuest* BrowserPluginGuest::GetOpener() const {
- if (!delegate_)
- return NULL;
-
- WebContents* opener = delegate_->GetOpener();
- if (!opener)
- return NULL;
-
- return static_cast<WebContentsImpl*>(opener)->GetBrowserPluginGuest();
-}
-
void BrowserPluginGuest::UpdateVisibility() {
OnSetVisibility(instance_id_, visible());
}
@@ -598,10 +378,11 @@ void BrowserPluginGuest::AddNewContents(WebContents* source,
const gfx::Rect& initial_pos,
bool user_gesture,
bool* was_blocked) {
- if (was_blocked)
- *was_blocked = false;
- RequestNewWindowPermission(disposition, initial_pos, user_gesture,
- static_cast<WebContentsImpl*>(new_contents));
+ if (!delegate_)
+ return;
+
+ delegate_->AddNewContents(source, new_contents, disposition,
+ initial_pos, user_gesture, was_blocked);
}
void BrowserPluginGuest::CanDownload(
@@ -695,29 +476,9 @@ void BrowserPluginGuest::FindReply(WebContents* contents,
WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
const OpenURLParams& params) {
- // If the guest wishes to navigate away prior to attachment then we save the
- // navigation to perform upon attachment. Navigation initializes a lot of
- // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
- // Navigation also resumes resource loading which we don't want to allow
- // until attachment.
- if (!attached()) {
- PendingWindowMap::iterator it =
- GetOpener()->pending_new_windows_.find(this);
- if (it == GetOpener()->pending_new_windows_.end())
- return NULL;
- const NewWindowInfo& old_target_url = it->second;
- NewWindowInfo new_window_info(params.url, old_target_url.name);
- new_window_info.changed = new_window_info.url != old_target_url.url;
- it->second = new_window_info;
+ if (!delegate_)
return NULL;
- }
- if (params.disposition == CURRENT_TAB) {
- // This can happen for cross-site redirects.
- LoadURLWithParams(params.url, params.referrer, params.transition, source);
- return source;
- }
-
- return CreateNewGuestWindow(params)->GetWebContents();
+ return delegate_->OpenURLFromTab(source, params);
}
void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
@@ -728,15 +489,17 @@ void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
WebContentsImpl* new_contents_impl =
static_cast<WebContentsImpl*>(new_contents);
BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
- if (guest->delegate_)
- guest->delegate_->SetOpener(GetWebContents());
std::string guest_name = base::UTF16ToUTF8(frame_name);
guest->name_ = guest_name;
- // Take ownership of the new guest until it is attached to the embedder's DOM
- // tree to avoid leaking a guest if this guest is destroyed before attaching
- // the new guest.
- pending_new_windows_.insert(
- std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
+
+ if (!delegate_)
+ return;
+
+ delegate_->WebContentsCreated(source_contents,
+ opener_render_frame_id,
+ frame_name,
+ target_url,
+ new_contents);
}
void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
@@ -782,38 +545,6 @@ bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
size.height() <= max_auto_size_.height();
}
-void BrowserPluginGuest::RequestNewWindowPermission(
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_bounds,
- bool user_gesture,
- WebContentsImpl* new_contents) {
- BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
- PendingWindowMap::iterator it = pending_new_windows_.find(guest);
- if (it == pending_new_windows_.end())
- return;
- const NewWindowInfo& new_window_info = it->second;
-
- base::DictionaryValue request_info;
- request_info.Set(browser_plugin::kInitialHeight,
- base::Value::CreateIntegerValue(initial_bounds.height()));
- request_info.Set(browser_plugin::kInitialWidth,
- base::Value::CreateIntegerValue(initial_bounds.width()));
- request_info.Set(browser_plugin::kTargetURL,
- base::Value::CreateStringValue(new_window_info.url.spec()));
- request_info.Set(browser_plugin::kName,
- base::Value::CreateStringValue(new_window_info.name));
- request_info.Set(browser_plugin::kWindowID,
- base::Value::CreateIntegerValue(guest->instance_id()));
- request_info.Set(browser_plugin::kWindowOpenDisposition,
- base::Value::CreateStringValue(
- WindowOpenDispositionToString(disposition)));
-
- RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
- new NewWindowRequest(weak_ptr_factory_.GetWeakPtr(),
- guest->instance_id()),
- request_info);
-}
-
void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
if (!attached()) {
// Some pages such as data URLs, javascript URLs, and about:blank
@@ -916,8 +647,6 @@ void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
default:
break;
}
- // TODO(fsamuel): Consider whether we should be clearing
- // |permission_request_map_| here.
if (delegate_)
delegate_->GuestProcessGone(status);
}
@@ -991,8 +720,6 @@ void BrowserPluginGuest::Attach(
if (attached())
return;
- extra_attach_params_.reset(extra_params.DeepCopy());
-
// Clear parameters that get inherited from the opener.
params.storage_partition_id.clear();
params.persist_storage = false;
@@ -1009,23 +736,6 @@ void BrowserPluginGuest::Attach(
new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
}
- // We need to do a navigation here if the target URL has changed between
- // the time the WebContents was created and the time it was attached.
- // We also need to do an initial navigation if a RenderView was never
- // created for the new window in cases where there is no referrer.
- PendingWindowMap::iterator it = GetOpener()->pending_new_windows_.find(this);
- if (it != GetOpener()->pending_new_windows_.end()) {
- const NewWindowInfo& new_window_info = it->second;
- if (new_window_info.changed || !has_render_view_)
- params.src = it->second.url.spec();
- } else {
- NOTREACHED();
- }
-
- // Once a new guest is attached to the DOM of the embedder page, then the
- // lifetime of the new guest is no longer managed by the opener guest.
- GetOpener()->pending_new_windows_.erase(this);
-
// The guest's frame name takes precedence over the BrowserPlugin's name.
// The guest's frame name is assigned in
// BrowserPluginGuest::WebContentsCreated.
@@ -1205,38 +915,11 @@ void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
mouse_locked_ = true;
}
-void BrowserPluginGuest::OnNavigateGuest(
- int instance_id,
- const std::string& src) {
- GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src);
-
- // Do not allow navigating a guest to schemes other than known safe schemes.
- // This will block the embedder trying to load unwanted schemes, e.g.
- // chrome://settings.
- bool scheme_is_blocked =
- (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
- url.scheme()) &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
- url.scheme())) ||
- url.SchemeIs(kJavaScriptScheme);
- if (scheme_is_blocked || !url.is_valid()) {
- if (delegate_) {
- std::string error_type;
- base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
- &error_type);
- delegate_->LoadAbort(true /* is_top_level */, url, error_type);
- }
+void BrowserPluginGuest::OnNavigateGuest(int instance_id,
+ const std::string& src) {
+ if (!delegate_)
return;
- }
-
- GURL validated_url(url);
- GetWebContents()->GetRenderProcessHost()->FilterURL(false, &validated_url);
- // As guests do not swap processes on navigation, only navigations to
- // normal web URLs are supported. No protocol handlers are installed for
- // other schemes (e.g., WebUI or extensions), and no permissions or bindings
- // can be granted to the guest process.
- LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL,
- GetWebContents());
+ delegate_->NavigateGuest(src);
}
void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {

Powered by Google App Engine
This is Rietveld 408576698