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

#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"

#include "base/bind.h"
#include "base/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system_interface.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/desktop_notifications.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/mounted_disk_monitor.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
#include "chrome/browser/drive/drive_service_interface.h"
#include "chrome/browser/extensions/event_names.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/login/login_state.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_source.h"
#include "webkit/common/fileapi/file_system_types.h"
#include "webkit/common/fileapi/file_system_util.h"

using chromeos::disks::DiskMountManager;
using content::BrowserThread;
using drive::DriveIntegrationService;
using drive::DriveIntegrationServiceFactory;

namespace file_manager {
namespace {

const char kPathChanged[] = "changed";
const char kPathWatchError[] = "error";

// Used as a callback for FileSystem::MarkCacheFileAsUnmounted().
void OnMarkAsUnmounted(drive::FileError error) {
  // Do nothing.
}

const char* MountErrorToString(chromeos::MountError error) {
  switch (error) {
    case chromeos::MOUNT_ERROR_NONE:
      return "success";
    case chromeos::MOUNT_ERROR_UNKNOWN:
      return "error_unknown";
    case chromeos::MOUNT_ERROR_INTERNAL:
      return "error_internal";
    case chromeos::MOUNT_ERROR_INVALID_ARGUMENT:
      return "error_invalid_argument";
    case chromeos::MOUNT_ERROR_INVALID_PATH:
      return "error_invalid_path";
    case chromeos::MOUNT_ERROR_PATH_ALREADY_MOUNTED:
      return "error_path_already_mounted";
    case chromeos::MOUNT_ERROR_PATH_NOT_MOUNTED:
      return "error_path_not_mounted";
    case chromeos::MOUNT_ERROR_DIRECTORY_CREATION_FAILED:
      return "error_directory_creation_failed";
    case chromeos::MOUNT_ERROR_INVALID_MOUNT_OPTIONS:
      return "error_invalid_mount_options";
    case chromeos::MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS:
      return "error_invalid_unmount_options";
    case chromeos::MOUNT_ERROR_INSUFFICIENT_PERMISSIONS:
      return "error_insufficient_permissions";
    case chromeos::MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND:
      return "error_mount_program_not_found";
    case chromeos::MOUNT_ERROR_MOUNT_PROGRAM_FAILED:
      return "error_mount_program_failed";
    case chromeos::MOUNT_ERROR_INVALID_DEVICE_PATH:
      return "error_invalid_device_path";
    case chromeos::MOUNT_ERROR_UNKNOWN_FILESYSTEM:
      return "error_unknown_filesystem";
    case chromeos::MOUNT_ERROR_UNSUPPORTED_FILESYSTEM:
      return "error_unsuported_filesystem";
    case chromeos::MOUNT_ERROR_INVALID_ARCHIVE:
      return "error_invalid_archive";
    case chromeos::MOUNT_ERROR_NOT_AUTHENTICATED:
      return "error_authentication";
    case chromeos::MOUNT_ERROR_PATH_UNMOUNTED:
      return "error_path_unmounted";
  }
  NOTREACHED();
  return "";
}

void DirectoryExistsOnBlockingPool(const base::FilePath& directory_path,
                                   const base::Closure& success_callback,
                                   const base::Closure& failure_callback) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());

  if (base::DirectoryExists(directory_path))
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, success_callback);
  else
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, failure_callback);
};

void DirectoryExistsOnUIThread(const base::FilePath& directory_path,
                               const base::Closure& success_callback,
                               const base::Closure& failure_callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  content::BrowserThread::PostBlockingPoolTask(
      FROM_HERE,
      base::Bind(&DirectoryExistsOnBlockingPool,
                 directory_path,
                 success_callback,
                 failure_callback));
};

// Creates a base::FilePathWatcher and starts watching at |watch_path| with
// |callback|. Returns NULL on failure.
base::FilePathWatcher* CreateAndStartFilePathWatcher(
    const base::FilePath& watch_path,
    const base::FilePathWatcher::Callback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(!callback.is_null());

  base::FilePathWatcher* watcher(new base::FilePathWatcher);
  if (!watcher->Watch(watch_path, false /* recursive */, callback)) {
    delete watcher;
    return NULL;
  }

  return watcher;
}

// Constants for the "transferState" field of onFileTransferUpdated event.
const char kFileTransferStateStarted[] = "started";
const char kFileTransferStateInProgress[] = "in_progress";
const char kFileTransferStateCompleted[] = "completed";
const char kFileTransferStateFailed[] = "failed";

