// 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__