11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_change_registrar.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/thread_task_runner_handle.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/app_mode/app_mode_utils.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive_integration_service.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/drive/file_change.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_interface.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/chromeos/extensions/file_manager/device_event_router.h"
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/app_id.h"
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/open_util.h"
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/volume_manager.h"
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/lock/screen_locker.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/drive/drive_service_interface.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/extensions/extension_util.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/chrome_switches.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/dbus/dbus_thread_manager.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/login/login_state.h"
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_handler.h"
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_state_handler.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/storage_partition.h"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_types.h"
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using chromeos::disks::DiskMountManager;
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing chromeos::NetworkHandler;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using drive::DriveIntegrationService;
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using drive::DriveIntegrationServiceFactory;
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::EntryDefinition;
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::FileDefinition;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace file_manager_private = extensions::api::file_manager_private;
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace file_manager {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Constants for the "transferState" field of onFileTransferUpdated event.
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char kFileTransferStateAdded[] = "added";
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kFileTransferStateStarted[] = "started";
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kFileTransferStateInProgress[] = "in_progress";
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kFileTransferStateCompleted[] = "completed";
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kFileTransferStateFailed[] = "failed";
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Frequency of sending onFileTransferUpdated.
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int64 kProgressEventFrequencyInMilliseconds = 1000;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Maximim size of detailed change info on directory change event. If the size
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// exceeds the maximum size, the detailed info is omitted and the force refresh
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// is kicked.
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst size_t kDirectoryChangeEventMaxDetailInfoSize = 1000;
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This time(millisecond) is used for confirm following event exists.
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int64 kFileTransferEventDelayTimeInMilliseconds = 300;
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Utility function to check if |job_info| is a file uploading job.
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IsUploadJob(drive::JobType type) {
832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return (type == drive::TYPE_UPLOAD_NEW_FILE ||
842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          type == drive::TYPE_UPLOAD_EXISTING_FILE);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisize_t CountActiveFileTransferJobInfo(
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<drive::JobInfo>& job_info_list) {
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t num_active_file_transfer_job_info = 0;
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < job_info_list.size(); ++i) {
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (IsActiveFileTransferJobInfo(job_info_list[i]))
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ++num_active_file_transfer_job_info;
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return num_active_file_transfer_job_info;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Converts the job info to a IDL generated type.
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void JobInfoToTransferStatus(
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* profile,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& job_status,
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const drive::JobInfo& job_info,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    file_manager_private::FileTransferStatus* status) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(IsActiveFileTransferJobInfo(job_info));
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url = util::ConvertDrivePathToFileSystemUrl(
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile, job_info.file_path, extension_id);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status->file_url = url.spec();
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  status->transfer_state = file_manager_private::ParseTransferState(job_status);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status->transfer_type =
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IsUploadJob(job_info.job_type) ?
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::TRANSFER_TYPE_UPLOAD :
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::TRANSFER_TYPE_DOWNLOAD;
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DriveIntegrationService* const integration_service =
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DriveIntegrationServiceFactory::FindForProfile(profile);
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  status->num_total_jobs = CountActiveFileTransferJobInfo(
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      integration_service->job_list()->GetJobInfoList());
119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // JavaScript does not have 64-bit integers. Instead we use double, which
120bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // is in IEEE 754 formant and accurate up to 52-bits in JS, and in practice
121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // in C++. Larger values are rounded.
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status->processed.reset(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new double(static_cast<double>(job_info.num_completed_bytes)));
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status->total.reset(
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new double(static_cast<double>(job_info.num_total_bytes)));
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Checks if the Recovery Tool is running. This is a temporary solution.
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO(mtomasz): Replace with crbug.com/341902 solution.
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool IsRecoveryToolRunning(Profile* profile) {
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  extensions::ExtensionPrefs* extension_prefs =
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::ExtensionPrefs::Get(profile);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!extension_prefs)
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string kRecoveryToolIds[] = {
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "kkebgepbbgbcmghedmmdfcbdcodlkngh",  // Recovery tool staging
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "jndclpdbaamdhonoechobihbbiimdgai"   // Recovery tool prod
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kRecoveryToolIds); ++i) {
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string extension_id = kRecoveryToolIds[i];
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (extension_prefs->IsExtensionRunning(extension_id))
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return true;
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return false;
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Sends an event named |event_name| with arguments |event_args| to extensions.
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void BroadcastEvent(Profile* profile,
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    const std::string& event_name,
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    scoped_ptr<base::ListValue> event_args) {
1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::EventRouter::Get(profile)->BroadcastEvent(
1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      make_scoped_ptr(new extensions::Event(event_name, event_args.Pass())));
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifile_manager_private::MountCompletedStatus
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)MountErrorToMountCompletedStatus(chromeos::MountError error) {
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (error) {
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_NONE:
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_SUCCESS;
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_UNKNOWN:
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_UNKNOWN;
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INTERNAL:
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INTERNAL;
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_ARGUMENT:
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_INVALID_ARGUMENT;
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_PATH:
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INVALID_PATH;
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_PATH_ALREADY_MOUNTED:
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_PATH_ALREADY_MOUNTED;
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_PATH_NOT_MOUNTED:
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_PATH_NOT_MOUNTED;
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_DIRECTORY_CREATION_FAILED:
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ::MOUNT_COMPLETED_STATUS_ERROR_DIRECTORY_CREATION_FAILED;
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_MOUNT_OPTIONS:
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ::MOUNT_COMPLETED_STATUS_ERROR_INVALID_MOUNT_OPTIONS;
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS:
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_INVALID_UNMOUNT_OPTIONS;
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INSUFFICIENT_PERMISSIONS:
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_INSUFFICIENT_PERMISSIONS;
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND:
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_MOUNT_PROGRAM_NOT_FOUND;
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_MOUNT_PROGRAM_FAILED:
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_MOUNT_PROGRAM_FAILED;
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_DEVICE_PATH:
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_INVALID_DEVICE_PATH;
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_UNKNOWN_FILESYSTEM:
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_UNKNOWN_FILESYSTEM;
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_UNSUPPORTED_FILESYSTEM:
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          MOUNT_COMPLETED_STATUS_ERROR_UNSUPPORTED_FILESYSTEM;
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_INVALID_ARCHIVE:
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INVALID_ARCHIVE;
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_NOT_AUTHENTICATED:
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_AUTHENTICATION;
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case chromeos::MOUNT_ERROR_PATH_UNMOUNTED:
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_PATH_UNMOUNTED;
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NOTREACHED();
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return file_manager_private::MOUNT_COMPLETED_STATUS_NONE;
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifile_manager_private::CopyProgressStatusType
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)CopyProgressTypeToCopyProgressStatusType(
21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::FileSystemOperation::CopyProgressType type) {
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  switch (type) {
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case storage::FileSystemOperation::BEGIN_COPY_ENTRY:
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::COPY_PROGRESS_STATUS_TYPE_BEGIN_COPY_ENTRY;
22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case storage::FileSystemOperation::END_COPY_ENTRY:
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::COPY_PROGRESS_STATUS_TYPE_END_COPY_ENTRY;
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case storage::FileSystemOperation::PROGRESS:
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::COPY_PROGRESS_STATUS_TYPE_PROGRESS;
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NOTREACHED();
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return file_manager_private::COPY_PROGRESS_STATUS_TYPE_NONE;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifile_manager_private::ChangeType ConvertChangeTypeFromDriveToApi(
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    drive::FileChange::ChangeType type) {
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  switch (type) {
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case drive::FileChange::ADD_OR_UPDATE:
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::CHANGE_TYPE_ADD_OR_UPDATE;
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case drive::FileChange::DELETE:
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return file_manager_private::CHANGE_TYPE_DELETE;
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  NOTREACHED();
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return file_manager_private::CHANGE_TYPE_ADD_OR_UPDATE;
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string FileErrorToErrorName(base::File::Error error_code) {
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  namespace js = extensions::api::file_manager_private;
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (error_code) {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_NOT_FOUND:
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "NotFoundError";
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_INVALID_OPERATION:
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_EXISTS:
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_NOT_EMPTY:
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "InvalidModificationError";
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_NOT_A_DIRECTORY:
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_NOT_A_FILE:
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "TypeMismatchError";
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_ACCESS_DENIED:
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "NoModificationAllowedError";
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_FAILED:
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "InvalidStateError";
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_ABORT:
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "AbortError";
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_SECURITY:
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "SecurityError";
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_NO_SPACE:
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "QuotaExceededError";
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case base::File::FILE_ERROR_INVALID_URL:
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "EncodingError";
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "InvalidModificationError";
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GrantAccessForAddedProfileToRunningInstance(Profile* added_profile,
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 Profile* running_profile) {
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::ProcessManager* const process_manager =
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ExtensionSystem::Get(running_profile)->process_manager();
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!process_manager)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::ExtensionHost* const extension_host =
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      process_manager->GetBackgroundHostForExtension(kFileManagerAppId);
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!extension_host || !extension_host->render_process_host())
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int id = extension_host->render_process_host()->GetID();
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_manager::util::SetupProfileFileAccessPermissions(id, added_profile);
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Checks if we should send a progress event or not according to the
289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// |last_time| of sending an event. If |always| is true, the function always
290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// returns true. If the function returns true, the function also updates
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// |last_time|.
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool ShouldSendProgressEvent(bool always, base::Time* last_time) {
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const base::Time now = base::Time::Now();
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int64 delta = (now - *last_time).InMilliseconds();
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // delta < 0 may rarely happen if system clock is synced and rewinded.
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // To be conservative, we don't skip in that case.
297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!always && 0 <= delta && delta < kProgressEventFrequencyInMilliseconds) {
298c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
299c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
300c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *last_time = now;
301c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return true;
302c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
303c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
304c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Obtains whether the Files.app should handle the volume or not.
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ShouldShowNotificationForVolume(
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Profile* profile,
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DeviceEventRouter& device_event_router,
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const VolumeInfo& volume_info) {
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (volume_info.type != VOLUME_TYPE_MTP &&
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      volume_info.type != VOLUME_TYPE_REMOVABLE_DISK_PARTITION) {
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (device_event_router.is_resuming() || device_event_router.is_starting_up())
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Do not attempt to open File Manager while the login is in progress or
319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the screen is locked or running in kiosk app mode and make sure the file
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // manager is opened only for the active user.
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (chromeos::LoginDisplayHostImpl::default_host() ||
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      chromeos::ScreenLocker::default_screen_locker() ||
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      chrome::IsRunningInForcedAppMode() ||
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      profile != ProfileManager::GetActiveUserProfile()) {
325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Do not pop-up the File Manager, if the recovery tool is running.
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (IsRecoveryToolRunning(profile))
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If the disable-default-apps flag is on, Files.app is not opened
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // automatically on device mount not to obstruct the manual test.
334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (CommandLine::ForCurrentProcess()->HasSwitch(
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          switches::kDisableDefaultApps)) {
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Sub-part of the event router for handling device events.
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass DeviceEventRouterImpl : public DeviceEventRouter {
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  explicit DeviceEventRouterImpl(Profile* profile) : profile_(profile) {}
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // DeviceEventRouter overrides.
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnDeviceEvent(file_manager_private::DeviceEventType type,
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             const std::string& device_path) OVERRIDE {
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_CURRENTLY_ON(BrowserThread::UI);
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    file_manager_private::DeviceEvent event;
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event.type = type;
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event.device_path = device_path;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BroadcastEvent(profile_,
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   file_manager_private::OnDeviceChanged::kEventName,
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   file_manager_private::OnDeviceChanged::Create(event));
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // DeviceEventRouter overrides.
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool IsExternalStorageDisabled() OVERRIDE {
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_CURRENTLY_ON(BrowserThread::UI);
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled);
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Profile* const profile_;
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(DeviceEventRouterImpl);
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Pass dummy value to JobInfo's constructor for make it default constructible.
3762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochEventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus()
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : job_info(drive::TYPE_DOWNLOAD_FILE) {
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochEventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus(
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const drive::JobInfo& info, const std::string& status)
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : job_info(info), status(status) {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)EventRouter::EventRouter(Profile* profile)
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : pref_change_registrar_(new PrefChangeRegistrar),
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      device_event_router_(new DeviceEventRouterImpl(profile)),
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ObserveEvents();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochEventRouter::~EventRouter() {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::Shutdown() {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DLOG_IF(WARNING, !file_watchers_.empty())
4012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      << "Not all file watchers are "
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "removed. This can happen when Files.app is open during shutdown.";
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&file_watchers_);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pref_change_registrar_->RemoveAll();
410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
411d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (NetworkHandler::IsInitialized()) {
412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                                   FROM_HERE);
414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DriveIntegrationService* const integration_service =
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DriveIntegrationServiceFactory::FindForProfile(profile_);
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (integration_service) {
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->file_system()->RemoveObserver(this);
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->drive_service()->RemoveObserver(this);
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->job_list()->RemoveObserver(this);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VolumeManager* const volume_manager = VolumeManager::Get(profile_);
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (volume_manager) {
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    volume_manager->RemoveObserver(this);
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    volume_manager->RemoveObserver(device_event_router_.get());
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  chromeos::PowerManagerClient* const power_manager_client =
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  power_manager_client->RemoveObserver(device_event_router_.get());
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_ = NULL;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EventRouter::ObserveEvents() {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!chromeos::LoginState::IsInitialized() ||
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !chromeos::LoginState::Get()->IsUserLoggedIn()) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Ignore device events for the first few seconds.
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  device_event_router_->Startup();
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // VolumeManager's construction triggers DriveIntegrationService's
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // construction, so it is necessary to call VolumeManager's Get before
452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // accessing DriveIntegrationService.
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VolumeManager* const volume_manager = VolumeManager::Get(profile_);
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (volume_manager) {
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    volume_manager->AddObserver(this);
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    volume_manager->AddObserver(device_event_router_.get());
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  chromeos::PowerManagerClient* const power_manager_client =
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  power_manager_client->AddObserver(device_event_router_.get());
462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DriveIntegrationService* const integration_service =
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DriveIntegrationServiceFactory::FindForProfile(profile_);
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (integration_service) {
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->drive_service()->AddObserver(this);
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->file_system()->AddObserver(this);
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    integration_service->job_list()->AddObserver(this);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (NetworkHandler::IsInitialized()) {
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NetworkHandler::Get()->network_state_handler()->AddObserver(this,
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                                                FROM_HERE);
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_->Init(profile_->GetPrefs());
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure callback =
4782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      base::Bind(&EventRouter::OnFileManagerPrefsChanged,
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_factory_.GetWeakPtr());
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pref_change_registrar_->Add(prefs::kDisableDriveOverCellular, callback);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pref_change_registrar_->Add(prefs::kDisableDriveHostedFiles, callback);
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pref_change_registrar_->Add(prefs::kDisableDrive, callback);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pref_change_registrar_->Add(prefs::kUse24HourClock, callback);
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  notification_registrar_.Add(this,
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              chrome::NOTIFICATION_PROFILE_ADDED,
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              content::NotificationService::AllSources());
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// File watch setup routines.
4912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::AddFileWatch(const base::FilePath& local_path,
4922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               const base::FilePath& virtual_path,
4932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               const std::string& extension_id,
4942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               const BoolCallback& callback) {
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath watch_path = local_path;
499bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  bool is_on_drive = drive::util::IsUnderDriveMountPoint(watch_path);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tweak watch path for remote sources - we need to drop leading /special
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directory from there in order to be able to pair these events with
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // their change notifications.
503bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (is_on_drive)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watch_path = drive::util::ExtractDrivePath(watch_path);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WatcherMap::iterator iter = file_watchers_.find(watch_path);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == file_watchers_.end()) {
508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    scoped_ptr<FileWatcher> watcher(new FileWatcher(virtual_path));
509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    watcher->AddExtension(extension_id);
510bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
511bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (is_on_drive) {
512bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      // For Drive, file watching is done via OnDirectoryChanged().
513bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      base::MessageLoopProxy::current()->PostTask(FROM_HERE,
514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                                  base::Bind(callback, true));
515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    } else {
516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      // For local files, start watching using FileWatcher.
517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      watcher->WatchLocalFile(
518bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch          watch_path,
519bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch          base::Bind(&EventRouter::HandleFileWatchNotification,
520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     weak_factory_.GetWeakPtr(),
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     static_cast<drive::FileChange*>(NULL)),
522bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch          callback);
523bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
524bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
5252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    file_watchers_[watch_path] = watcher.release();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->second->AddExtension(extension_id);
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(FROM_HERE,
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                base::Bind(callback, true));
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::RemoveFileWatch(const base::FilePath& local_path,
5342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  const std::string& extension_id) {
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath watch_path = local_path;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tweak watch path for remote sources - we need to drop leading /special
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directory from there in order to be able to pair these events with
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // their change notifications.
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (drive::util::IsUnderDriveMountPoint(watch_path)) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watch_path = drive::util::ExtractDrivePath(watch_path);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WatcherMap::iterator iter = file_watchers_.find(watch_path);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == file_watchers_.end())
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
547bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Remove the watcher if |watch_path| is no longer watched by any extensions.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second->RemoveExtension(extension_id);
549bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (iter->second->GetExtensionIds().empty()) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete iter->second;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_watchers_.erase(iter);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void EventRouter::OnCopyCompleted(int copy_id,
55668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                  const GURL& source_url,
55768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                  const GURL& destination_url,
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  base::File::Error error) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::CopyProgressStatus status;
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error == base::File::FILE_OK) {
56358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Send success event.
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    status.type = file_manager_private::COPY_PROGRESS_STATUS_TYPE_SUCCESS;
56568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    status.source_url.reset(new std::string(source_url.spec()));
56668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    status.destination_url.reset(new std::string(destination_url.spec()));
56758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
56858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Send error event.
5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    status.type = file_manager_private::COPY_PROGRESS_STATUS_TYPE_ERROR;
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    status.error.reset(new std::string(FileErrorToErrorName(error)));
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  BroadcastEvent(
57458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      profile_,
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnCopyProgress::kEventName,
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnCopyProgress::Create(copy_id, status));
577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void EventRouter::OnCopyProgress(
580d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int copy_id,
58103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::FileSystemOperation::CopyProgressType type,
58268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const GURL& source_url,
58368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const GURL& destination_url,
584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int64 size) {
585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::CopyProgressStatus status;
588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  status.type = CopyProgressTypeToCopyProgressStatusType(type);
58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  status.source_url.reset(new std::string(source_url.spec()));
59003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (type == storage::FileSystemOperation::END_COPY_ENTRY)
59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    status.destination_url.reset(new std::string(destination_url.spec()));
59203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (type == storage::FileSystemOperation::PROGRESS)
593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    status.size.reset(new double(size));
594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Should not skip events other than TYPE_PROGRESS.
596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const bool always =
5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      status.type != file_manager_private::COPY_PROGRESS_STATUS_TYPE_PROGRESS;
598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!ShouldSendProgressEvent(always, &last_copy_progress_event_))
599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
600c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  BroadcastEvent(
602d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      profile_,
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnCopyProgress::kEventName,
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnCopyProgress::Create(copy_id, status));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
607d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void EventRouter::DefaultNetworkChanged(const chromeos::NetworkState* network) {
6080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!profile_ || !extensions::EventRouter::Get(profile_)) {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
61258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  BroadcastEvent(
61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      profile_,
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveConnectionStatusChanged::kEventName,
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveConnectionStatusChanged::Create());
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnFileManagerPrefsChanged() {
6200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!profile_ || !extensions::EventRouter::Get(profile_)) {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  BroadcastEvent(
62658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      profile_,
6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnPreferencesChanged::kEventName,
6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnPreferencesChanged::Create());
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnJobAdded(const drive::JobInfo& job_info) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!drive::IsActiveFileTransferJobInfo(job_info))
6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScheduleDriveFileTransferEvent(
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      job_info, kFileTransferStateAdded, false /* immediate */);
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnJobUpdated(const drive::JobInfo& job_info) {
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!drive::IsActiveFileTransferJobInfo(job_info))
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool is_new_job = (drive_jobs_.find(job_info.job_id) == drive_jobs_.end());
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::string status =
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      is_new_job ? kFileTransferStateStarted : kFileTransferStateInProgress;
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Replace with the latest job info.
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  drive_jobs_[job_info.job_id] = DriveJobInfoWithStatus(job_info, status);
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScheduleDriveFileTransferEvent(job_info, status, false /* immediate */);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnJobDone(const drive::JobInfo& job_info,
6562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                            drive::FileError error) {
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
65890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!drive::IsActiveFileTransferJobInfo(job_info))
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::string status = error == drive::FILE_ERROR_OK
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 ? kFileTransferStateCompleted
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 : kFileTransferStateFailed;
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScheduleDriveFileTransferEvent(job_info, status, true /* immediate */);
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Forget about the job.
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  drive_jobs_.erase(job_info.job_id);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EventRouter::ScheduleDriveFileTransferEvent(const drive::JobInfo& job_info,
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 const std::string& status,
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 bool immediate) {
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool no_pending_task = !drive_job_info_for_scheduled_event_;
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Update the latest event.
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  drive_job_info_for_scheduled_event_.reset(
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new DriveJobInfoWithStatus(job_info, status));
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (immediate) {
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SendDriveFileTransferEvent();
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (no_pending_task) {
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::TimeDelta delay = base::TimeDelta::FromMilliseconds(
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        kFileTransferEventDelayTimeInMilliseconds);
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&EventRouter::SendDriveFileTransferEvent,
6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_factory_.GetWeakPtr()),
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        delay);
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EventRouter::SendDriveFileTransferEvent() {
6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!drive_job_info_for_scheduled_event_)
693c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::FileTransferStatus status;
6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  JobInfoToTransferStatus(profile_,
6971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          kFileManagerAppId,
6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          drive_job_info_for_scheduled_event_->status,
6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          drive_job_info_for_scheduled_event_->job_info,
7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          &status);
7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  drive_job_info_for_scheduled_event_.reset();
7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BroadcastEvent(profile_,
7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnFileTransfersUpdated::kEventName,
7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnFileTransfersUpdated::Create(status));
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EventRouter::OnDirectoryChanged(const base::FilePath& drive_path) {
710116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  HandleFileWatchNotification(NULL, drive_path, false);
711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
713116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRouter::OnFileChanged(const drive::FileChange& changed_files) {
714116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typedef std::map<base::FilePath, drive::FileChange> FileChangeMap;
715116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
716116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileChangeMap map;
717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const drive::FileChange::Map& changed_file_map = changed_files.map();
718116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (drive::FileChange::Map::const_iterator it = changed_file_map.begin();
719116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != changed_file_map.end();
720116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it++) {
721116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::FilePath& path = it->first;
722116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    map[path.DirName()].Update(path, it->second);
723116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
724116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (FileChangeMap::const_iterator it = map.begin(); it != map.end(); it++) {
726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    HandleFileWatchNotification(&(it->second), it->first, false);
727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EventRouter::OnDriveSyncError(drive::file_system::DriveSyncErrorType type,
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   const base::FilePath& drive_path) {
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::DriveSyncErrorEvent event;
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (type) {
7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case drive::file_system::DRIVE_SYNC_ERROR_DELETE_WITHOUT_PERMISSION:
7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type =
7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          file_manager_private::DRIVE_SYNC_ERROR_TYPE_DELETE_WITHOUT_PERMISSION;
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case drive::file_system::DRIVE_SYNC_ERROR_SERVICE_UNAVAILABLE:
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type =
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          file_manager_private::DRIVE_SYNC_ERROR_TYPE_SERVICE_UNAVAILABLE;
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case drive::file_system::DRIVE_SYNC_ERROR_MISC:
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event.type =
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          file_manager_private::DRIVE_SYNC_ERROR_TYPE_MISC;
7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  event.file_url = util::ConvertDrivePathToFileSystemUrl(
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_, drive_path, kFileManagerAppId).spec();
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BroadcastEvent(
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_,
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveSyncError::kEventName,
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveSyncError::Create(event));
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnRefreshTokenInvalid() {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Raise a DriveConnectionStatusChanged event to notify the status offline.
75958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  BroadcastEvent(
76058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      profile_,
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveConnectionStatusChanged::kEventName,
7621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::OnDriveConnectionStatusChanged::Create());
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRouter::HandleFileWatchNotification(const drive::FileChange* list,
766116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                              const base::FilePath& local_path,
7672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                              bool got_error) {
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WatcherMap::const_iterator iter = file_watchers_.find(local_path);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == file_watchers_.end()) {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (list && list->size() > kDirectoryChangeEventMaxDetailInfoSize) {
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Removes the detailed information, if the list size is more than
777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // kDirectoryChangeEventMaxDetailInfoSize, since passing large list
778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // and processing it may cause more itme.
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // This will be invoked full-refresh in Files.app.
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    list = NULL;
781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DispatchDirectoryChangeEvent(iter->second->virtual_path(),
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               list,
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               got_error,
786bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                               iter->second->GetExtensionIds());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::DispatchDirectoryChangeEvent(
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& virtual_path,
791116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const drive::FileChange* list,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool got_error,
793bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    const std::vector<std::string>& extension_ids) {
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  linked_ptr<drive::FileChange> changes;
799116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (list)
800116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    changes.reset(new drive::FileChange(*list));  // Copy
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  for (size_t i = 0; i < extension_ids.size(); ++i) {
803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::string* extension_id = new std::string(extension_ids[i]);
804a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
805a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FileDefinition file_definition;
806a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition.virtual_path = virtual_path;
807a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition.is_directory = true;
808a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
809a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_manager::util::ConvertFileDefinitionToEntryDefinition(
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        profile_,
811116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        *extension_id,
812a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        file_definition,
813a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(
814a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            &EventRouter::DispatchDirectoryChangeEventWithEntryDefinition,
815a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            weak_factory_.GetWeakPtr(),
816116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            changes,
817116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            base::Owned(extension_id),
818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            got_error));
819a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
820a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
821a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
822a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void EventRouter::DispatchDirectoryChangeEventWithEntryDefinition(
823116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const linked_ptr<drive::FileChange> list,
824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string* extension_id,
825a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool watcher_error,
826a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const EntryDefinition& entry_definition) {
827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typedef std::map<base::FilePath, drive::FileChange::ChangeList> ChangeListMap;
828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (entry_definition.error != base::File::FILE_OK ||
830cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      !entry_definition.is_directory) {
831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(1) << "Unable to dispatch event because resolving the directory "
832cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             << "entry definition failed.";
833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::FileWatchEvent event;
837a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event.event_type = watcher_error
8381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ? file_manager_private::FILE_WATCH_EVENT_TYPE_ERROR
8391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : file_manager_private::FILE_WATCH_EVENT_TYPE_CHANGED;
840a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
841116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Detailed information is available.
842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (list.get()) {
843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    event.changed_files.reset(
8441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new std::vector<linked_ptr<file_manager_private::FileChange> >);
845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
846116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (list->map().empty())
847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
848116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (drive::FileChange::Map::const_iterator it = list->map().begin();
850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         it != list->map().end();
851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         it++) {
8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      linked_ptr<file_manager_private::FileChange> change_list(
8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          new file_manager_private::FileChange);
854116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
855116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GURL url = util::ConvertDrivePathToFileSystemUrl(
856116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          profile_, it->first, *extension_id);
857116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      change_list->url = url.spec();
858116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
859116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      for (drive::FileChange::ChangeList::List::const_iterator change =
860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               it->second.list().begin();
861116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           change != it->second.list().end();
862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           change++) {
863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        change_list->changes.push_back(
864116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            ConvertChangeTypeFromDriveToApi(change->change()));
865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
867116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      event.changed_files->push_back(change_list);
868116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
869116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
870116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
871a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event.entry.additional_properties.SetString(
872a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "fileSystemName", entry_definition.file_system_name);
873a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event.entry.additional_properties.SetString(
874a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "fileSystemRoot", entry_definition.file_system_root_url);
875a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event.entry.additional_properties.SetString(
876a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "fileFullPath", "/" + entry_definition.full_path.value());
877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event.entry.additional_properties.SetBoolean("fileIsDirectory",
878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               entry_definition.is_directory);
879a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
880a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BroadcastEvent(profile_,
8811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnDirectoryChanged::kEventName,
8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnDirectoryChanged::Create(event));
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void EventRouter::OnDiskAdded(
88658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const DiskMountManager::Disk& disk, bool mounting) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
8881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do nothing.
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void EventRouter::OnDiskRemoved(const DiskMountManager::Disk& disk) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
89358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Do nothing.
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnDeviceAdded(const std::string& device_path) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
8981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do nothing.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
901116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRouter::OnDeviceRemoved(const std::string& device_path) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
9031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do nothing.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void EventRouter::OnVolumeMounted(chromeos::MountError error_code,
9071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  const VolumeInfo& volume_info) {
90858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // profile_ is NULL if ShutdownOnUIThread() is called earlier. This can
91058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // happen at shutdown. This should be removed after removing Drive mounting
91158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // code in addMount. (addMount -> OnFileSystemMounted -> OnVolumeMounted is
91258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the only path to come here after Shutdown is called).
91358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!profile_)
91458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
9151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DispatchMountCompletedEvent(
9171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::MOUNT_COMPLETED_EVENT_TYPE_MOUNT,
9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error_code,
9191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      volume_info);
92058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
92158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
92258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void EventRouter::OnVolumeUnmounted(chromeos::MountError error_code,
92358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                    const VolumeInfo& volume_info) {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DispatchMountCompletedEvent(
9261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_manager_private::MOUNT_COMPLETED_EVENT_TYPE_UNMOUNT,
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error_code,
9281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      volume_info);
929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
931116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid EventRouter::DispatchMountCompletedEvent(
9321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    file_manager_private::MountCompletedEventType event_type,
933116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    chromeos::MountError error,
9341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const VolumeInfo& volume_info) {
935116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Build an event object.
9361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  file_manager_private::MountCompletedEvent event;
937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event.event_type = event_type;
938116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event.status = MountErrorToMountCompletedStatus(error);
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  util::VolumeInfoToVolumeMetadata(
940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      profile_, volume_info, &event.volume_metadata);
941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event.should_notify = ShouldShowNotificationForVolume(
9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      profile_, *device_event_router_, volume_info);
943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BroadcastEvent(profile_,
9441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnMountCompleted::kEventName,
9451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 file_manager_private::OnMountCompleted::Create(event));
946116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
947116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
9482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnFormatStarted(const std::string& device_path,
9492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                  bool success) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
9511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do nothing.
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid EventRouter::OnFormatCompleted(const std::string& device_path,
9552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                    bool success) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
9571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Do nothing.
9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void EventRouter::Observe(int type,
9615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const content::NotificationSource& source,
9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const content::NotificationDetails& details) {
9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == chrome::NOTIFICATION_PROFILE_ADDED) {
9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* const added_profile = content::Source<Profile>(source).ptr();
9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!added_profile->IsOffTheRecord())
9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GrantAccessForAddedProfileToRunningInstance(added_profile, profile_);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
969a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
970a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace file_manager
971