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#ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__
6#define CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__
7#pragma once
8
9#include <map>
10
11#include "base/basictypes.h"
12#include "content/common/notification_observer.h"
13#include "content/common/notification_registrar.h"
14#include "content/common/notification_source.h"
15#include "content/common/notification_type.h"
16#include "ipc/ipc_message.h"
17
18// Template trick so that AutomationResourceTracker can be used with non-pointer
19// types.
20template <class T>
21struct AutomationResourceTraits {
22  typedef T ValueType;
23};
24
25template <class T>
26struct AutomationResourceTraits<T*> {
27  typedef T ValueType;
28};
29
30// This class exists for the sole purpose of allowing some of the implementation
31// of AutomationResourceTracker to live in a .cc file.
32class AutomationResourceTrackerImpl {
33 public:
34  explicit AutomationResourceTrackerImpl(IPC::Message::Sender* sender);
35  virtual ~AutomationResourceTrackerImpl();
36
37 protected:
38  // These need to be implemented in AutomationResourceTracker,
39  // since it needs to call the subclass's type-specific notification
40  // registration functions.
41  virtual void AddObserverTypeProxy(const void* resource) = 0;
42  virtual void RemoveObserverTypeProxy(const void* resource) = 0;
43
44  int AddImpl(const void* resource);
45  void RemoveImpl(const void* resource);
46  int GenerateHandle();
47  bool ContainsResourceImpl(const void* resource);
48  bool ContainsHandleImpl(int handle);
49  const void* GetResourceImpl(int handle);
50  int GetHandleImpl(const void* resource);
51  void HandleCloseNotification(const void* resource);
52
53 private:
54  typedef std::map<const void*, int> ResourceToHandleMap;
55  typedef std::map<int, const void*> HandleToResourceMap;
56
57  ResourceToHandleMap resource_to_handle_;
58  HandleToResourceMap handle_to_resource_;
59
60  IPC::Message::Sender* sender_;
61
62  DISALLOW_COPY_AND_ASSIGN(AutomationResourceTrackerImpl);
63};
64
65// This template defines a superclass for an object that wants to track
66// a particular kind of application resource (like windows or tabs) for
67// automation purposes.  The only things that a subclass should need to
68// define are AddObserver and RemoveObserver for the given resource's
69// close notifications.
70template <class T>
71class AutomationResourceTracker : public AutomationResourceTrackerImpl,
72                                  public NotificationObserver {
73 public:
74  explicit AutomationResourceTracker(IPC::Message::Sender* automation)
75    : AutomationResourceTrackerImpl(automation) {}
76
77  // The implementations for these should call the NotificationService
78  // to add and remove this object as an observer for the appropriate
79  // resource closing notification.
80  virtual void AddObserver(T resource) = 0;
81  virtual void RemoveObserver(T resource) = 0;
82
83  // Adds the given resource to this tracker, and returns a handle that
84  // can be used to refer to that resource.  If the resource is already
85  // being tracked, the handle may be the same as one returned previously.
86  int Add(T resource) {
87    return AddImpl(resource);
88  }
89
90  // Removes the given resource from this tracker.  If the resource is not
91  // currently present in the tracker, this is a no-op.
92  void Remove(T resource) {
93    RemoveImpl(resource);
94  }
95
96  // Returns true if this tracker currently tracks the resource pointed to
97  // by the parameter.
98  bool ContainsResource(T resource) {
99    return ContainsResourceImpl(resource);
100  }
101
102  // Returns true if this tracker currently tracks the given handle.
103  bool ContainsHandle(int handle) {
104    return ContainsHandleImpl(handle);
105  }
106
107  // Returns the resource pointer associated with a given handle, or NULL
108  // if that handle is not present in the mapping.
109  // The casts here allow this to compile with both T = Foo and T = const Foo.
110  T GetResource(int handle) {
111    return static_cast<T>(const_cast<void*>(GetResourceImpl(handle)));
112  }
113
114  // Returns the handle associated with a given resource pointer, or 0 if
115  // the resource is not currently in the mapping.
116  int GetHandle(T resource) {
117    return GetHandleImpl(resource);
118  }
119
120  // NotificationObserver implementation--the only thing that this tracker
121  // does in response to notifications is to tell the AutomationProxy
122  // that the associated handle is now invalid.
123  virtual void Observe(NotificationType type,
124                       const NotificationSource& source,
125                       const NotificationDetails& details) {
126     T resource =
127        Source<typename AutomationResourceTraits<T>::ValueType>(source).ptr();
128
129     CloseResource(resource);
130  }
131
132 protected:
133  // Removes |resource| from the tracker, and handles sending the close
134  // notification back to the client. This typically should not be called
135  // directly, unless there is no appropriate notification available
136  // for the resource type.
137  void CloseResource(T resource) {
138    HandleCloseNotification(resource);
139  }
140
141  // These proxy calls from the base Impl class to the template's subclss.
142  // The casts here allow this to compile with both T = Foo and T = const Foo.
143  virtual void AddObserverTypeProxy(const void* resource) {
144    AddObserver(static_cast<T>(const_cast<void*>(resource)));
145  }
146  virtual void RemoveObserverTypeProxy(const void* resource) {
147    RemoveObserver(static_cast<T>(const_cast<void*>(resource)));
148  }
149
150  NotificationRegistrar registrar_;
151
152 private:
153  DISALLOW_COPY_AND_ASSIGN(AutomationResourceTracker);
154};
155
156#endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_TRACKER_H__
157