// Frequency of sending onFileTransferUpdated.
const int64 kFileTransferEventFrequencyInMilliseconds = 1000;

// Utility function to check if |job_info| is a file uploading job.
bool IsUploadJob(drive::JobType type) {
  return (type == drive::TYPE_UPLOAD_NEW_FILE ||
          type == drive::TYPE_UPLOAD_EXISTING_FILE);
}

// Utility function to check if |job_info| is a file downloading job.
bool IsDownloadJob(drive::JobType type) {
  return type == drive::TYPE_DOWNLOAD_FILE;
}

// Converts the job info to its JSON (Value) form.
scoped_ptr<base::DictionaryValue> JobInfoToDictionaryValue(
    const std::string& extension_id,
    const std::string& job_status,
    const drive::JobInfo& job_info) {
  DCHECK(IsActiveFileTransferJobInfo(job_info));

  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
  GURL url = util::ConvertRelativePathToFileSystemUrl(
      job_info.file_path, extension_id);
  result->SetString("fileUrl", url.spec());
  result->SetString("transferState", job_status);
  result->SetString("transferType",
                    IsUploadJob(job_info.job_type) ? "upload" : "download");
  // JavaScript does not have 64-bit integers. Instead we use double, which
  // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice
  // in C++. Larger values are rounded.
  result->SetDouble("processed",
                    static_cast<double>(job_info.num_completed_bytes));
  result->SetDouble("total", static_cast<double>(job_info.num_total_bytes));
  return result.Pass();
}

// Checks for availability of the Google+ Photos app.
bool IsGooglePhotosInstalled(Profile *profile) {
  ExtensionService* service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  if (!service)
    return false;

  // Google+ Photos uses several ids for different channels. Therefore, all of
  // them should be checked.
  const std::string kGooglePlusPhotosIds[] = {
    "ebpbnabdhheoknfklmpddcdijjkmklkp",  // G+ Photos staging
    "efjnaogkjbogokcnohkmnjdojkikgobo",  // G+ Photos prod
    "ejegoaikibpmikoejfephaneibodccma"   // G+ Photos dev
  };

  for (size_t i = 0; i < arraysize(kGooglePlusPhotosIds); ++i) {
    if (service->GetExtensionById(kGooglePlusPhotosIds[i],
                                  false /* include_disable */) != NULL)
      return true;
  }

  return false;
}

}  // namespace

// Pass dummy value to JobInfo's constructor for make it default constructible.
EventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus()
    : job_info(drive::TYPE_DOWNLOAD_FILE) {
}

EventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus(
    const drive::JobInfo& info, const std::string& status)
    : job_info(info), status(status) {
}

EventRouter::EventRouter(
    Profile* profile)
    : notifications_(new DesktopNotifications(profile)),
      pref_change_registrar_(new PrefChangeRegistrar),
      profile_(profile),
      weak_factory_(this) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

EventRouter::~EventRouter() {
}

void EventRouter::Shutdown() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DLOG_IF(WARNING, !file_watchers_.empty())
      << "Not all file watchers are "
      << "removed. This can happen when Files.app is open during shutdown.";
  STLDeleteValues(&file_watchers_);
  if (!profile_) {
    NOTREACHED();
    return;
  }

  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
  if (disk_mount_manager)
    disk_mount_manager->RemoveObserver(this);

  DriveIntegrationService* integration_service =
      DriveIntegrationServiceFactory::FindForProfileRegardlessOfStates(
          profile_);
  if (integration_service) {
    integration_service->RemoveObserver(this);
    integration_service->file_system()->RemoveObserver(this);
    integration_service->drive_service()->RemoveObserver(this);
    integration_service->job_list()->RemoveObserver(this);
  }

  if (chromeos::ConnectivityStateHelper::IsInitialized()) {
    chromeos::ConnectivityStateHelper::Get()->
        RemoveNetworkManagerObserver(this);
  }
  profile_ = NULL;
}

