root/components/storage_monitor/storage_monitor.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright 2014 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 COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_
#define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_

#include <map>
#include <string>
#include <vector>

#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "components/storage_monitor/storage_info.h"

class MediaFileSystemRegistryTest;
class MediaGalleriesPlatformAppBrowserTest;
class SystemStorageApiTest;
class SystemStorageEjectApiTest;

namespace device {
class MediaTransferProtocolManager;
}

namespace storage_monitor {

class RemovableStorageObserver;
class TransientDeviceIds;

// Base class for platform-specific instances watching for removable storage
// attachments/detachments.
// Lifecycle contracts: This class is created in the browser process
// before the profile is initialized, so listeners can be
// created during profile construction. The platform-specific initialization,
// which can lead to calling registered listeners with notifications of
// attached volumes, are done lazily at first use through the async
// |EnsureInitialized()| method. That must be done before any of the registered
// listeners will receive updates or calls to other API methods return
// meaningful results.
// A post-initialization |GetAttachedStorage()| call coupled with a
// registered listener will receive a complete set, albeit potentially with
// duplicates. This is because there's no tracking between when listeners were
// registered and the state of initialization, and the fact that platforms
// behave differently in how these notifications are provided.
class StorageMonitor {
 public:
  // This interface is provided to generators of storage notifications.
  class Receiver {
   public:
    virtual ~Receiver();

    virtual void ProcessAttach(const StorageInfo& info) = 0;
    virtual void ProcessDetach(const std::string& id) = 0;
    virtual void MarkInitialized() = 0;
  };

  // Status codes for the result of an EjectDevice() call.
  enum EjectStatus {
    EJECT_OK,
    EJECT_IN_USE,
    EJECT_NO_SUCH_DEVICE,
    EJECT_FAILURE
  };

  // Instantiates the StorageMonitor singleton. This function does not
  // guarantee the complete initialization of the object. For that, see
  // |EnsureInitialized|.
  static void Create();

  // Destroys the StorageMonitor singleton.
  static void Destroy();

  // Returns a pointer to an object owned by BrowserProcess, with lifetime
  // starting before main message loop start, and ending after main message loop
  // shutdown. Called outside it's lifetime (or with no browser process),
  // returns NULL.
  static StorageMonitor* GetInstance();

  static void SetStorageMonitorForTesting(
      scoped_ptr<StorageMonitor> storage_monitor);

  virtual ~StorageMonitor();

  // Ensures that the storage monitor is initialized. The provided callback, if
  // non-null, will be called when initialization is complete. If initialization
  // has already completed, this callback will be invoked within the calling
  // stack. Before the callback is run, calls to |GetAllAvailableStorages| and
  // |GetStorageInfoForPath| may not return the correct results. In addition,
  // registered observers will not be notified on device attachment/detachment.
  // Should be invoked on the UI thread; callbacks will be run on the UI thread.
  void EnsureInitialized(base::Closure callback);

  // Return true if the storage monitor has already been initialized.
  bool IsInitialized() const;

  // Finds the device that contains |path| and populates |device_info|.
  // Should be able to handle any path on the local system, not just removable
  // storage. Returns false if unable to find the device.
  virtual bool GetStorageInfoForPath(
      const base::FilePath& path,
      StorageInfo* device_info) const = 0;

// TODO(gbillock): make this either unnecessary (implementation-specific) or
// platform-independent.
#if defined(OS_WIN)
  // Gets the MTP device storage information specified by |storage_device_id|.
  // On success, returns true and fills in |device_location| with device
  // interface details and |storage_object_id| with the string ID that
  // uniquely identifies the object on the device. This ID need not be
  // persistent across sessions.
  virtual bool GetMTPStorageInfoFromDeviceId(
      const std::string& storage_device_id,
      base::string16* device_location,
      base::string16* storage_object_id) const = 0;
#endif

#if defined(OS_LINUX)
  virtual device::MediaTransferProtocolManager*
      media_transfer_protocol_manager() = 0;
#endif

  // Returns information for all known storages on the system,
  // including fixed and removable storages.
  std::vector<StorageInfo> GetAllAvailableStorages() const;

  void AddObserver(RemovableStorageObserver* obs);
  void RemoveObserver(RemovableStorageObserver* obs);

  std::string GetTransientIdForDeviceId(const std::string& device_id);
  std::string GetDeviceIdForTransientId(const std::string& transient_id) const;

  virtual void EjectDevice(
      const std::string& device_id,
      base::Callback<void(EjectStatus)> callback);

 protected:
  friend class ::MediaFileSystemRegistryTest;
  friend class ::MediaGalleriesPlatformAppBrowserTest;
  friend class ::SystemStorageApiTest;
  friend class ::SystemStorageEjectApiTest;

  StorageMonitor();

  virtual Receiver* receiver() const;

  // Called to initialize the storage monitor.
  virtual void Init() = 0;

  // Called by subclasses to mark the storage monitor as
  // fully initialized. Must be called on the UI thread.
  void MarkInitialized();

 private:
  // Internal method for creating platform specific StorageMonitor.
  static StorageMonitor* CreateInternal();

  class ReceiverImpl;
  friend class ReceiverImpl;

  // Key: device id.
  typedef std::map<std::string, StorageInfo> StorageMap;

  void ProcessAttach(const StorageInfo& storage);
  void ProcessDetach(const std::string& id);

  scoped_ptr<Receiver> receiver_;

  scoped_refptr<ObserverListThreadSafe<RemovableStorageObserver> >
      observer_list_;

  // Used to make sure we call initialize from the same thread as creation.
  base::ThreadChecker thread_checker_;

  bool initializing_;
  bool initialized_;
  std::vector<base::Closure> on_initialize_callbacks_;

  // For manipulating storage_map_ structure.
  mutable base::Lock storage_lock_;

  // Map of all known storage devices,including fixed and removable storages.
  StorageMap storage_map_;

  scoped_ptr<TransientDeviceIds> transient_device_ids_;
};

}  // namespace storage_monitor

#endif  // COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_H_

/* [<][>][^][v][top][bottom][index][help] */