Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: chrome/browser/chromeos/extensions/file_browser_event_router.cc

Issue 7471024: Formatting feature initial commit for ChromeOS Tree (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/extensions/file_browser_event_router.h" 5 #include "chrome/browser/chromeos/extensions/file_browser_event_router.h"
6 6
7 #include "base/bind.h"
7 #include "base/json/json_writer.h" 8 #include "base/json/json_writer.h"
8 #include "base/memory/singleton.h" 9 #include "base/memory/singleton.h"
10 #include "base/message_loop.h"
9 #include "base/stl_util.h" 11 #include "base/stl_util.h"
10 #include "base/values.h" 12 #include "base/values.h"
11 #include "chrome/browser/chromeos/cros/cros_library.h" 13 #include "chrome/browser/chromeos/cros/cros_library.h"
12 #include "chrome/browser/chromeos/login/user_manager.h" 14 #include "chrome/browser/chromeos/login/user_manager.h"
13 #include "chrome/browser/chromeos/notifications/system_notification.h" 15 #include "chrome/browser/chromeos/notifications/system_notification.h"
14 #include "chrome/browser/extensions/extension_event_names.h" 16 #include "chrome/browser/extensions/extension_event_names.h"
15 #include "chrome/browser/extensions/extension_event_router.h" 17 #include "chrome/browser/extensions/extension_event_router.h"
16 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/extensions/file_manager_util.h" 19 #include "chrome/browser/extensions/file_manager_util.h"
18 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
19 #include "content/browser/browser_thread.h" 21 #include "content/browser/browser_thread.h"
20 #include "grit/generated_resources.h" 22 #include "grit/generated_resources.h"
21 #include "grit/theme_resources.h" 23 #include "grit/theme_resources.h"
22 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
23 #include "webkit/fileapi/file_system_types.h" 25 #include "webkit/fileapi/file_system_types.h"
24 #include "webkit/fileapi/file_system_util.h" 26 #include "webkit/fileapi/file_system_util.h"
25 27
26 const char kDiskAddedEventType[] = "added"; 28 namespace {
27 const char kDiskRemovedEventType[] = "removed"; 29 const char kDiskAddedEventType[] = "added";
30 const char kDiskRemovedEventType[] = "removed";
28 31
29 const char kPathChanged[] = "changed"; 32 const char kPathChanged[] = "changed";
30 const char kPathWatchError[] = "error"; 33 const char kPathWatchError[] = "error";
31 34
32 const char* DeviceTypeToString(chromeos::DeviceType type) { 35 const char* DeviceTypeToString(chromeos::DeviceType type) {
33 switch (type) { 36 switch (type) {
34 case chromeos::FLASH: 37 case chromeos::FLASH:
35 return "flash"; 38 return "flash";
36 case chromeos::HDD: 39 case chromeos::HDD:
37 return "hdd"; 40 return "hdd";
38 case chromeos::OPTICAL: 41 case chromeos::OPTICAL:
39 return "optical"; 42 return "optical";
40 default: 43 default:
41 break; 44 break;
45 }
46 return "undefined";
42 } 47 }
43 return "undefined"; 48
49 DictionaryValue* DiskToDictionaryValue(
50 const chromeos::MountLibrary::Disk* disk) {
51 DictionaryValue* result = new DictionaryValue();
52 result->SetString("mountPath", disk->mount_path());
53 result->SetString("devicePath", disk->device_path());
54 result->SetString("label", disk->device_label());
55 result->SetString("deviceType", DeviceTypeToString(disk->device_type()));
56 result->SetInteger("totalSizeKB", disk->total_size() / 1024);
57 result->SetBoolean("readOnly", disk->is_read_only());
58 return result;
59 }
44 } 60 }
45 61
46 DictionaryValue* DiskToDictionaryValue( 62 void HideFileBrowserNotificationExternally(const std::string& cathegory,
47 const chromeos::MountLibrary::Disk* disk) { 63 const std::string& system_path, ExtensionFileBrowserEventRouter* that) {
48 DictionaryValue* result = new DictionaryValue(); 64 that->HideFileBrowserNotification(cathegory, system_path);
49 result->SetString("mountPath", disk->mount_path());
50 result->SetString("devicePath", disk->device_path());
51 result->SetString("label", disk->device_label());
52 result->SetString("deviceType", DeviceTypeToString(disk->device_type()));
53 result->SetInteger("totalSizeKB", disk->total_size() / 1024);
54 result->SetBoolean("readOnly", disk->is_read_only());
55 return result;
56 } 65 }
57 66
58 ExtensionFileBrowserEventRouter::ExtensionFileBrowserEventRouter() 67 ExtensionFileBrowserEventRouter::ExtensionFileBrowserEventRouter()
59 : delegate_(new ExtensionFileBrowserEventRouter::FileWatcherDelegate()), 68 : delegate_(new ExtensionFileBrowserEventRouter::FileWatcherDelegate()),
60 profile_(NULL) { 69 profile_(NULL) {
61 } 70 }
62 71
63 ExtensionFileBrowserEventRouter::~ExtensionFileBrowserEventRouter() { 72 ExtensionFileBrowserEventRouter::~ExtensionFileBrowserEventRouter() {
64 DCHECK(file_watchers_.empty()); 73 DCHECK(file_watchers_.empty());
65 STLDeleteValues(&file_watchers_); 74 STLDeleteValues(&file_watchers_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 155
147 void ExtensionFileBrowserEventRouter::DiskChanged( 156 void ExtensionFileBrowserEventRouter::DiskChanged(
148 chromeos::MountLibraryEventType event, 157 chromeos::MountLibraryEventType event,
149 const chromeos::MountLibrary::Disk* disk) { 158 const chromeos::MountLibrary::Disk* disk) {
150 if (event == chromeos::MOUNT_DISK_ADDED) { 159 if (event == chromeos::MOUNT_DISK_ADDED) {
151 OnDiskAdded(disk); 160 OnDiskAdded(disk);
152 } else if (event == chromeos::MOUNT_DISK_REMOVED) { 161 } else if (event == chromeos::MOUNT_DISK_REMOVED) {
153 OnDiskRemoved(disk); 162 OnDiskRemoved(disk);
154 } else if (event == chromeos::MOUNT_DISK_CHANGED) { 163 } else if (event == chromeos::MOUNT_DISK_CHANGED) {
155 OnDiskChanged(disk); 164 OnDiskChanged(disk);
165 } else if (event == chromeos::MOUNT_DISK_MOUNTED) {
166 OnDiskMounted(disk);
167 } else if (event == chromeos::MOUNT_DISK_UNMOUNTED) {
168 OnDiskUnmounted(disk);
156 } 169 }
157 } 170 }
158 171
159 void ExtensionFileBrowserEventRouter::DeviceChanged( 172 void ExtensionFileBrowserEventRouter::DeviceChanged(
160 chromeos::MountLibraryEventType event, 173 chromeos::MountLibraryEventType event,
161 const std::string& device_path) { 174 const std::string& device_path) {
162 if (event == chromeos::MOUNT_DEVICE_ADDED) { 175 if (event == chromeos::MOUNT_DEVICE_ADDED) {
163 OnDeviceAdded(device_path); 176 OnDeviceAdded(device_path);
164 } else if (event == chromeos::MOUNT_DEVICE_REMOVED) { 177 } else if (event == chromeos::MOUNT_DEVICE_REMOVED) {
165 OnDeviceRemoved(device_path); 178 OnDeviceRemoved(device_path);
166 } else if (event == chromeos::MOUNT_DEVICE_SCANNED) { 179 } else if (event == chromeos::MOUNT_DEVICE_SCANNED) {
167 OnDeviceScanned(device_path); 180 OnDeviceScanned(device_path);
181 } else if (event == chromeos::MOUNT_FORMATTING_STARTED) {
182 OnFormattingStarted(device_path);
183 } else if (event == chromeos::MOUNT_FORMATTING_FINISHED) {
184 OnFormattingFinished(device_path);
168 } 185 }
169 } 186 }
170 187
171 void ExtensionFileBrowserEventRouter::HandleFileWatchNotification( 188 void ExtensionFileBrowserEventRouter::HandleFileWatchNotification(
172 const FilePath& local_path, bool got_error) { 189 const FilePath& local_path, bool got_error) {
173 base::AutoLock lock(lock_); 190 base::AutoLock lock(lock_);
174 WatcherMap::const_iterator iter = file_watchers_.find(local_path); 191 WatcherMap::const_iterator iter = file_watchers_.find(local_path);
175 if (iter == file_watchers_.end()) { 192 if (iter == file_watchers_.end()) {
176 NOTREACHED(); 193 NOTREACHED();
177 return; 194 return;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 DictionaryValue* disk_info = DiskToDictionaryValue(disk); 243 DictionaryValue* disk_info = DiskToDictionaryValue(disk);
227 mount_info->Set("volumeInfo", disk_info); 244 mount_info->Set("volumeInfo", disk_info);
228 245
229 std::string args_json; 246 std::string args_json;
230 base::JSONWriter::Write(&args, false /* pretty_print */, &args_json); 247 base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
231 profile_->GetExtensionEventRouter()->DispatchEventToRenderers( 248 profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
232 extension_event_names::kOnFileBrowserDiskChanged, args_json, NULL, 249 extension_event_names::kOnFileBrowserDiskChanged, args_json, NULL,
233 GURL()); 250 GURL());
234 } 251 }
235 252
253
236 void ExtensionFileBrowserEventRouter::OnDiskAdded( 254 void ExtensionFileBrowserEventRouter::OnDiskAdded(
237 const chromeos::MountLibrary::Disk* disk) { 255 const chromeos::MountLibrary::Disk* disk) {
238 VLOG(1) << "Disk added: " << disk->device_path(); 256 VLOG(1) << "Disk added: " << disk->device_path();
239 if (disk->device_path().empty()) { 257 if (disk->device_path().empty()) {
240 VLOG(1) << "Empty system path for " << disk->device_path(); 258 VLOG(1) << "Empty system path for " << disk->device_path();
241 return; 259 return;
242 } 260 }
243 if (disk->is_parent()) { 261 if (disk->is_parent()) {
244 if (!disk->has_media()) { 262 if (!disk->has_media()) {
245 HideDeviceNotification(disk->system_path()); 263 HideFileBrowserNotification("MOUNT", disk->system_path());
246 return; 264 return;
247 } 265 }
248 } 266 }
249 267
250 // If disk is not mounted yet, give it a try. 268 // If disk is not mounted yet, give it a try.
251 if (disk->mount_path().empty()) { 269 if (disk->mount_path().empty()) {
252 // Initiate disk mount operation. 270 // Initiate disk mount operation.
253 chromeos::MountLibrary* lib = 271 chromeos::MountLibrary* lib =
254 chromeos::CrosLibrary::Get()->GetMountLibrary(); 272 chromeos::CrosLibrary::Get()->GetMountLibrary();
255 lib->MountPath(disk->device_path().c_str()); 273 lib->MountPath(disk->device_path().c_str());
256 } 274 }
275 DispatchMountEvent(disk, true);
257 } 276 }
258 277
259 void ExtensionFileBrowserEventRouter::OnDiskRemoved( 278 void ExtensionFileBrowserEventRouter::OnDiskRemoved(
260 const chromeos::MountLibrary::Disk* disk) { 279 const chromeos::MountLibrary::Disk* disk) {
261 VLOG(1) << "Disk removed: " << disk->device_path(); 280 VLOG(1) << "Disk removed: " << disk->device_path();
262 HideDeviceNotification(disk->system_path()); 281 HideFileBrowserNotification("MOUNT", disk->system_path());
263 MountPointMap::iterator iter = mounted_devices_.find(disk->device_path()); 282 MountPointMap::iterator iter = mounted_devices_.find(disk->device_path());
264 if (iter == mounted_devices_.end()) 283 if (iter == mounted_devices_.end())
265 return; 284 return;
266 285
267 chromeos::MountLibrary* lib = 286 chromeos::MountLibrary* lib =
268 chromeos::CrosLibrary::Get()->GetMountLibrary(); 287 chromeos::CrosLibrary::Get()->GetMountLibrary();
269 // TODO(zelidrag): This for some reason does not work as advertized. 288 // TODO(zelidrag): This for some reason does not work as advertized.
270 // we might need to clean up mount directory on FILE thread here as well. 289 // we might need to clean up mount directory on FILE thread here as well.
271 lib->UnmountPath(disk->device_path().c_str()); 290 lib->UnmountPath(disk->device_path().c_str());
272
273 DispatchMountEvent(disk, false); 291 DispatchMountEvent(disk, false);
274 mounted_devices_.erase(iter); 292 mounted_devices_.erase(iter);
275 } 293 }
276 294
277 void ExtensionFileBrowserEventRouter::OnDiskChanged( 295 void ExtensionFileBrowserEventRouter::OnDiskChanged(
278 const chromeos::MountLibrary::Disk* disk) { 296 const chromeos::MountLibrary::Disk* disk) {
279 VLOG(1) << "Disk changed : " << disk->device_path(); 297 VLOG(1) << "Disk changed : " << disk->device_path();
280 if (!disk->mount_path().empty()) { 298 if (!disk->mount_path().empty()) {
281 HideDeviceNotification(disk->system_path()); 299 HideFileBrowserNotification("MOUNT", disk->system_path());
282 // Remember this mount point. 300 // Remember this mount point.
283 if (mounted_devices_.find(disk->device_path()) == mounted_devices_.end()) { 301 if (mounted_devices_.find(disk->device_path()) == mounted_devices_.end()) {
284 mounted_devices_.insert( 302 mounted_devices_.insert(
285 std::pair<std::string, std::string>(disk->device_path(), 303 std::pair<std::string, std::string>(disk->device_path(),
286 disk->mount_path())); 304 disk->mount_path()));
287 DispatchMountEvent(disk, true); 305 DispatchMountEvent(disk, true);
288 HideDeviceNotification(disk->system_path()); 306 HideFileBrowserNotification("MOUNT", disk->system_path());
289 FileManagerUtil::ShowFullTabUrl(profile_, FilePath(disk->mount_path())); 307 FileManagerUtil::ShowFullTabUrl(profile_, FilePath(disk->mount_path()));
290 } 308 }
291 } 309 }
292 } 310 }
293 311
312 void ExtensionFileBrowserEventRouter::OnDiskMounted(
313 const chromeos::MountLibrary::Disk* disk) {
314 DispatchMountEvent(disk, true);
315 }
316
317 void ExtensionFileBrowserEventRouter::OnDiskUnmounted(
318 const chromeos::MountLibrary::Disk* disk) {
319 DispatchMountEvent(disk, false);
320 }
321
294 void ExtensionFileBrowserEventRouter::OnDeviceAdded( 322 void ExtensionFileBrowserEventRouter::OnDeviceAdded(
295 const std::string& device_path) { 323 const std::string& device_path) {
296 VLOG(1) << "Device added : " << device_path; 324 VLOG(1) << "Device added : " << device_path;
297 // TODO(zelidrag): Find better icon here. 325 // TODO(zelidrag): Find better icon here.
298 ShowDeviceNotification(device_path, IDR_PAGEINFO_INFO, 326 ShowFileBrowserNotification("MOUNT", device_path, IDR_PAGEINFO_INFO,
327 l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_DETECTION_TITLE),
299 l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE)); 328 l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE));
300
301 } 329 }
302 330
303 void ExtensionFileBrowserEventRouter::OnDeviceRemoved( 331 void ExtensionFileBrowserEventRouter::OnDeviceRemoved(
304 const std::string& system_path) { 332 const std::string& system_path) {
305 HideDeviceNotification(system_path); 333 HideFileBrowserNotification("MOUNT", system_path);
306 } 334 }
307 335
308 void ExtensionFileBrowserEventRouter::OnDeviceScanned( 336 void ExtensionFileBrowserEventRouter::OnDeviceScanned(
309 const std::string& device_path) { 337 const std::string& device_path) {
310 VLOG(1) << "Device scanned : " << device_path; 338 VLOG(1) << "Device scanned : " << device_path;
311 } 339 }
312 340
313 void ExtensionFileBrowserEventRouter::ShowDeviceNotification( 341 void ExtensionFileBrowserEventRouter::OnFormattingStarted(
314 const std::string& system_path, int icon_resource_id, 342 const std::string& device_path) {
315 const string16& message) { 343 if (device_path[0] == '!') {
316 NotificationMap::iterator iter = FindNotificationForPath(system_path); 344 ShowFileBrowserNotification("FORMAT_FINISHED", device_path.substr(1, -1),
317 std::string mount_path; 345 IDR_PAGEINFO_WARNING_MAJOR,
318 if (iter != notifications_.end()) { 346 l10n_util::GetStringUTF16(IDS_FORMATTING_OF_DEVICE_FINISHED_TITLE),
319 iter->second->Show(message, false, false); 347 l10n_util::GetStringUTF16(IDS_FORMATTING_STARTED_FAILURE_MESSAGE));
320 } else { 348 } else {
321 if (!profile_) { 349 ShowFileBrowserNotification("FORMAT", device_path, IDR_PAGEINFO_INFO,
322 NOTREACHED(); 350 l10n_util::GetStringUTF16(IDS_FORMATTING_OF_DEVICE_PENDING_TITLE),
323 return; 351 l10n_util::GetStringUTF16(IDS_FORMATTING_OF_DEVICE_PENDING_MESSAGE));
324 }
325 chromeos::SystemNotification* notification =
326 new chromeos::SystemNotification(
327 profile_,
328 system_path,
329 icon_resource_id,
330 l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_DETECTION_TITLE));
331 notifications_.insert(NotificationMap::value_type(system_path,
332 linked_ptr<chromeos::SystemNotification>(notification)));
333 notification->Show(message, false, false);
334 } 352 }
335 } 353 }
336 354
337 void ExtensionFileBrowserEventRouter::HideDeviceNotification( 355 void ExtensionFileBrowserEventRouter::OnFormattingFinished(
338 const std::string& system_path) { 356 const std::string& device_path) {
339 NotificationMap::iterator iter = FindNotificationForPath(system_path); 357 if (device_path[0] == '!') {
358 HideFileBrowserNotification("FORMAT", device_path.substr(1, -1));
359 ShowFileBrowserNotification("FORMAT_FINISHED", device_path.substr(1, -1),
360 IDR_PAGEINFO_WARNING_MAJOR,
361 l10n_util::GetStringUTF16(IDS_FORMATTING_OF_DEVICE_FINISHED_TITLE),
362 l10n_util::GetStringUTF16(IDS_FORMATTING_FINISHED_FAILURE_MESSAGE));
363 } else {
364 HideFileBrowserNotification("FORMAT", device_path);
365 ShowFileBrowserNotification("FORMAT_FINISHED", device_path,
366 IDR_PAGEINFO_INFO,
367 l10n_util::GetStringUTF16(IDS_FORMATTING_OF_DEVICE_FINISHED_TITLE),
368 l10n_util::GetStringUTF16(IDS_FORMATTING_FINISHED_SUCCESS_MESSAGE));
369 // Hide it after a couple of seconds
370 MessageLoop::current()->PostDelayedTask(
371 FROM_HERE,
achuithb 2011/07/21 00:58:21 Is the indentation weird here?
sidor 2011/07/21 18:24:15 Yup, I changed it, I added newline between this an
372 base::Bind(
373 &HideFileBrowserNotificationExternally,
374 "FORMAT_FINISHED",
375 device_path,
376 this),
377 4000);
378 chromeos::MountLibrary* lib =
379 chromeos::CrosLibrary::Get()->GetMountLibrary();
380 lib->MountPath(device_path.c_str());
381 }
382 }
383
384 void ExtensionFileBrowserEventRouter::ShowFileBrowserNotification(
385 const std::string& cathegory, const std::string& system_path,
386 int icon_resource_id, const string16& title, const string16& message) {
387 std::string notification_id = cathegory + system_path;
388 // New notification always created because, it might have been closed by now.
389 NotificationMap::iterator iter = FindNotificationForPath(notification_id);
390 if (iter != notifications_.end())
391 notifications_.erase(iter);
392 if (!profile_) {
393 NOTREACHED();
394 return;
395 }
396 chromeos::SystemNotification* notification =
397 new chromeos::SystemNotification(
398 profile_,
399 notification_id,
400 icon_resource_id,
401 title);
402 notifications_.insert(NotificationMap::value_type(notification_id,
403 linked_ptr<chromeos::SystemNotification>(notification)));
404 notification->Show(message, false, false);
405 }
406
407 void ExtensionFileBrowserEventRouter::HideFileBrowserNotification(
408 const std::string& cathegory, const std::string& system_path) {
409 NotificationMap::iterator iter = FindNotificationForPath(
410 cathegory + system_path);
340 if (iter != notifications_.end()) { 411 if (iter != notifications_.end()) {
341 iter->second->Hide(); 412 iter->second->Hide();
342 notifications_.erase(iter); 413 notifications_.erase(iter);
343 } 414 }
344 } 415 }
345 416
346 ExtensionFileBrowserEventRouter::NotificationMap::iterator 417 ExtensionFileBrowserEventRouter::NotificationMap::iterator
347 ExtensionFileBrowserEventRouter::FindNotificationForPath( 418 ExtensionFileBrowserEventRouter::FindNotificationForPath(
348 const std::string& system_path) { 419 const std::string& notification_id) {
349 for (NotificationMap::iterator iter = notifications_.begin(); 420 for (NotificationMap::iterator iter = notifications_.begin();
350 iter != notifications_.end(); 421 iter != notifications_.end();
351 ++iter) { 422 ++iter) {
352 const std::string& notification_device_path = iter->first; 423 const std::string& notification_device_path = iter->first;
353 // Doing a sub string match so that we find if this new one is a subdevice 424 // Doing a sub string match so that we find if this new one is a subdevice
354 // of another already inserted device. 425 // of another already inserted device.
355 if (StartsWithASCII(system_path, notification_device_path, true)) { 426 if (StartsWithASCII(notification_id, notification_device_path, true)) {
356 return iter; 427 return iter;
357 } 428 }
358 } 429 }
359 return notifications_.end(); 430 return notifications_.end();
360 } 431 }
361 432
362 433
363 // ExtensionFileBrowserEventRouter::WatcherDelegate methods. 434 // ExtensionFileBrowserEventRouter::WatcherDelegate methods.
364 ExtensionFileBrowserEventRouter::FileWatcherDelegate::FileWatcherDelegate() { 435 ExtensionFileBrowserEventRouter::FileWatcherDelegate::FileWatcherDelegate() {
365 } 436 }
(...skipping 17 matching lines...) Expand all
383 local_path, 454 local_path,
384 true)); // got_error 455 true)); // got_error
385 } 456 }
386 457
387 void 458 void
388 ExtensionFileBrowserEventRouter::FileWatcherDelegate::HandleFileWatchOnUIThread( 459 ExtensionFileBrowserEventRouter::FileWatcherDelegate::HandleFileWatchOnUIThread(
389 const FilePath& local_path, bool got_error) { 460 const FilePath& local_path, bool got_error) {
390 ExtensionFileBrowserEventRouter::GetInstance()->HandleFileWatchNotification( 461 ExtensionFileBrowserEventRouter::GetInstance()->HandleFileWatchNotification(
391 local_path, got_error); 462 local_path, got_error);
392 } 463 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698