void EventRouter::ObserveFileSystemEvents() {
  if (!profile_) {
    NOTREACHED();
    return;
  }
  if (!chromeos::LoginState::IsInitialized() ||
      !chromeos::LoginState::Get()->IsUserLoggedIn()) {
    return;
  }

  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
  if (disk_mount_manager) {
    disk_mount_manager->RemoveObserver(this);
    disk_mount_manager->AddObserver(this);
    disk_mount_manager->RequestMountInfoRefresh();
  }

  DriveIntegrationService* integration_service =
      DriveIntegrationServiceFactory::GetForProfileRegardlessOfStates(
          profile_);
  if (integration_service) {
    integration_service->AddObserver(this);
    integration_service->drive_service()->AddObserver(this);
    integration_service->file_system()->AddObserver(this);
    integration_service->job_list()->AddObserver(this);
  }

  if (chromeos::ConnectivityStateHelper::IsInitialized()) {
    chromeos::ConnectivityStateHelper::Get()->
        AddNetworkManagerObserver(this);
  }

  mounted_disk_monitor_.reset(new MountedDiskMonitor());

  pref_change_registrar_->Init(profile_->GetPrefs());

  pref_change_registrar_->Add(
      prefs::kExternalStorageDisabled,
      base::Bind(&EventRouter::OnExternalStorageDisabledChanged,
                 weak_factory_.GetWeakPtr()));

  base::Closure callback =
      base::Bind(&EventRouter::OnFileManagerPrefsChanged,
                 weak_factory_.GetWeakPtr());
  pref_change_registrar_->Add(prefs::kDisableDriveOverCellular, callback);
  pref_change_registrar_->Add(prefs::kDisableDriveHostedFiles, callback);
  pref_change_registrar_->Add(prefs::kDisableDrive, callback);
  pref_change_registrar_->Add(prefs::kUse24HourClock, callback);
}

// File watch setup routines.
void EventRouter::AddFileWatch(const base::FilePath& local_path,
                               const base::FilePath& virtual_path,
                               const std::string& extension_id,
                               const BoolCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  base::FilePath watch_path = local_path;
  bool is_on_drive = drive::util::IsUnderDriveMountPoint(watch_path);
  // Tweak watch path for remote sources - we need to drop leading /special
  // directory from there in order to be able to pair these events with
  // their change notifications.
  if (is_on_drive)
    watch_path = drive::util::ExtractDrivePath(watch_path);

  WatcherMap::iterator iter = file_watchers_.find(watch_path);
  if (iter == file_watchers_.end()) {
    scoped_ptr<FileWatcher> watcher(new FileWatcher(virtual_path));
    watcher->AddExtension(extension_id);

    if (is_on_drive) {
      // For Drive, file watching is done via OnDirectoryChanged().
      base::MessageLoopProxy::current()->PostTask(FROM_HERE,
                                                  base::Bind(callback, true));
    } else {
      // For local files, start watching using FileWatcher.
      watcher->WatchLocalFile(
          watch_path,
          base::Bind(&EventRouter::HandleFileWatchNotification,
                     weak_factory_.GetWeakPtr()),
          callback);
    }

    file_watchers_[watch_path] = watcher.release();
  } else {
    iter->second->AddExtension(extension_id);
    base::MessageLoopProxy::current()->PostTask(FROM_HERE,
                                                base::Bind(callback, true));
  }
}

void EventRouter::RemoveFileWatch(const base::FilePath& local_path,
                                  const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  base::FilePath watch_path = local_path;
  // Tweak watch path for remote sources - we need to drop leading /special
  // directory from there in order to be able to pair these events with
  // their change notifications.
  if (drive::util::IsUnderDriveMountPoint(watch_path)) {
    watch_path = drive::util::ExtractDrivePath(watch_path);
  }
  WatcherMap::iterator iter = file_watchers_.find(watch_path);
  if (iter == file_watchers_.end())
    return;
  // Remove the watcher if |watch_path| is no longer watched by any extensions.
  iter->second->RemoveExtension(extension_id);
  if (iter->second->GetExtensionIds().empty()) {
    delete iter->second;
    file_watchers_.erase(iter);
  }
}

void EventRouter::OnDiskEvent(DiskMountManager::DiskEvent event,
                              const DiskMountManager::Disk* disk) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Disregard hidden devices.
  if (disk->is_hidden())
    return;
  if (event == DiskMountManager::DISK_ADDED) {
    OnDiskAdded(disk);
  } else if (event == DiskMountManager::DISK_REMOVED) {
    OnDiskRemoved(disk);
  }
}

