<webview> WebRequest API tied to webview instance ID instead of guest instance ID
This permits installing WebRequest API listeners prior to initial navigation and prior to attachment.
BUG=171421
Test=WebViewInteractiveTest.NewWindow
Review URL: https://chromiumcodereview.appspot.com/15894014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204213 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index cfcedc7..6381e399 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -678,8 +678,10 @@
return activity_log->IsLogEnabled();
}
-void ChromeContentBrowserClient::GuestWebContentsCreated(
- WebContents* guest_web_contents, WebContents* embedder_web_contents) {
+void ChromeContentBrowserClient::GuestWebContentsAttached(
+ WebContents* guest_web_contents,
+ WebContents* embedder_web_contents,
+ int browser_plugin_instance_id) {
Profile* profile = Profile::FromBrowserContext(
embedder_web_contents->GetBrowserContext());
ExtensionService* service =
@@ -697,7 +699,10 @@
// TODO(fsamuel): This should be replaced with WebViewGuest or AdViewGuest
// once they are ready.
extensions::TabHelper::CreateForWebContents(guest_web_contents);
- new WebViewGuest(guest_web_contents, embedder_web_contents, extension->id());
+ new WebViewGuest(guest_web_contents,
+ embedder_web_contents,
+ extension->id(),
+ browser_plugin_instance_id);
}
void ChromeContentBrowserClient::RenderProcessHostCreated(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 6472748..db7b5b8d 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -59,9 +59,10 @@
bool* in_memory) OVERRIDE;
virtual content::WebContentsViewDelegate* GetWebContentsViewDelegate(
content::WebContents* web_contents) OVERRIDE;
- virtual void GuestWebContentsCreated(
+ virtual void GuestWebContentsAttached(
content::WebContents* guest_web_contents,
- content::WebContents* embedder_web_contents) OVERRIDE;
+ content::WebContents* embedder_web_contents,
+ int browser_plugin_instance_id) OVERRIDE;
virtual void RenderProcessHostCreated(
content::RenderProcessHost* host) OVERRIDE;
virtual bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc
index 401741f6..e43a471 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -394,7 +394,8 @@
RequestFilter filter;
int extra_info_spec;
int embedder_process_id;
- int web_view_instance_id;
+ int embedder_routing_id;
+ int webview_instance_id;
base::WeakPtr<IPC::Sender> ipc_sender;
mutable std::set<uint64> blocked_requests;
@@ -1155,7 +1156,8 @@
const RequestFilter& filter,
int extra_info_spec,
int embedder_process_id,
- int web_view_instance_id,
+ int embedder_routing_id,
+ int webview_instance_id,
base::WeakPtr<IPC::Sender> ipc_sender) {
if (!IsWebRequestEvent(event_name))
@@ -1169,7 +1171,8 @@
listener.extra_info_spec = extra_info_spec;
listener.ipc_sender = ipc_sender;
listener.embedder_process_id = embedder_process_id;
- listener.web_view_instance_id = web_view_instance_id;
+ listener.embedder_routing_id = embedder_routing_id;
+ listener.webview_instance_id = webview_instance_id;
if (listeners_[profile][event_name].count(listener) != 0u) {
// This is likely an abuse of the API by a malicious extension.
@@ -1219,7 +1222,7 @@
void* profile,
const std::string& extension_id,
int embedder_process_id,
- int web_view_instance_id) {
+ int webview_instance_id) {
// Iterate over all listeners of all WebRequest events to delete
// any listeners that belong to the provided <webview>.
ListenerMapForProfile& map_for_profile = listeners_[profile];
@@ -1231,7 +1234,7 @@
listener_iter != listeners.end(); ++listener_iter) {
const EventListener& listener = *listener_iter;
if (listener.embedder_process_id == embedder_process_id &&
- listener.web_view_instance_id == web_view_instance_id)
+ listener.webview_instance_id == webview_instance_id)
listeners_to_delete.push_back(listener);
}
for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
@@ -1326,9 +1329,9 @@
std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
matching_listeners) {
std::string web_request_event_name(event_name);
- ExtensionRendererState::WebViewInfo web_view_info;
+ ExtensionRendererState::WebViewInfo webview_info;
bool is_guest = ExtensionRendererState::GetInstance()->
- GetWebViewInfo(render_process_host_id, routing_id, &web_view_info);
+ GetWebViewInfo(render_process_host_id, routing_id, &webview_info);
if (is_guest)
web_request_event_name.replace(0, sizeof(kWebRequest) - 1, kWebView);
@@ -1343,8 +1346,9 @@
}
if (is_guest &&
- (it->embedder_process_id != web_view_info.embedder_process_id ||
- it->web_view_instance_id != web_view_info.web_view_instance_id))
+ (it->embedder_process_id != webview_info.embedder_process_id ||
+ it->embedder_routing_id != webview_info.embedder_routing_id ||
+ it->webview_instance_id != webview_info.instance_id))
continue;
if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
@@ -2037,19 +2041,20 @@
std::string sub_event_name;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
- int web_view_instance_id = 0;
- EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &web_view_instance_id));
+ int webview_instance_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id));
base::WeakPtr<ChromeRenderMessageFilter> ipc_sender = ipc_sender_weak();
int embedder_process_id =
ipc_sender.get() ? ipc_sender->render_process_id() : -1;
+ int embedder_routing_id = routing_id();
const Extension* extension =
extension_info_map()->extensions().GetByID(extension_id());
std::string extension_name = extension ? extension->name() : extension_id();
- bool is_guest = web_view_instance_id != 0;
+ bool is_guest = webview_instance_id != 0;
// We check automatically whether the extension has the 'webRequest'
// permission. For blocking calls we require the additional permission
// 'webRequestBlocking'.
@@ -2078,7 +2083,8 @@
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
profile_id(), extension_id(), extension_name,
event_name, sub_event_name, filter, extra_info_spec,
- embedder_process_id, web_view_instance_id, ipc_sender_weak());
+ embedder_process_id, embedder_routing_id, webview_instance_id,
+ ipc_sender_weak());
EXTENSION_FUNCTION_VALIDATE(success);
helpers::ClearCacheOnNavigation();
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.h b/chrome/browser/extensions/api/web_request/web_request_api.h
index 108174c..3a0d43e 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api.h
@@ -246,6 +246,7 @@
const RequestFilter& filter,
int extra_info_spec,
int embedder_process_id,
+ int embedder_routing_id,
int web_view_instance_id,
base::WeakPtr<IPC::Sender> ipc_sender);
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index e6e39cd..dac311d1 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -225,12 +225,12 @@
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
net::URLRequestJobFactoryImpl job_factory;
job_factory.SetProtocolHandler(
@@ -360,12 +360,12 @@
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
GURL request_url("about:blank");
net::URLRequest request(request_url, &delegate_, context_.get());
@@ -428,11 +428,11 @@
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName2, kEventName2 + "/1",
- filter, 0, -1, -1, ipc_sender_factory.GetWeakPtr());
+ filter, 0, -1, MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
GURL request_url("about:blank");
net::URLRequest request(request_url, &delegate_, context_.get());
@@ -617,7 +617,7 @@
ASSERT_TRUE(GenerateInfoSpec(string_spec_post, &extra_info_spec_body));
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_body, -1, -1,
+ filter, extra_info_spec_body, -1, MSG_ROUTING_NONE, -1,
ipc_sender_factory.GetWeakPtr());
FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2);
@@ -634,7 +634,7 @@
GenerateInfoSpec(string_spec_no_post, &extra_info_spec_empty));
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_empty, -1, -1,
+ filter, extra_info_spec_empty, -1, MSG_ROUTING_NONE, -1,
ipc_sender_factory.GetWeakPtr());
FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2);
@@ -645,7 +645,7 @@
// Subscribe to OnBeforeRequest with requestBody requirement.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_body, -1, -1,
+ filter, extra_info_spec_body, -1, MSG_ROUTING_NONE, -1,
ipc_sender_factory.GetWeakPtr());
// Part 3.
@@ -704,7 +704,8 @@
// Subscribe to OnBeforeRequest with requestBody requirement.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec, -1, -1, ipc_sender_factory.GetWeakPtr());
+ filter, extra_info_spec, -1, MSG_ROUTING_NONE, -1,
+ ipc_sender_factory.GetWeakPtr());
// The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
const GURL request_url("http://www.example.com");
@@ -817,19 +818,19 @@
// higher precedence than extension 1.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
// Install one extension that observes the final headers.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
&profile_, extension3_id, extension3_id, keys::kOnSendHeadersEvent,
std::string(keys::kOnSendHeadersEvent) + "/3", filter,
- ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, -1, -1,
- ipc_sender_factory.GetWeakPtr());
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, -1,
+ MSG_ROUTING_NONE, -1, ipc_sender_factory.GetWeakPtr());
GURL request_url("http://doesnotexist/does_not_exist.html");
net::URLRequest request(request_url, &delegate_, context_.get());
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index 6aa978c..fcf5cf6 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -264,7 +264,8 @@
render_view_host_->GetRoutingID(), level, message));
}
-IOThreadExtensionFunction::IOThreadExtensionFunction() {
+IOThreadExtensionFunction::IOThreadExtensionFunction()
+ : routing_id_(MSG_ROUTING_NONE) {
}
IOThreadExtensionFunction::~IOThreadExtensionFunction() {
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index 4218786e..4afc40d1 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -405,14 +405,18 @@
virtual IOThreadExtensionFunction* AsIOThreadExtensionFunction() OVERRIDE;
- void set_ipc_sender(base::WeakPtr<ChromeRenderMessageFilter> ipc_sender) {
+ void set_ipc_sender(base::WeakPtr<ChromeRenderMessageFilter> ipc_sender,
+ int routing_id) {
ipc_sender_ = ipc_sender;
+ routing_id_ = routing_id;
}
base::WeakPtr<ChromeRenderMessageFilter> ipc_sender_weak() const {
return ipc_sender_;
}
+ int routing_id() const { return routing_id_; }
+
void set_extension_info_map(const ExtensionInfoMap* extension_info_map) {
extension_info_map_ = extension_info_map;
}
@@ -433,6 +437,7 @@
private:
base::WeakPtr<ChromeRenderMessageFilter> ipc_sender_;
+ int routing_id_;
scoped_refptr<const ExtensionInfoMap> extension_info_map_;
};
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index a9fb3f7..ed05d09 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -279,7 +279,7 @@
NOTREACHED();
return;
}
- function_io->set_ipc_sender(ipc_sender);
+ function_io->set_ipc_sender(ipc_sender, routing_id);
function_io->set_extension_info_map(extension_info_map);
function->set_include_incognito(
extension_info_map->IsIncognitoEnabled(extension->id()));
diff --git a/chrome/browser/extensions/extension_renderer_state.cc b/chrome/browser/extensions/extension_renderer_state.cc
index 62516b0..c43c690 100644
--- a/chrome/browser/extensions/extension_renderer_state.cc
+++ b/chrome/browser/extensions/extension_renderer_state.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/tab_contents/retargeting_details.h"
+#include "chrome/browser/webview/webview_guest.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.h"
@@ -37,22 +38,12 @@
}
virtual void RenderViewHostDestroyed(content::RenderViewHost* host) OVERRIDE {
- if (host->GetProcess()->IsGuest()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &ExtensionRendererState::RemoveWebView,
- base::Unretained(ExtensionRendererState::GetInstance()),
- host->GetProcess()->GetID(),
- host->GetRoutingID()));
- } else {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &ExtensionRendererState::ClearTabAndWindowId,
- base::Unretained(ExtensionRendererState::GetInstance()),
- host->GetProcess()->GetID(), host->GetRoutingID()));
- }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &ExtensionRendererState::ClearTabAndWindowId,
+ base::Unretained(ExtensionRendererState::GetInstance()),
+ host->GetProcess()->GetID(), host->GetRoutingID()));
delete this;
}
@@ -88,9 +79,6 @@
registrar_.Add(this,
content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
content::NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this,
- content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
- content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, chrome::NOTIFICATION_RETARGETING,
@@ -128,33 +116,6 @@
break;
}
- case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: {
- WebContents* web_contents = content::Source<WebContents>(source).ptr();
- if (!web_contents->GetRenderProcessHost()->IsGuest())
- return;
-
- WebContents* embedder_web_contents =
- web_contents->GetEmbedderWebContents();
- if (!embedder_web_contents)
- return;
- WebViewInfo web_view_info;
- web_view_info.embedder_process_id =
- embedder_web_contents->GetRenderProcessHost()->GetID();
- web_view_info.embedder_routing_id =
- embedder_web_contents->GetRoutingID();
- web_view_info.web_view_instance_id =
- web_contents->GetEmbeddedInstanceID();
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &ExtensionRendererState::AddWebView,
- base::Unretained(ExtensionRendererState::GetInstance()),
- web_contents->GetRenderProcessHost()->GetID(),
- web_contents->GetRoutingID(),
- web_view_info));
- break;
- }
case chrome::NOTIFICATION_TAB_PARENTED: {
WebContents* web_contents = content::Source<WebContents>(source).ptr();
SessionTabHelper* session_tab_helper =
@@ -249,27 +210,27 @@
void ExtensionRendererState::AddWebView(int guest_process_id,
int guest_routing_id,
- const WebViewInfo& web_view_info) {
+ const WebViewInfo& webview_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
RenderId render_id(guest_process_id, guest_routing_id);
- web_view_info_map_[render_id] = web_view_info;
+ webview_info_map_[render_id] = webview_info;
}
void ExtensionRendererState::RemoveWebView(int guest_process_id,
int guest_routing_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
RenderId render_id(guest_process_id, guest_routing_id);
- web_view_info_map_.erase(render_id);
+ webview_info_map_.erase(render_id);
}
bool ExtensionRendererState::GetWebViewInfo(int guest_process_id,
int guest_routing_id,
- WebViewInfo* web_view_info) {
+ WebViewInfo* webview_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
RenderId render_id(guest_process_id, guest_routing_id);
- WebViewInfoMap::iterator iter = web_view_info_map_.find(render_id);
- if (iter != web_view_info_map_.end()) {
- *web_view_info = iter->second;
+ WebViewInfoMap::iterator iter = webview_info_map_.find(render_id);
+ if (iter != webview_info_map_.end()) {
+ *webview_info = iter->second;
return true;
}
return false;
diff --git a/chrome/browser/extensions/extension_renderer_state.h b/chrome/browser/extensions/extension_renderer_state.h
index 04a48bd..8118585 100644
--- a/chrome/browser/extensions/extension_renderer_state.h
+++ b/chrome/browser/extensions/extension_renderer_state.h
@@ -12,6 +12,10 @@
#include "base/basictypes.h"
#include "base/memory/singleton.h"
+namespace chrome {
+class WebViewGuest;
+} // namespace chrome
+
// This class keeps track of renderer state for use on the IO thread. All
// methods should be called on the IO thread except for Init and Shutdown.
class ExtensionRendererState {
@@ -19,7 +23,8 @@
struct WebViewInfo {
int embedder_process_id;
int embedder_routing_id;
- int web_view_instance_id;
+ int guest_instance_id;
+ int instance_id;
};
static ExtensionRendererState* GetInstance();
@@ -32,7 +37,7 @@
// Looks up the information for the embedder <webview> for a given render
// view, if one exists. Called on the IO thread.
bool GetWebViewInfo(int guest_process_id, int guest_routing_id,
- WebViewInfo* web_view_info);
+ WebViewInfo* webview_info);
// Looks up the tab and window ID for a given render view. Returns true
// if we have the IDs in our map. Called on the IO thread.
@@ -43,6 +48,7 @@
class RenderViewHostObserver;
class TabObserver;
friend class TabObserver;
+ friend class chrome::WebViewGuest;
friend struct DefaultSingletonTraits<ExtensionRendererState>;
typedef std::pair<int, int> RenderId;
@@ -61,12 +67,12 @@
// Adds or removes a <webview> guest render process from the set.
void AddWebView(int render_process_host_id, int routing_id,
- const WebViewInfo& web_view_info);
+ const WebViewInfo& webview_info);
void RemoveWebView(int render_process_host_id, int routing_id);
TabObserver* observer_;
TabAndWindowIdMap map_;
- WebViewInfoMap web_view_info_map_;
+ WebViewInfoMap webview_info_map_;
DISALLOW_COPY_AND_ASSIGN(ExtensionRendererState);
};
diff --git a/chrome/browser/webview/webview_guest.cc b/chrome/browser/webview/webview_guest.cc
index 643486b..a073eaa 100644
--- a/chrome/browser/webview/webview_guest.cc
+++ b/chrome/browser/webview/webview_guest.cc
@@ -6,6 +6,7 @@
#include "base/lazy_instance.h"
#include "chrome/browser/extensions/api/web_request/web_request_api.h"
+#include "chrome/browser/extensions/extension_renderer_state.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
@@ -26,46 +27,51 @@
void* profile,
const std::string& extension_id,
int embedder_process_id,
- int web_view_instance_id) {
+ int guest_instance_id) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
- profile, extension_id, embedder_process_id, web_view_instance_id);
+ profile, extension_id, embedder_process_id, guest_instance_id);
}
} // namespace
WebViewGuest::WebViewGuest(WebContents* guest_web_contents,
WebContents* embedder_web_contents,
- const std::string& extension_id)
+ const std::string& extension_id,
+ int webview_instance_id)
: WebContentsObserver(guest_web_contents),
embedder_web_contents_(embedder_web_contents),
extension_id_(extension_id),
embedder_render_process_id_(
embedder_web_contents->GetRenderProcessHost()->GetID()),
profile_(guest_web_contents->GetBrowserContext()),
- instance_id_(guest_web_contents->GetEmbeddedInstanceID()) {
+ guest_instance_id_(guest_web_contents->GetEmbeddedInstanceID()),
+ webview_instance_id_(webview_instance_id) {
webview_profile_map.Get()[profile_].insert(
- std::make_pair(instance_id_, this));
+ std::make_pair(guest_instance_id_, this));
+
+ AddWebViewToExtensionRendererState();
}
// static
-WebViewGuest* WebViewGuest::From(void* profile, int instance_id) {
+WebViewGuest* WebViewGuest::From(void* profile, int guest_instance_id) {
WebViewProfileMap* profile_map = webview_profile_map.Pointer();
WebViewProfileMap::iterator it = profile_map->find(profile);
if (it == profile_map->end())
return NULL;
const WebViewGuestMap& guest_map = it->second;
- WebViewGuestMap::const_iterator guest_it = guest_map.find(instance_id);
+ WebViewGuestMap::const_iterator guest_it = guest_map.find(guest_instance_id);
return guest_it == guest_map.end() ? NULL : guest_it->second;
}
WebViewGuest::~WebViewGuest() {
- webview_profile_map.Get()[profile_].erase(instance_id_);
+ webview_profile_map.Get()[profile_].erase(guest_instance_id_);
if (webview_profile_map.Get()[profile_].empty())
webview_profile_map.Get().erase(profile_);
}
void WebViewGuest::WebContentsDestroyed(WebContents* web_contents) {
+ RemoveWebViewFromExtensionRendererState(web_contents);
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
@@ -73,8 +79,38 @@
&RemoveWebViewEventListenersOnIOThread,
profile_, extension_id_,
embedder_render_process_id_,
- instance_id_));
+ webview_instance_id_));
delete this;
}
+void WebViewGuest::AddWebViewToExtensionRendererState() {
+ ExtensionRendererState::WebViewInfo webview_info;
+ webview_info.embedder_process_id =
+ embedder_web_contents()->GetRenderProcessHost()->GetID();
+ webview_info.embedder_routing_id = embedder_web_contents()->GetRoutingID();
+ webview_info.guest_instance_id = guest_instance_id_;
+ webview_info.instance_id = webview_instance_id_;
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &ExtensionRendererState::AddWebView,
+ base::Unretained(ExtensionRendererState::GetInstance()),
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetRoutingID(),
+ webview_info));
+}
+
+// static
+void WebViewGuest::RemoveWebViewFromExtensionRendererState(
+ WebContents* web_contents) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &ExtensionRendererState::RemoveWebView,
+ base::Unretained(ExtensionRendererState::GetInstance()),
+ web_contents->GetRenderProcessHost()->GetID(),
+ web_contents->GetRoutingID()));
+}
+
} // namespace chrome
diff --git a/chrome/browser/webview/webview_guest.h b/chrome/browser/webview/webview_guest.h
index 135bb68..91dd737 100644
--- a/chrome/browser/webview/webview_guest.h
+++ b/chrome/browser/webview/webview_guest.h
@@ -11,12 +11,17 @@
// A WebViewGuest is a WebContentsObserver on the guest WebContents of a
// <webview> tag. It provides the browser-side implementation of the <webview>
-// API and manages the lifetime of <webview> extension events.
+// API and manages the lifetime of <webview> extension events. WebViewGuest is
+// created on attachment. That is, when a guest WebContents is associated with
+// a particular embedder WebContents. This happens on either initial navigation
+// or through the use of the New Window API, when a new window is attached to
+// a particular <webview>.
class WebViewGuest : public content::WebContentsObserver {
public:
WebViewGuest(content::WebContents* guest_web_contents,
content::WebContents* embedder_web_contents,
- const std::string& extension_id);
+ const std::string& extension_id,
+ int webview_instance_id);
static WebViewGuest* From(void* profile, int instance_id);
@@ -28,18 +33,29 @@
return WebContentsObserver::web_contents();
}
+ int instance_id() const { return webview_instance_id_; }
+
private:
virtual ~WebViewGuest();
virtual void WebContentsDestroyed(
content::WebContents* web_contents) OVERRIDE;
+ void AddWebViewToExtensionRendererState();
+ static void RemoveWebViewFromExtensionRendererState(
+ content::WebContents* web_contents);
+
content::WebContents* embedder_web_contents_;
const std::string extension_id_;
const int embedder_render_process_id_;
// Profile and instance ID are cached here because |web_contents()| is
// null on destruction.
void* profile_;
- const int instance_id_;
+ // |guest_instance_id_| is a profile-wide unique identifier for a guest
+ // WebContents.
+ const int guest_instance_id_;
+ // |webview_instance_id_| is an identifier that's unique within a particular
+ // embedder RenderView for a particular <webview> instance.
+ int webview_instance_id_;
DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
};
diff --git a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
index 262fa21..65c3a5f 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
@@ -230,6 +230,42 @@
embedder.setUpNewWindowRequest_(webview, 'about:blank', '', testName);
};
+embedder.tests.testNewWindowWebRequest =
+ function testNewWindowWebRequest() {
+ var testName = 'testNewWindowExecuteScript';
+ var webview = embedder.setUpGuest_('foobar');
+
+ var onNewWindow = function(e) {
+ chrome.test.log('Embedder notified on newwindow');
+ embedder.assertCorrectEvent_(e, '');
+
+ var newwebview = document.createElement('webview');
+ document.querySelector('#webview-tag-container').appendChild(newwebview);
+ var calledWebRequestEvent = false;
+ e.preventDefault();
+ // The WebRequest API is not exposed until the <webview> MutationObserver
+ // picks up the <webview> in the DOM. Thus, we cannot immediately access
+ // WebRequest API.
+ window.setTimeout(function() {
+ newwebview.onBeforeRequest.addListener(function(e) {
+ if (!calledWebRequestEvent) {
+ calledWebRequestEvent = true;
+ chrome.test.succeed();
+ }
+ }, { urls: ['<all_urls>'] }, ['blocking']);
+ try {
+ e.window.attach(newwebview);
+ } catch (e) {
+ chrome.test.fail();
+ }
+ }, 0);
+ };
+ webview.addEventListener('newwindow', onNewWindow);
+
+ // Load a new window with the given name.
+ embedder.setUpNewWindowRequest_(webview, 'guest.html', '', testName);
+};
+
onload = function() {
chrome.test.getConfig(function(config) {
embedder.setUp(config);
@@ -239,7 +275,8 @@
embedder.tests.testNoName,
embedder.tests.testNewWindowRedirect,
embedder.tests.testNewWindowClose,
- embedder.tests.testNewWindowExecuteScript
+ embedder.tests.testNewWindowExecuteScript,
+ embedder.tests.testNewWindowWebRequest
]);
});
};