// 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__ #include #include "base/basictypes.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "ipc/ipc_sender.h" // Template trick so that AutomationResourceTracker can be used with non-pointer // types. template struct AutomationResourceTraits { typedef T ValueType; }; template struct AutomationResourceTraits { 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::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 ResourceToHandleMap; typedef std::map HandleToResourceMap; ResourceToHandleMap resource_to_handle_; HandleToResourceMap handle_to_resource_; IPC::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 AutomationResourceTracker : public AutomationResourceTrackerImpl, public content::NotificationObserver { public: explicit AutomationResourceTracker(IPC::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(const_cast(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); } // content::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(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { T resource = content::Source:: 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(const_cast(resource))); } virtual void RemoveObserverTypeProxy(const void* resource) { RemoveObserver(static_cast(const_cast(resource))); } content::NotificationRegistrar registrar_; private: DISALLOW_COPY_AND_ASSIGN(AutomationResourceTracker); }; #endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__