// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/extension_tab_id_map.h" #include "content/browser/browser_thread.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/renderer_host/render_process_host.h" #include "content/common/notification_registrar.h" #include "content/common/notification_observer.h" #include "content/common/notification_service.h" // ExtensionTabIdMap is a Singleton, so it doesn't need refcounting. DISABLE_RUNNABLE_METHOD_REFCOUNT(ExtensionTabIdMap); // // ExtensionTabIdMap::TabObserver // // This class listens for notifications about new and closed tabs on the UI // thread, and notifies the ExtensionTabIdMap on the IO thread. It should only // ever be accessed on the UI thread. class ExtensionTabIdMap::TabObserver : public NotificationObserver { public: TabObserver(); ~TabObserver(); private: // NotificationObserver interface. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); NotificationRegistrar registrar_; }; ExtensionTabIdMap::TabObserver::TabObserver() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB, NotificationService::AllSources()); registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::TAB_PARENTED, NotificationService::AllSources()); } ExtensionTabIdMap::TabObserver::~TabObserver() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); } void ExtensionTabIdMap::TabObserver::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: { TabContents* contents = Source<TabContents>(source).ptr(); RenderViewHost* host = Details<RenderViewHost>(details).ptr(); // TODO(mpcmoplete): How can we tell if window_id is bogus? It may not // have been set yet. BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( ExtensionTabIdMap::GetInstance(), &ExtensionTabIdMap::SetTabAndWindowId, host->process()->id(), host->routing_id(), contents->controller().session_id().id(), contents->controller().window_id().id())); break; } case NotificationType::TAB_PARENTED: { NavigationController* controller = Source<NavigationController>(source).ptr(); RenderViewHost* host = controller->tab_contents()->render_view_host(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( ExtensionTabIdMap::GetInstance(), &ExtensionTabIdMap::SetTabAndWindowId, host->process()->id(), host->routing_id(), controller->session_id().id(), controller->window_id().id())); break; } case NotificationType::RENDER_VIEW_HOST_DELETED: { RenderViewHost* host = Source<RenderViewHost>(source).ptr(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( ExtensionTabIdMap::GetInstance(), &ExtensionTabIdMap::ClearTabAndWindowId, host->process()->id(), host->routing_id())); break; } default: NOTREACHED(); return; } } // // ExtensionTabIdMap // ExtensionTabIdMap::ExtensionTabIdMap() : observer_(NULL) { } ExtensionTabIdMap::~ExtensionTabIdMap() { } // static ExtensionTabIdMap* ExtensionTabIdMap::GetInstance() { return Singleton<ExtensionTabIdMap>::get(); } void ExtensionTabIdMap::Init() { observer_ = new TabObserver; } void ExtensionTabIdMap::Shutdown() { delete observer_; } void ExtensionTabIdMap::SetTabAndWindowId( int render_process_host_id, int routing_id, int tab_id, int window_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); RenderId render_id(render_process_host_id, routing_id); map_[render_id] = TabAndWindowId(tab_id, window_id); } void ExtensionTabIdMap::ClearTabAndWindowId( int render_process_host_id, int routing_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); RenderId render_id(render_process_host_id, routing_id); map_.erase(render_id); } bool ExtensionTabIdMap::GetTabAndWindowId( int render_process_host_id, int routing_id, int* tab_id, int* window_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); RenderId render_id(render_process_host_id, routing_id); TabAndWindowIdMap::iterator iter = map_.find(render_id); if (iter != map_.end()) { *tab_id = iter->second.first; *window_id = iter->second.second; return true; } return false; }