void EventRouter::OnDeviceEvent(DiskMountManager::DeviceEvent event,
                                const std::string& device_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (event == DiskMountManager::DEVICE_ADDED) {
    OnDeviceAdded(device_path);
  } else if (event == DiskMountManager::DEVICE_REMOVED) {
    OnDeviceRemoved(device_path);
  } else if (event == DiskMountManager::DEVICE_SCANNED) {
    OnDeviceScanned(device_path);
  }
}

void EventRouter::OnMountEvent(
    DiskMountManager::MountEvent event,
    chromeos::MountError error_code,
    const DiskMountManager::MountPointInfo& mount_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // profile_ is NULL if ShutdownOnUIThread() is called earlier. This can
  // happen at shutdown.
  if (!profile_)
    return;

  DCHECK(mount_info.mount_type != chromeos::MOUNT_TYPE_INVALID);

  DispatchMountEvent(event, error_code, mount_info);

  if (mount_info.mount_type == chromeos::MOUNT_TYPE_DEVICE &&
      event == DiskMountManager::MOUNTING) {
    DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
    const DiskMountManager::Disk* disk =
        disk_mount_manager->FindDiskBySourcePath(mount_info.source_path);
    if (!disk || mounted_disk_monitor_->DiskIsRemounting(*disk))
      return;

    notifications_->ManageNotificationsOnMountCompleted(
        disk->system_path_prefix(), disk->drive_label(), disk->is_parent(),
        error_code == chromeos::MOUNT_ERROR_NONE,
        error_code == chromeos::MOUNT_ERROR_UNSUPPORTED_FILESYSTEM);

    // If a new device was mounted, a new File manager window may need to be
    // opened.
    if (error_code == chromeos::MOUNT_ERROR_NONE)
      ShowRemovableDeviceInFileManager(
          *disk,
          base::FilePath::FromUTF8Unsafe(mount_info.mount_path));
  } else if (mount_info.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) {
    // Clear the "mounted" state for archive files in drive cache
    // when mounting failed or unmounting succeeded.
    if ((event == DiskMountManager::MOUNTING) !=
        (error_code == chromeos::MOUNT_ERROR_NONE)) {
      DriveIntegrationService* integration_service =
          DriveIntegrationServiceFactory::GetForProfile(profile_);
      drive::FileSystemInterface* file_system =
          integration_service ? integration_service->file_system() : NULL;
      if (file_system) {
        file_system->MarkCacheFileAsUnmounted(
            base::FilePath(mount_info.source_path),
            base::Bind(&OnMarkAsUnmounted));
      }
    }
  }
}

void EventRouter::OnFormatEvent(DiskMountManager::FormatEvent event,
                                chromeos::FormatError error_code,
                                const std::string& device_path) {
  if (event == DiskMountManager::FORMAT_STARTED) {
    OnFormatStarted(device_path, error_code == chromeos::FORMAT_ERROR_NONE);
  } else if (event == DiskMountManager::FORMAT_COMPLETED) {
    OnFormatCompleted(device_path, error_code == chromeos::FORMAT_ERROR_NONE);
  }
}

void EventRouter::NetworkManagerChanged() {
  if (!profile_ ||
      !extensions::ExtensionSystem::Get(profile_)->event_router()) {
    NOTREACHED();
    return;
  }
  scoped_ptr<extensions::Event> event(new extensions::Event(
      extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged,
      scoped_ptr<ListValue>(new ListValue())));
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      BroadcastEvent(event.Pass());
}

void EventRouter::DefaultNetworkChanged() {
  NetworkManagerChanged();
}

void EventRouter::OnExternalStorageDisabledChanged() {
  // If the policy just got disabled we have to unmount every device currently
  // mounted. The opposite is fine - we can let the user re-plug her device to
  // make it available.
  if (profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) {
    DiskMountManager* manager = DiskMountManager::GetInstance();
    DiskMountManager::MountPointMap mounts(manager->mount_points());
    for (DiskMountManager::MountPointMap::const_iterator it = mounts.begin();
         it != mounts.end(); ++it) {
      LOG(INFO) << "Unmounting " << it->second.mount_path
                << " because of policy.";
      manager->UnmountPath(it->second.mount_path,
                           chromeos::UNMOUNT_OPTIONS_NONE,
                           DiskMountManager::UnmountPathCallback());
    }
  }
}

