blob: 57073a15a363a8e0573457d23fff76848b0a08d2 [file] [log] [blame]
// Copyright (c) 2012 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_CHROMEOS_EXTENSIONS_FILE_BROWSER_EVENT_ROUTER_H_
#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_BROWSER_EVENT_ROUTER_H_
#include <map>
#include <set>
#include <string>
#include "base/files/file_path_watcher.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/gdata/drive_file_system_interface.h"
#include "chrome/browser/chromeos/gdata/drive_service_interface.h"
#include "chrome/browser/profiles/refcounted_profile_keyed_service.h"
#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_source.h"
class FileBrowserNotifications;
class PrefChangeRegistrar;
class Profile;
// Monitors changes in disk mounts, network connection state and preferences
// affecting File Manager. Dispatches appropriate File Browser events.
class FileBrowserEventRouter
: public RefcountedProfileKeyedService,
public chromeos::disks::DiskMountManager::Observer,
public chromeos::NetworkLibrary::NetworkManagerObserver,
public content::NotificationObserver,
public gdata::DriveServiceObserver,
public gdata::DriveFileSystemInterface::Observer {
public:
// RefcountedProfileKeyedService overrides.
virtual void ShutdownOnUIThread() OVERRIDE;
// Starts observing file system change events. Currently only
// CrosDisksClient events are being observed.
void ObserveFileSystemEvents();
// File watch setup routines.
bool AddFileWatch(const FilePath& file_path,
const FilePath& virtual_path,
const std::string& extension_id);
void RemoveFileWatch(const FilePath& file_path,
const std::string& extension_id);
// Mounts Drive on File browser. |callback| will be called after raising a
// mount request event to file manager on JS-side.
void MountDrive(const base::Closure& callback);
// CrosDisksClient::Observer overrides.
virtual void DiskChanged(chromeos::disks::DiskMountManagerEventType event,
const chromeos::disks::DiskMountManager::Disk* disk)
OVERRIDE;
virtual void DeviceChanged(chromeos::disks::DiskMountManagerEventType event,
const std::string& device_path) OVERRIDE;
virtual void MountCompleted(
chromeos::disks::DiskMountManager::MountEvent event_type,
chromeos::MountError error_code,
const chromeos::disks::DiskMountManager::MountPointInfo& mount_info)
OVERRIDE;
// chromeos::NetworkLibrary::NetworkManagerObserver override.
virtual void OnNetworkManagerChanged(
chromeos::NetworkLibrary* network_library) OVERRIDE;
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// gdata::DriveServiceObserver overrides.
virtual void OnProgressUpdate(
const gdata::OperationProgressStatusList& list) OVERRIDE;
virtual void OnAuthenticationFailed() OVERRIDE;
// gdata::DriveFileSystemInterface::Observer overrides.
virtual void OnDirectoryChanged(const FilePath& directory_path) OVERRIDE;
virtual void OnDocumentFeedFetched(int num_accumulated_entries) OVERRIDE;
virtual void OnFileSystemMounted() OVERRIDE;
virtual void OnFileSystemBeingUnmounted() OVERRIDE;
private:
friend class FileBrowserEventRouterFactory;
// Helper class for passing through file watch notification events.
class FileWatcherDelegate : public base::files::FilePathWatcher::Delegate {
public:
explicit FileWatcherDelegate(FileBrowserEventRouter* router);
protected:
virtual ~FileWatcherDelegate() {}
private:
// base::files::FilePathWatcher::Delegate overrides.
virtual void OnFilePathChanged(const FilePath& path) OVERRIDE;
virtual void OnFilePathError(const FilePath& path) OVERRIDE;
void HandleFileWatchOnUIThread(const FilePath& local_path, bool got_error);
FileBrowserEventRouter* router_;
};
typedef std::map<std::string, int> ExtensionUsageRegistry;
class FileWatcherExtensions {
public:
FileWatcherExtensions(const FilePath& path,
const std::string& extension_id,
bool is_remote_file_system);
~FileWatcherExtensions();
void AddExtension(const std::string& extension_id);
void RemoveExtension(const std::string& extension_id);
const ExtensionUsageRegistry& GetExtensions() const;
unsigned int GetRefCount() const;
const FilePath& GetVirtualPath() const;
bool Watch(const FilePath& path, FileWatcherDelegate* delegate);
private:
linked_ptr<base::files::FilePathWatcher> file_watcher_;
FilePath local_path_;
FilePath virtual_path_;
ExtensionUsageRegistry extensions_;
unsigned int ref_count_;
bool is_remote_file_system_;
};
typedef std::map<FilePath, FileWatcherExtensions*> WatcherMap;
explicit FileBrowserEventRouter(Profile* profile);
virtual ~FileBrowserEventRouter();
// USB mount event handlers.
void OnDiskAdded(const chromeos::disks::DiskMountManager::Disk* disk);
void OnDiskRemoved(const chromeos::disks::DiskMountManager::Disk* disk);
void OnDiskMounted(const chromeos::disks::DiskMountManager::Disk* disk);
void OnDiskUnmounted(const chromeos::disks::DiskMountManager::Disk* disk);
void OnDeviceAdded(const std::string& device_path);
void OnDeviceRemoved(const std::string& device_path);
void OnDeviceScanned(const std::string& device_path);
void OnFormattingStarted(const std::string& device_path, bool success);
void OnFormattingFinished(const std::string& device_path, bool success);
// Process file watch notifications.
void HandleFileWatchNotification(const FilePath& path,
bool got_error);
// Sends folder change event.
void DispatchFolderChangeEvent(const FilePath& path, bool error,
const ExtensionUsageRegistry& extensions);
// Sends filesystem changed extension message to all renderers.
void DispatchDiskEvent(const chromeos::disks::DiskMountManager::Disk* disk,
bool added);
void DispatchMountCompletedEvent(
chromeos::disks::DiskMountManager::MountEvent event,
chromeos::MountError error_code,
const chromeos::disks::DiskMountManager::MountPointInfo& mount_info);
void RemoveBrowserFromVector(const std::string& path);
// Used to create a window of a standard size, and add it to a list
// of tracked browser windows in case that device goes away.
void OpenFileBrowse(const std::string& url,
const std::string& device_path,
bool small);
// Returns the DriveFileSystem for the current profile.
gdata::DriveFileSystemInterface* GetRemoteFileSystem() const;
// Handles requests to start and stop periodic updates on remote file system.
// When |start| is set to true, this function starts periodic updates only if
// it is not yet started; when |start| is set to false, this function stops
// periodic updates only if the number of outstanding update requests reaches
// zero.
void HandleRemoteUpdateRequestOnUIThread(bool start);
// Used to implement MountDrive(). Called after the authentication.
void OnAuthenticated(const base::Closure& callback,
gdata::GDataErrorCode error,
const std::string& tokeni);
scoped_refptr<FileWatcherDelegate> delegate_;
WatcherMap file_watchers_;
scoped_ptr<FileBrowserNotifications> notifications_;
scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
Profile* profile_;
base::Lock lock_;
bool current_gdata_operation_failed_;
int last_active_gdata_operation_count_;
// Number of active update requests on the remote file system.
int num_remote_update_requests_;
DISALLOW_COPY_AND_ASSIGN(FileBrowserEventRouter);
};
// Singleton that owns all FileBrowserEventRouter and associates
// them with Profiles.
class FileBrowserEventRouterFactory
: public RefcountedProfileKeyedServiceFactory {
public:
// Returns the FileBrowserEventRouter for |profile|, creating it if
// it is not yet created.
static scoped_refptr<FileBrowserEventRouter> GetForProfile(Profile* profile);
// Returns the FileBrowserEventRouterFactory instance.
static FileBrowserEventRouterFactory* GetInstance();
protected:
// ProfileKeyedBasedFactory overrides:
virtual bool ServiceHasOwnInstanceInIncognito() const OVERRIDE;
private:
friend struct DefaultSingletonTraits<FileBrowserEventRouterFactory>;
FileBrowserEventRouterFactory();
virtual ~FileBrowserEventRouterFactory();
// ProfileKeyedServiceFactory:
virtual scoped_refptr<RefcountedProfileKeyedService> BuildServiceInstanceFor(
Profile* profile) const OVERRIDE;
};
#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_BROWSER_EVENT_ROUTER_H_