C++程序  |  157行  |  5.54 KB

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