void EventRouter::OnFileManagerPrefsChanged() {
  if (!profile_ ||
      !extensions::ExtensionSystem::Get(profile_)->event_router()) {
    NOTREACHED();
    return;
  }

  scoped_ptr<extensions::Event> event(new extensions::Event(
      extensions::event_names::kOnFileBrowserPreferencesChanged,
      scoped_ptr<ListValue>(new ListValue())));
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      BroadcastEvent(event.Pass());
}

void EventRouter::OnJobAdded(const drive::JobInfo& job_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  OnJobUpdated(job_info);
}

void EventRouter::OnJobUpdated(const drive::JobInfo& job_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (!drive::IsActiveFileTransferJobInfo(job_info))
    return;

  bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end());

  // Replace with the latest job info.
  drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(
      job_info,
      is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress);

  // Fire event if needed.
  bool always = is_new_job;
  SendDriveFileTransferEvent(always);
}

void EventRouter::OnJobDone(const drive::JobInfo& job_info,
                            drive::FileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (!drive::IsActiveFileTransferJobInfo(job_info))
    return;

  // Replace with the latest job info.
  drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(
      job_info,
      error == drive::FILE_ERROR_OK ? kFileTransferStateCompleted
      : kFileTransferStateFailed);

  // Fire event if needed.
  bool always = true;
  SendDriveFileTransferEvent(always);

  // Forget about the job.
  drive_jobs_.erase(job_info.job_id);
}

void EventRouter::SendDriveFileTransferEvent(bool always) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  const base::Time now = base::Time::Now();

  // When |always| flag is not set, we don't send the event until certain
  // amount of time passes after the previous one. This is to avoid
  // flooding the IPC between extensions by many onFileTransferUpdated events.
  if (!always) {
    const int64 delta = (now - last_file_transfer_event_).InMilliseconds();
    // delta < 0 may rarely happen if system clock is synced and rewinded.
    // To be conservative, we don't skip in that case.
    if (0 <= delta && delta < kFileTransferEventFrequencyInMilliseconds)
      return;
  }

  // Convert the current |drive_jobs_| to a JSON value.
  scoped_ptr<base::ListValue> event_list(new base::ListValue);
  for (std::map<drive::JobID, DriveJobInfoWithStatus>::iterator
           iter = drive_jobs_.begin(); iter != drive_jobs_.end(); ++iter) {

    scoped_ptr<base::DictionaryValue> job_info_dict(
        JobInfoToDictionaryValue(kFileBrowserDomain,
                                 iter->second.status,
                                 iter->second.job_info));
    event_list->Append(job_info_dict.release());
  }

  scoped_ptr<ListValue> args(new ListValue());
  args->Append(event_list.release());
  scoped_ptr<extensions::Event> event(new extensions::Event(
      extensions::event_names::kOnFileTransfersUpdated, args.Pass()));
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      DispatchEventToExtension(kFileBrowserDomain, event.Pass());

  last_file_transfer_event_ = now;
}

void EventRouter::OnDirectoryChanged(const base::FilePath& directory_path) {
  HandleFileWatchNotification(directory_path, false);
}

void EventRouter::OnFileSystemMounted() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  const std::string& drive_path = drive::util::GetDriveMountPointPathAsString();
  DiskMountManager::MountPointInfo mount_info(
      drive_path,
      drive_path,
      chromeos::MOUNT_TYPE_GOOGLE_DRIVE,
      chromeos::disks::MOUNT_CONDITION_NONE);

  // Raise mount event.
  // We can pass chromeos::MOUNT_ERROR_NONE even when authentication is failed
  // or network is unreachable. These two errors will be handled later.
  OnMountEvent(DiskMountManager::MOUNTING, chromeos::MOUNT_ERROR_NONE,
               mount_info);
}

void EventRouter::OnFileSystemBeingUnmounted() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Raise a mount event to notify the File Manager.
  const std::string& drive_path = drive::util::GetDriveMountPointPathAsString();
  DiskMountManager::MountPointInfo mount_info(
      drive_path,
      drive_path,
      chromeos::MOUNT_TYPE_GOOGLE_DRIVE,
      chromeos::disks::MOUNT_CONDITION_NONE);
  OnMountEvent(DiskMountManager::UNMOUNTING, chromeos::MOUNT_ERROR_NONE,
               mount_info);
}

void EventRouter::OnRefreshTokenInvalid() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Raise a DriveConnectionStatusChanged event to notify the status offline.
  scoped_ptr<extensions::Event> event(new extensions::Event(
      extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged,
      scoped_ptr<ListValue>(new ListValue())));
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      BroadcastEvent(event.Pass());
}

