// 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. #ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__ #define CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__ #pragma once #include <map> #include "base/basictypes.h" #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "content/common/notification_source.h" #include "content/common/notification_type.h" #include "ipc/ipc_message.h" // Template trick so that AutomationResourceTracker can be used with non-pointer // types. template <class T> struct AutomationResourceTraits { typedef T ValueType; }; template <class T> struct AutomationResourceTraits<T*> { typedef T ValueType; }; // This class exists for the sole purpose of allowing some of the implementation // of AutomationResourceTracker to live in a .cc file. class AutomationResourceTrackerImpl { public: explicit AutomationResourceTrackerImpl(IPC::Message::Sender* sender); virtual ~AutomationResourceTrackerImpl(); protected: // These need to be implemented in AutomationResourceTracker, // since it needs to call the subclass's type-specific notification // registration functions. virtual void AddObserverTypeProxy(const void* resource) = 0; virtual void RemoveObserverTypeProxy(const void* resource) = 0; int AddImpl(const void* resource); void RemoveImpl(const void* resource); int GenerateHandle(); bool ContainsResourceImpl(const void* resource); bool ContainsHandleImpl(int handle); const void* GetResourceImpl(int handle); int GetHandleImpl(const void* resource); void HandleCloseNotification(const void* resource); private: typedef std::map<const void*, int> ResourceToHandleMap; typedef std::map<int, const void*> HandleToResourceMap; ResourceToHandleMap resource_to_handle_; HandleToResourceMap handle_to_resource_; IPC::Message::Sender* sender_; DISALLOW_COPY_AND_ASSIGN(AutomationResourceTrackerImpl); }; // This template defines a superclass for an object that wants to track // a particular kind of application resource (like windows or tabs) for // automation purposes. The only things that a subclass should need to // define are AddObserver and RemoveObserver for the given resource's // close notifications. template <class T> class AutomationResourceTracker : public AutomationResourceTrackerImpl, public NotificationObserver { public: explicit AutomationResourceTracker(IPC::Message::Sender* automation) : AutomationResourceTrackerImpl(automation) {} // The implementations for these should call the NotificationService // to add and remove this object as an observer for the appropriate // resource closing notification. virtual void AddObserver(T resource) = 0; virtual void RemoveObserver(T resource) = 0; // Adds the given resource to this tracker, and returns a handle that // can be used to refer to that resource. If the resource is already // being tracked, the handle may be the same as one returned previously. int Add(T resource) { return AddImpl(resource); } // Removes the given resource from this tracker. If the resource is not // currently present in the tracker, this is a no-op. void Remove(T resource) { RemoveImpl(resource); } // Returns true if this tracker currently tracks the resource pointed to // by the parameter. bool ContainsResource(T resource) { return ContainsResourceImpl(resource); } // Returns true if this tracker currently tracks the given handle. bool ContainsHandle(int handle) { return ContainsHandleImpl(handle); } // Returns the resource pointer associated with a given handle, or NULL // if that handle is not present in the mapping. // The casts here allow this to compile with both T = Foo and T = const Foo. T GetResource(int handle) { return static_cast<T>(const_cast<void*>(GetResourceImpl(handle))); } // Returns the handle associated with a given resource pointer, or 0 if // the resource is not currently in the mapping. int GetHandle(T resource) { return GetHandleImpl(resource); } // NotificationObserver implementation--the only thing that this tracker // does in response to notifications is to tell the AutomationProxy // that the associated handle is now invalid. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { T resource = Source<typename AutomationResourceTraits<T>::ValueType>(source).ptr(); CloseResource(resource); } protected: // Removes |resource| from the tracker, and handles sending the close // notification back to the client. This typically should not be called // directly, unless there is no appropriate notification available // for the resource type. void CloseResource(T resource) { HandleCloseNotification(resource); } // These proxy calls from the base Impl class to the template's subclss. // The casts here allow this to compile with both T = Foo and T = const Foo. virtual void AddObserverTypeProxy(const void* resource) { AddObserver(static_cast<T>(const_cast<void*>(resource))); } virtual void RemoveObserverTypeProxy(const void* resource) { RemoveObserver(static_cast<T>(const_cast<void*>(resource))); } NotificationRegistrar registrar_; private: DISALLOW_COPY_AND_ASSIGN(AutomationResourceTracker); }; #endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__