Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / extension_renderer_state.cc
blob1792b603e0ab4ea9beafc72f256285dbf2007209
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_renderer_state.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/sessions/session_tab_helper.h"
11 #include "chrome/browser/tab_contents/retargeting_details.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/navigation_details.h"
14 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_types.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/resource_request_info.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_observer.h"
23 #include "content/public/common/process_type.h"
25 using content::BrowserThread;
26 using content::RenderProcessHost;
27 using content::RenderViewHost;
28 using content::WebContents;
31 // ExtensionRendererState::RenderViewHostObserver
34 class ExtensionRendererState::RenderViewHostObserver
35 : public content::WebContentsObserver {
36 public:
37 RenderViewHostObserver(RenderViewHost* host, WebContents* web_contents)
38 : content::WebContentsObserver(web_contents),
39 render_view_host_(host) {
42 void RenderViewDeleted(content::RenderViewHost* host) override {
43 if (host != render_view_host_)
44 return;
45 BrowserThread::PostTask(
46 BrowserThread::IO, FROM_HERE,
47 base::Bind(
48 &ExtensionRendererState::ClearTabAndWindowId,
49 base::Unretained(ExtensionRendererState::GetInstance()),
50 host->GetProcess()->GetID(), host->GetRoutingID()));
52 delete this;
55 private:
56 RenderViewHost* render_view_host_;
58 DISALLOW_COPY_AND_ASSIGN(RenderViewHostObserver);
62 // ExtensionRendererState::TabObserver
65 // This class listens for notifications about changes in renderer state on the
66 // UI thread, and notifies the ExtensionRendererState on the IO thread. It
67 // should only ever be accessed on the UI thread.
68 class ExtensionRendererState::TabObserver
69 : public content::NotificationObserver {
70 public:
71 TabObserver();
72 ~TabObserver() override;
74 private:
75 // content::NotificationObserver interface.
76 void Observe(int type,
77 const content::NotificationSource& source,
78 const content::NotificationDetails& details) override;
80 content::NotificationRegistrar registrar_;
83 ExtensionRendererState::TabObserver::TabObserver() {
84 DCHECK_CURRENTLY_ON(BrowserThread::UI);
85 registrar_.Add(this,
86 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
87 content::NotificationService::AllBrowserContextsAndSources());
88 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED,
89 content::NotificationService::AllBrowserContextsAndSources());
90 registrar_.Add(this, chrome::NOTIFICATION_RETARGETING,
91 content::NotificationService::AllBrowserContextsAndSources());
94 ExtensionRendererState::TabObserver::~TabObserver() {
95 DCHECK_CURRENTLY_ON(BrowserThread::UI);
98 void ExtensionRendererState::TabObserver::Observe(
99 int type, const content::NotificationSource& source,
100 const content::NotificationDetails& details) {
101 switch (type) {
102 case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: {
103 WebContents* web_contents = content::Source<WebContents>(source).ptr();
104 SessionTabHelper* session_tab_helper =
105 SessionTabHelper::FromWebContents(web_contents);
106 if (!session_tab_helper)
107 return;
108 RenderViewHost* host = content::Details<RenderViewHost>(details).ptr();
109 // TODO(mpcomplete): How can we tell if window_id is bogus? It may not
110 // have been set yet.
111 BrowserThread::PostTask(
112 BrowserThread::IO, FROM_HERE,
113 base::Bind(
114 &ExtensionRendererState::SetTabAndWindowId,
115 base::Unretained(ExtensionRendererState::GetInstance()),
116 host->GetProcess()->GetID(), host->GetRoutingID(),
117 session_tab_helper->session_id().id(),
118 session_tab_helper->window_id().id()));
120 // The observer deletes itself.
121 new ExtensionRendererState::RenderViewHostObserver(host, web_contents);
123 break;
125 case chrome::NOTIFICATION_TAB_PARENTED: {
126 WebContents* web_contents = content::Source<WebContents>(source).ptr();
127 SessionTabHelper* session_tab_helper =
128 SessionTabHelper::FromWebContents(web_contents);
129 if (!session_tab_helper)
130 return;
131 RenderViewHost* host = web_contents->GetRenderViewHost();
132 BrowserThread::PostTask(
133 BrowserThread::IO, FROM_HERE,
134 base::Bind(
135 &ExtensionRendererState::SetTabAndWindowId,
136 base::Unretained(ExtensionRendererState::GetInstance()),
137 host->GetProcess()->GetID(), host->GetRoutingID(),
138 session_tab_helper->session_id().id(),
139 session_tab_helper->window_id().id()));
140 break;
142 case chrome::NOTIFICATION_RETARGETING: {
143 RetargetingDetails* retargeting_details =
144 content::Details<RetargetingDetails>(details).ptr();
145 WebContents* web_contents = retargeting_details->target_web_contents;
146 SessionTabHelper* session_tab_helper =
147 SessionTabHelper::FromWebContents(web_contents);
148 if (!session_tab_helper)
149 return;
150 RenderViewHost* host = web_contents->GetRenderViewHost();
151 BrowserThread::PostTask(
152 BrowserThread::IO, FROM_HERE,
153 base::Bind(
154 &ExtensionRendererState::SetTabAndWindowId,
155 base::Unretained(ExtensionRendererState::GetInstance()),
156 host->GetProcess()->GetID(), host->GetRoutingID(),
157 session_tab_helper->session_id().id(),
158 session_tab_helper->window_id().id()));
159 break;
161 default:
162 NOTREACHED();
163 return;
168 // ExtensionRendererState
171 ExtensionRendererState::ExtensionRendererState() : observer_(NULL) {
174 ExtensionRendererState::~ExtensionRendererState() {
177 // static
178 ExtensionRendererState* ExtensionRendererState::GetInstance() {
179 return base::Singleton<ExtensionRendererState>::get();
182 void ExtensionRendererState::Init() {
183 observer_ = new TabObserver;
186 void ExtensionRendererState::Shutdown() {
187 delete observer_;
190 void ExtensionRendererState::SetTabAndWindowId(
191 int render_process_host_id, int routing_id, int tab_id, int window_id) {
192 DCHECK_CURRENTLY_ON(BrowserThread::IO);
193 RenderId render_id(render_process_host_id, routing_id);
194 map_[render_id] = TabAndWindowId(tab_id, window_id);
197 void ExtensionRendererState::ClearTabAndWindowId(
198 int render_process_host_id, int routing_id) {
199 DCHECK_CURRENTLY_ON(BrowserThread::IO);
200 RenderId render_id(render_process_host_id, routing_id);
201 map_.erase(render_id);
204 bool ExtensionRendererState::GetTabAndWindowId(
205 const content::ResourceRequestInfo* info, int* tab_id, int* window_id) {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO);
207 int render_process_id;
208 if (info->GetProcessType() == content::PROCESS_TYPE_PLUGIN) {
209 render_process_id = info->GetOriginPID();
210 } else {
211 render_process_id = info->GetChildID();
213 int render_view_id = info->GetRouteID();
214 RenderId render_id(render_process_id, render_view_id);
215 TabAndWindowIdMap::iterator iter = map_.find(render_id);
216 if (iter != map_.end()) {
217 *tab_id = iter->second.first;
218 *window_id = iter->second.second;
219 return true;
221 return false;