void EventRouter::HandleFileWatchNotification(const base::FilePath& local_path,
                                              bool got_error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  WatcherMap::const_iterator iter = file_watchers_.find(local_path);
  if (iter == file_watchers_.end()) {
    return;
  }
  DispatchDirectoryChangeEvent(iter->second->virtual_path(), got_error,
                               iter->second->GetExtensionIds());
}

void EventRouter::DispatchDirectoryChangeEvent(
    const base::FilePath& virtual_path,
    bool got_error,
    const std::vector<std::string>& extension_ids) {
  if (!profile_) {
    NOTREACHED();
    return;
  }

  for (size_t i = 0; i < extension_ids.size(); ++i) {
    const std::string& extension_id = extension_ids[i];

    GURL target_origin_url(extensions::Extension::GetBaseURLFromExtensionId(
        extension_id));
    GURL base_url = fileapi::GetFileSystemRootURI(
        target_origin_url,
        fileapi::kFileSystemTypeExternal);
    GURL target_directory_url = GURL(base_url.spec() + virtual_path.value());
    scoped_ptr<ListValue> args(new ListValue());
    DictionaryValue* watch_info = new DictionaryValue();
    args->Append(watch_info);
    watch_info->SetString("directoryUrl", target_directory_url.spec());
    watch_info->SetString("eventType",
                          got_error ? kPathWatchError : kPathChanged);

    // TODO(mtomasz): Pass set of entries. http://crbug.com/157834
    ListValue* watch_info_entries = new ListValue();
    watch_info->Set("changedEntries", watch_info_entries);

    scoped_ptr<extensions::Event> event(new extensions::Event(
        extensions::event_names::kOnDirectoryChanged, args.Pass()));
    extensions::ExtensionSystem::Get(profile_)->event_router()->
        DispatchEventToExtension(extension_id, event.Pass());
  }
}

void EventRouter::DispatchMountEvent(
    DiskMountManager::MountEvent event,
    chromeos::MountError error_code,
    const DiskMountManager::MountPointInfo& mount_info) {
  scoped_ptr<ListValue> args(new ListValue());
  DictionaryValue* mount_info_value = new DictionaryValue();
  args->Append(mount_info_value);
  mount_info_value->SetString(
      "eventType",
      event == DiskMountManager::MOUNTING ? "mount" : "unmount");
  mount_info_value->SetString("status", MountErrorToString(error_code));
  mount_info_value->SetString(
      "mountType",
      DiskMountManager::MountTypeToString(mount_info.mount_type));

  // Add sourcePath to the event.
  mount_info_value->SetString("sourcePath", mount_info.source_path);

  base::FilePath relative_mount_path;

  // If there were no error or some special conditions occurred, add mountPath
  // to the event.
  if (event == DiskMountManager::UNMOUNTING ||
      error_code == chromeos::MOUNT_ERROR_NONE ||
      mount_info.mount_condition) {
    // Convert mount point path to relative path with the external file system
    // exposed within File API.
    if (util::ConvertFileToRelativeFileSystemPath(
            profile_,
            kFileBrowserDomain,
            base::FilePath(mount_info.mount_path),
            &relative_mount_path)) {
      mount_info_value->SetString("mountPath",
                                  "/" + relative_mount_path.value());
    } else {
      mount_info_value->SetString(
          "status",
          MountErrorToString(chromeos::MOUNT_ERROR_PATH_UNMOUNTED));
    }
  }

  scoped_ptr<extensions::Event> extension_event(new extensions::Event(
      extensions::event_names::kOnFileBrowserMountCompleted, args.Pass()));
  extensions::ExtensionSystem::Get(profile_)->event_router()->
      BroadcastEvent(extension_event.Pass());
}

void EventRouter::ShowRemovableDeviceInFileManager(
    const DiskMountManager::Disk& disk,
    const base::FilePath& mount_path) {
  // Do not attempt to open File Manager while the login is in progress or
  // the screen is locked.
  if (chromeos::LoginDisplayHostImpl::default_host() ||
      chromeos::ScreenLocker::default_screen_locker())
    return;

  // According to DCF (Design rule of Camera File system) by JEITA / CP-3461
  // cameras should have pictures located in the DCIM root directory.
  const base::FilePath dcim_path = mount_path.Append(
      FILE_PATH_LITERAL("DCIM"));

  // If there is no DCIM folder or an external photo importer is not available,
  // then launch Files.app.
  DirectoryExistsOnUIThread(
      dcim_path,
      IsGooglePhotosInstalled(profile_) ?
      base::Bind(&base::DoNothing) :
      base::Bind(&util::ViewRemovableDrive, mount_path),
      base::Bind(&util::ViewRemovableDrive, mount_path));
}

