1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/extensions/file_browser_event_router.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_writer.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/stl_util-inl.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/values.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/cros/cros_library.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/login/user_manager.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/notifications/system_notification.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_event_names.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_event_router.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/file_manager_util.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/generated_resources.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/theme_resources.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/l10n/l10n_util.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kDiskAddedEventType[] = "added";
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kDiskRemovedEventType[] = "removed";
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char* DeviceTypeToString(chromeos::DeviceType type) {
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (type) {
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case chromeos::FLASH:
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return "flash";
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case chromeos::HDD:
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return "hdd";
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case chromeos::OPTICAL:
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return "optical";
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return "undefined";
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDictionaryValue* DiskToDictionaryValue(
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk) {
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* result = new DictionaryValue();
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->SetString("mountPath", disk->mount_path());
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->SetString("label", disk->device_label());
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->SetString("deviceType", DeviceTypeToString(disk->device_type()));
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->SetInteger("totalSizeKB", disk->total_size() / 1024);
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result->SetBoolean("readOnly", disk->is_read_only());
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result;
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionFileBrowserEventRouter::ExtensionFileBrowserEventRouter()
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : profile_(NULL) {
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionFileBrowserEventRouter::~ExtensionFileBrowserEventRouter() {
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::ObserveFileSystemEvents(
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Profile* profile) {
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!profile)
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  profile_ = profile;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!chromeos::CrosLibrary::Get()->EnsureLoaded())
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (chromeos::UserManager::Get()->user_is_logged_in()) {
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    chromeos::MountLibrary* lib =
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        chromeos::CrosLibrary::Get()->GetMountLibrary();
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    lib->RemoveObserver(this);
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    lib->AddObserver(this);
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    lib->RequestMountInfoRefresh();
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::StopObservingFileSystemEvents() {
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!profile_)
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!chromeos::CrosLibrary::Get()->EnsureLoaded())
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  chromeos::MountLibrary* lib =
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      chromeos::CrosLibrary::Get()->GetMountLibrary();
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  lib->RemoveObserver(this);
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  profile_ = NULL;
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionFileBrowserEventRouter*
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExtensionFileBrowserEventRouter::GetInstance() {
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return Singleton<ExtensionFileBrowserEventRouter>::get();
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::DiskChanged(
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    chromeos::MountLibraryEventType event,
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk) {
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (event == chromeos::MOUNT_DISK_ADDED) {
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDiskAdded(disk);
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (event == chromeos::MOUNT_DISK_REMOVED) {
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDiskRemoved(disk);
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (event == chromeos::MOUNT_DISK_CHANGED) {
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDiskChanged(disk);
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::DeviceChanged(
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    chromeos::MountLibraryEventType event,
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& device_path) {
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (event == chromeos::MOUNT_DEVICE_ADDED) {
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDeviceAdded(device_path);
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (event == chromeos::MOUNT_DEVICE_REMOVED) {
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDeviceRemoved(device_path);
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (event == chromeos::MOUNT_DEVICE_SCANNED) {
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDeviceScanned(device_path);
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::DispatchEvent(
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk, bool added) {
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!profile_) {
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue args;
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* mount_info = new DictionaryValue();
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args.Append(mount_info);
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  mount_info->SetString("eventType",
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                        added ? kDiskAddedEventType : kDiskRemovedEventType);
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* disk_info = DiskToDictionaryValue(disk);
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  mount_info->Set("volumeInfo", disk_info);
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string args_json;
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_event_names::kOnFileBrowserDiskChanged, args_json, NULL,
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GURL());
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDiskAdded(
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk) {
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(1) << "Disk added: " << disk->device_path();
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (disk->device_path().empty()) {
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    VLOG(1) << "Empty system path for " << disk->device_path();
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (disk->is_parent()) {
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!disk->has_media())
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      HideDeviceNotification(disk->system_path());
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If disk is not mounted yet, give it a try.
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (disk->mount_path().empty()) {
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Initiate disk mount operation.
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    chromeos::MountLibrary* lib =
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        chromeos::CrosLibrary::Get()->GetMountLibrary();
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    lib->MountPath(disk->device_path().c_str());
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDiskRemoved(
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk) {
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(1) << "Disk removed: " << disk->device_path();
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HideDeviceNotification(disk->system_path());
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MountPointMap::iterator iter = mounted_devices_.find(disk->device_path());
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter == mounted_devices_.end())
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  chromeos::MountLibrary* lib =
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      chromeos::CrosLibrary::Get()->GetMountLibrary();
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(zelidrag): This for some reason does not work as advertized.
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // we might need to clean up mount directory on FILE thread here as well.
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  lib->UnmountPath(disk->device_path().c_str());
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DispatchEvent(disk, false);
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  mounted_devices_.erase(iter);
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDiskChanged(
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const chromeos::MountLibrary::Disk* disk) {
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(1) << "Disk changed : " << disk->device_path();
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!disk->mount_path().empty()) {
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    HideDeviceNotification(disk->system_path());
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Remember this mount point.
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (mounted_devices_.find(disk->device_path()) == mounted_devices_.end()) {
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      mounted_devices_.insert(
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          std::pair<std::string, std::string>(disk->device_path(),
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                              disk->mount_path()));
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DispatchEvent(disk, true);
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      HideDeviceNotification(disk->system_path());
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      FileManagerUtil::ShowFullTabUrl(profile_, FilePath(disk->mount_path()));
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDeviceAdded(
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& device_path) {
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(1) << "Device added : " << device_path;
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(zelidrag): Find better icon here.
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ShowDeviceNotification(device_path, IDR_PAGEINFO_INFO,
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE));
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDeviceRemoved(
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& system_path) {
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HideDeviceNotification(system_path);
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::OnDeviceScanned(
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& device_path) {
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(1) << "Device scanned : " << device_path;
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::ShowDeviceNotification(
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& system_path, int icon_resource_id,
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const string16& message) {
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NotificationMap::iterator iter = FindNotificationForPath(system_path);
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string mount_path;
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter != notifications_.end()) {
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    iter->second->Show(message, false, false);
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!profile_) {
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED();
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    chromeos::SystemNotification* notification =
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new chromeos::SystemNotification(
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            profile_,
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            system_path,
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            icon_resource_id,
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_DETECTION_TITLE));
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    notifications_.insert(NotificationMap::value_type(system_path,
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        linked_ptr<chromeos::SystemNotification>(notification)));
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    notification->Show(message, false, false);
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionFileBrowserEventRouter::HideDeviceNotification(
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& system_path) {
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NotificationMap::iterator iter = FindNotificationForPath(system_path);
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter != notifications_.end()) {
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    iter->second->Hide();
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    notifications_.erase(iter);
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionFileBrowserEventRouter::NotificationMap::iterator
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExtensionFileBrowserEventRouter::FindNotificationForPath(
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        const std::string& system_path) {
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (NotificationMap::iterator iter = notifications_.begin();
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != notifications_.end();
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& notification_device_path = iter->first;
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Doing a sub string match so that we find if this new one is a subdevice
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // of another already inserted device.
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (StartsWithASCII(system_path, notification_device_path, true)) {
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return iter;
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return notifications_.end();
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
260