• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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.
4 
5 #include "chrome/browser/extensions/extension_tab_id_map.h"
6 
7 #include "content/browser/browser_thread.h"
8 #include "content/browser/tab_contents/tab_contents.h"
9 #include "content/browser/renderer_host/render_view_host.h"
10 #include "content/browser/renderer_host/render_process_host.h"
11 #include "content/common/notification_registrar.h"
12 #include "content/common/notification_observer.h"
13 #include "content/common/notification_service.h"
14 
15 // ExtensionTabIdMap is a Singleton, so it doesn't need refcounting.
16 DISABLE_RUNNABLE_METHOD_REFCOUNT(ExtensionTabIdMap);
17 
18 //
19 // ExtensionTabIdMap::TabObserver
20 //
21 
22 // This class listens for notifications about new and closed tabs on the UI
23 // thread, and notifies the ExtensionTabIdMap on the IO thread. It should only
24 // ever be accessed on the UI thread.
25 class ExtensionTabIdMap::TabObserver : public NotificationObserver {
26  public:
27   TabObserver();
28   ~TabObserver();
29 
30  private:
31   // NotificationObserver interface.
32   virtual void Observe(NotificationType type,
33                        const NotificationSource& source,
34                        const NotificationDetails& details);
35 
36   NotificationRegistrar registrar_;
37 };
38 
TabObserver()39 ExtensionTabIdMap::TabObserver::TabObserver() {
40   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
41   registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
42                  NotificationService::AllSources());
43   registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
44                  NotificationService::AllSources());
45   registrar_.Add(this, NotificationType::TAB_PARENTED,
46                  NotificationService::AllSources());
47 }
48 
~TabObserver()49 ExtensionTabIdMap::TabObserver::~TabObserver() {
50   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51 }
52 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)53 void ExtensionTabIdMap::TabObserver::Observe(
54     NotificationType type, const NotificationSource& source,
55     const NotificationDetails& details) {
56   switch (type.value) {
57     case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
58       TabContents* contents = Source<TabContents>(source).ptr();
59       RenderViewHost* host = Details<RenderViewHost>(details).ptr();
60       // TODO(mpcmoplete): How can we tell if window_id is bogus? It may not
61       // have been set yet.
62       BrowserThread::PostTask(
63           BrowserThread::IO, FROM_HERE,
64           NewRunnableMethod(
65               ExtensionTabIdMap::GetInstance(),
66               &ExtensionTabIdMap::SetTabAndWindowId,
67               host->process()->id(), host->routing_id(),
68               contents->controller().session_id().id(),
69               contents->controller().window_id().id()));
70       break;
71     }
72     case NotificationType::TAB_PARENTED: {
73       NavigationController* controller =
74           Source<NavigationController>(source).ptr();
75       RenderViewHost* host = controller->tab_contents()->render_view_host();
76       BrowserThread::PostTask(
77           BrowserThread::IO, FROM_HERE,
78           NewRunnableMethod(
79               ExtensionTabIdMap::GetInstance(),
80               &ExtensionTabIdMap::SetTabAndWindowId,
81               host->process()->id(), host->routing_id(),
82               controller->session_id().id(),
83               controller->window_id().id()));
84       break;
85     }
86     case NotificationType::RENDER_VIEW_HOST_DELETED: {
87       RenderViewHost* host = Source<RenderViewHost>(source).ptr();
88       BrowserThread::PostTask(
89           BrowserThread::IO, FROM_HERE,
90           NewRunnableMethod(
91               ExtensionTabIdMap::GetInstance(),
92               &ExtensionTabIdMap::ClearTabAndWindowId,
93               host->process()->id(), host->routing_id()));
94       break;
95     }
96     default:
97       NOTREACHED();
98       return;
99   }
100 }
101 
102 //
103 // ExtensionTabIdMap
104 //
105 
ExtensionTabIdMap()106 ExtensionTabIdMap::ExtensionTabIdMap() : observer_(NULL) {
107 }
108 
~ExtensionTabIdMap()109 ExtensionTabIdMap::~ExtensionTabIdMap() {
110 }
111 
112 // static
GetInstance()113 ExtensionTabIdMap* ExtensionTabIdMap::GetInstance() {
114   return Singleton<ExtensionTabIdMap>::get();
115 }
116 
Init()117 void ExtensionTabIdMap::Init() {
118   observer_ = new TabObserver;
119 }
120 
Shutdown()121 void ExtensionTabIdMap::Shutdown() {
122   delete observer_;
123 }
124 
SetTabAndWindowId(int render_process_host_id,int routing_id,int tab_id,int window_id)125 void ExtensionTabIdMap::SetTabAndWindowId(
126     int render_process_host_id, int routing_id, int tab_id, int window_id) {
127   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
128   RenderId render_id(render_process_host_id, routing_id);
129   map_[render_id] = TabAndWindowId(tab_id, window_id);
130 }
131 
ClearTabAndWindowId(int render_process_host_id,int routing_id)132 void ExtensionTabIdMap::ClearTabAndWindowId(
133     int render_process_host_id, int routing_id) {
134   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
135   RenderId render_id(render_process_host_id, routing_id);
136   map_.erase(render_id);
137 }
138 
GetTabAndWindowId(int render_process_host_id,int routing_id,int * tab_id,int * window_id)139 bool ExtensionTabIdMap::GetTabAndWindowId(
140     int render_process_host_id, int routing_id, int* tab_id, int* window_id) {
141   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
142   RenderId render_id(render_process_host_id, routing_id);
143   TabAndWindowIdMap::iterator iter = map_.find(render_id);
144   if (iter != map_.end()) {
145     *tab_id = iter->second.first;
146     *window_id = iter->second.second;
147     return true;
148   }
149   return false;
150 }
151