void EventRouter::OnDiskAdded(const DiskMountManager::Disk* disk) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  VLOG(1) << "Disk added: " << disk->device_path();
  if (disk->device_path().empty()) {
    VLOG(1) << "Empty system path for " << disk->device_path();
    return;
  }

  // If disk is not mounted yet and it has media and there is no policy
  // forbidding external storage, give it a try.
  if (disk->mount_path().empty() && disk->has_media() &&
      !profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) {
    // Initiate disk mount operation. MountPath auto-detects the filesystem
    // format if the second argument is empty. The third argument (mount label)
    // is not used in a disk mount operation.
    DiskMountManager::GetInstance()->MountPath(
        disk->device_path(), std::string(), std::string(),
        chromeos::MOUNT_TYPE_DEVICE);
  } else {
    // Either the disk was mounted or it has no media. In both cases we don't
    // want the Scanning notification to persist.
    notifications_->HideNotification(DesktopNotifications::DEVICE,
                                     disk->system_path_prefix());
  }
}

void EventRouter::OnDiskRemoved(const DiskMountManager::Disk* disk) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  VLOG(1) << "Disk removed: " << disk->device_path();

  if (!disk->mount_path().empty()) {
    DiskMountManager::GetInstance()->UnmountPath(
        disk->mount_path(),
        chromeos::UNMOUNT_OPTIONS_LAZY,
        DiskMountManager::UnmountPathCallback());
  }
}

void EventRouter::OnDeviceAdded(const std::string& device_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  VLOG(1) << "Device added : " << device_path;

  // If the policy is set instead of showing the new device notification we show
  // a notification that the operation is not permitted.
  if (profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) {
    notifications_->ShowNotification(
        DesktopNotifications::DEVICE_EXTERNAL_STORAGE_DISABLED,
        device_path);
    return;
  }

  notifications_->RegisterDevice(device_path);
  notifications_->ShowNotificationDelayed(DesktopNotifications::DEVICE,
                                          device_path,
                                          base::TimeDelta::FromSeconds(5));
}

void EventRouter::OnDeviceRemoved(const std::string& device_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  VLOG(1) << "Device removed : " << device_path;
  notifications_->HideNotification(DesktopNotifications::DEVICE,
                                   device_path);
  notifications_->HideNotification(DesktopNotifications::DEVICE_FAIL,
                                   device_path);
  notifications_->UnregisterDevice(device_path);
}

void EventRouter::OnDeviceScanned(const std::string& device_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  VLOG(1) << "Device scanned : " << device_path;
}

void EventRouter::OnFormatStarted(const std::string& device_path,
                                  bool success) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (success) {
    notifications_->ShowNotification(DesktopNotifications::FORMAT_START,
                                     device_path);
  } else {
    notifications_->ShowNotification(
        DesktopNotifications::FORMAT_START_FAIL, device_path);
  }
}

void EventRouter::OnFormatCompleted(const std::string& device_path,
                                    bool success) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (success) {
    notifications_->HideNotification(DesktopNotifications::FORMAT_START,
                                     device_path);
    notifications_->ShowNotification(DesktopNotifications::FORMAT_SUCCESS,
                                     device_path);
    // Hide it after a couple of seconds.
    notifications_->HideNotificationDelayed(
        DesktopNotifications::FORMAT_SUCCESS,
        device_path,
        base::TimeDelta::FromSeconds(4));
    // MountPath auto-detects filesystem format if second argument is empty.
    // The third argument (mount label) is not used in a disk mount operation.
    DiskMountManager::GetInstance()->MountPath(device_path, std::string(),
                                               std::string(),
                                               chromeos::MOUNT_TYPE_DEVICE);
  } else {
    notifications_->HideNotification(DesktopNotifications::FORMAT_START,
                                     device_path);
    notifications_->ShowNotification(DesktopNotifications::FORMAT_FAIL,
                                     device_path);
  }
}

}  // namespace file_manager
