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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/provided_file_system.cc

Issue 674413002: [fsp] Rename ObserveEntry with AddWatcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 6 years, 1 month 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/file_system_provider/provided_file_system.h" 5 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/files/file.h" 10 #include "base/files/file.h"
11 #include "chrome/browser/chromeos/file_system_provider/notification_manager.h" 11 #include "chrome/browser/chromeos/file_system_provider/notification_manager.h"
12 #include "chrome/browser/chromeos/file_system_provider/operations/abort.h" 12 #include "chrome/browser/chromeos/file_system_provider/operations/abort.h"
13 #include "chrome/browser/chromeos/file_system_provider/operations/add_watcher.h"
13 #include "chrome/browser/chromeos/file_system_provider/operations/close_file.h" 14 #include "chrome/browser/chromeos/file_system_provider/operations/close_file.h"
14 #include "chrome/browser/chromeos/file_system_provider/operations/copy_entry.h" 15 #include "chrome/browser/chromeos/file_system_provider/operations/copy_entry.h"
15 #include "chrome/browser/chromeos/file_system_provider/operations/create_directo ry.h" 16 #include "chrome/browser/chromeos/file_system_provider/operations/create_directo ry.h"
16 #include "chrome/browser/chromeos/file_system_provider/operations/create_file.h" 17 #include "chrome/browser/chromeos/file_system_provider/operations/create_file.h"
17 #include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h " 18 #include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h "
18 #include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h " 19 #include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h "
19 #include "chrome/browser/chromeos/file_system_provider/operations/move_entry.h" 20 #include "chrome/browser/chromeos/file_system_provider/operations/move_entry.h"
20 #include "chrome/browser/chromeos/file_system_provider/operations/observe_direct ory.h"
21 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h" 21 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h"
22 #include "chrome/browser/chromeos/file_system_provider/operations/read_directory .h" 22 #include "chrome/browser/chromeos/file_system_provider/operations/read_directory .h"
23 #include "chrome/browser/chromeos/file_system_provider/operations/read_file.h" 23 #include "chrome/browser/chromeos/file_system_provider/operations/read_file.h"
24 #include "chrome/browser/chromeos/file_system_provider/operations/remove_watcher .h"
24 #include "chrome/browser/chromeos/file_system_provider/operations/truncate.h" 25 #include "chrome/browser/chromeos/file_system_provider/operations/truncate.h"
25 #include "chrome/browser/chromeos/file_system_provider/operations/unmount.h" 26 #include "chrome/browser/chromeos/file_system_provider/operations/unmount.h"
26 #include "chrome/browser/chromeos/file_system_provider/operations/unobserve_entr y.h"
27 #include "chrome/browser/chromeos/file_system_provider/operations/write_file.h" 27 #include "chrome/browser/chromeos/file_system_provider/operations/write_file.h"
28 #include "chrome/browser/chromeos/file_system_provider/request_manager.h" 28 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
29 #include "chrome/browser/profiles/profile.h" 29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/common/extensions/api/file_system_provider.h" 30 #include "chrome/common/extensions/api/file_system_provider.h"
31 #include "extensions/browser/event_router.h" 31 #include "extensions/browser/event_router.h"
32 32
33 namespace net { 33 namespace net {
34 class IOBuffer; 34 class IOBuffer;
35 } // namespace net 35 } // namespace net
36 36
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 event_router_, file_system_info_, file_path, length, callback))); 357 event_router_, file_system_info_, file_path, length, callback)));
358 if (!request_id) { 358 if (!request_id) {
359 callback.Run(base::File::FILE_ERROR_SECURITY); 359 callback.Run(base::File::FILE_ERROR_SECURITY);
360 return AbortCallback(); 360 return AbortCallback();
361 } 361 }
362 362
363 return base::Bind( 363 return base::Bind(
364 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 364 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
365 } 365 }
366 366
367 ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory( 367 ProvidedFileSystem::AbortCallback ProvidedFileSystem::AddWatcher(
368 const GURL& origin, 368 const GURL& origin,
369 const base::FilePath& directory_path, 369 const base::FilePath& entry_path,
370 bool recursive, 370 bool recursive,
371 bool persistent, 371 bool persistent,
372 const storage::AsyncFileUtil::StatusCallback& callback) { 372 const storage::AsyncFileUtil::StatusCallback& callback) {
373 // TODO(mtomasz): Wrap the entire method body with an asynchronous queue to 373 // TODO(mtomasz): Wrap the entire method body with an asynchronous queue to
374 // avoid races. 374 // avoid races.
375 if (persistent && !file_system_info_.supports_notify_tag()) { 375 if (persistent && !file_system_info_.supports_notify_tag()) {
376 OnObserveDirectoryCompleted(origin, 376 OnAddWatcherCompleted(origin,
377 directory_path, 377 entry_path,
378 recursive, 378 recursive,
379 persistent, 379 persistent,
380 callback, 380 callback,
381 base::File::FILE_ERROR_INVALID_OPERATION); 381 base::File::FILE_ERROR_INVALID_OPERATION);
382 return AbortCallback(); 382 return AbortCallback();
383 } 383 }
384 384
385 const ObservedEntryKey key(directory_path, recursive); 385 const WatcherKey key(entry_path, recursive);
386 const ObservedEntries::const_iterator it = observed_entries_.find(key); 386 const Watchers::const_iterator it = watchers_.find(key);
387 if (it != observed_entries_.end()) { 387 if (it != watchers_.end()) {
388 const bool exists = 388 const bool exists =
389 it->second.subscribers.find(origin) != it->second.subscribers.end(); 389 it->second.subscribers.find(origin) != it->second.subscribers.end();
390 OnObserveDirectoryCompleted( 390 OnAddWatcherCompleted(
391 origin, 391 origin,
392 directory_path, 392 entry_path,
393 recursive, 393 recursive,
394 persistent, 394 persistent,
395 callback, 395 callback,
396 exists ? base::File::FILE_ERROR_EXISTS : base::File::FILE_OK); 396 exists ? base::File::FILE_ERROR_EXISTS : base::File::FILE_OK);
397 return AbortCallback(); 397 return AbortCallback();
398 } 398 }
399 399
400 const int request_id = request_manager_->CreateRequest( 400 const int request_id = request_manager_->CreateRequest(
401 OBSERVE_DIRECTORY, 401 ADD_WATCHER,
402 scoped_ptr<RequestManager::HandlerInterface>( 402 scoped_ptr<RequestManager::HandlerInterface>(new operations::AddWatcher(
403 new operations::ObserveDirectory( 403 event_router_,
404 event_router_, 404 file_system_info_,
405 file_system_info_, 405 entry_path,
406 directory_path, 406 recursive,
407 recursive, 407 base::Bind(&ProvidedFileSystem::OnAddWatcherCompleted,
408 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted, 408 weak_ptr_factory_.GetWeakPtr(),
409 weak_ptr_factory_.GetWeakPtr(), 409 origin,
410 origin, 410 entry_path,
411 directory_path, 411 recursive,
412 recursive, 412 persistent,
413 persistent, 413 callback))));
414 callback))));
415 414
416 if (!request_id) { 415 if (!request_id) {
417 OnObserveDirectoryCompleted(origin, 416 OnAddWatcherCompleted(origin,
418 directory_path, 417 entry_path,
419 recursive, 418 recursive,
420 persistent, 419 persistent,
421 callback, 420 callback,
422 base::File::FILE_ERROR_SECURITY); 421 base::File::FILE_ERROR_SECURITY);
423 return AbortCallback(); 422 return AbortCallback();
424 } 423 }
425 424
426 return base::Bind( 425 return base::Bind(
427 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 426 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
428 } 427 }
429 428
430 void ProvidedFileSystem::UnobserveEntry( 429 void ProvidedFileSystem::RemoveWatcher(
431 const GURL& origin, 430 const GURL& origin,
432 const base::FilePath& entry_path, 431 const base::FilePath& entry_path,
433 bool recursive, 432 bool recursive,
434 const storage::AsyncFileUtil::StatusCallback& callback) { 433 const storage::AsyncFileUtil::StatusCallback& callback) {
435 const ObservedEntryKey key(entry_path, recursive); 434 const WatcherKey key(entry_path, recursive);
436 const ObservedEntries::iterator it = observed_entries_.find(key); 435 const Watchers::iterator it = watchers_.find(key);
437 if (it == observed_entries_.end() || 436 if (it == watchers_.end() ||
438 it->second.subscribers.find(origin) == it->second.subscribers.end()) { 437 it->second.subscribers.find(origin) == it->second.subscribers.end()) {
439 callback.Run(base::File::FILE_ERROR_NOT_FOUND); 438 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
440 return; 439 return;
441 } 440 }
442 441
443 // Delete the subscriber in advance, since the list of observed entries is 442 // Delete the subscriber in advance, since the list of watchers is owned by
444 // owned by the C++ layer, not by the extension. 443 // the C++ layer, not by the extension.
445 it->second.subscribers.erase(origin); 444 it->second.subscribers.erase(origin);
446 445
447 FOR_EACH_OBSERVER( 446 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
448 ProvidedFileSystemObserver, 447 observers_,
449 observers_, 448 OnWatcherListChanged(file_system_info_, watchers_));
450 OnObservedEntryListChanged(file_system_info_, observed_entries_));
451 449
452 // If there are other subscribers, then do not remove the obsererver, but 450 // If there are other subscribers, then do not remove the obsererver, but
453 // simply return a success. 451 // simply return a success.
454 if (it->second.subscribers.size()) { 452 if (it->second.subscribers.size()) {
455 callback.Run(base::File::FILE_OK); 453 callback.Run(base::File::FILE_OK);
456 return; 454 return;
457 } 455 }
458 456
459 // Delete the watcher in advance. 457 // Delete the watcher in advance.
460 observed_entries_.erase(it); 458 watchers_.erase(it);
461 459
462 // Even if the extension returns an error, the callback is called with base:: 460 // Even if the extension returns an error, the callback is called with base::
463 // File::FILE_OK. The reason for that is that the observed is not watched 461 // File::FILE_OK. The reason for that is that the entry is not watche anymore
464 // anymore anyway, as it's removed in advance. 462 // anyway, as it's removed in advance.
465 const int request_id = request_manager_->CreateRequest( 463 const int request_id = request_manager_->CreateRequest(
466 UNOBSERVE_ENTRY, 464 REMOVE_WATCHER,
467 scoped_ptr<RequestManager::HandlerInterface>( 465 scoped_ptr<RequestManager::HandlerInterface>(
468 new operations::UnobserveEntry( 466 new operations::RemoveWatcher(
469 event_router_, 467 event_router_,
470 file_system_info_, 468 file_system_info_,
471 entry_path, 469 entry_path,
472 recursive, 470 recursive,
473 base::Bind(&AlwaysSuccessCallback, callback)))); 471 base::Bind(&AlwaysSuccessCallback, callback))));
474 if (!request_id) 472 if (!request_id)
475 callback.Run(base::File::FILE_OK); 473 callback.Run(base::File::FILE_OK);
476 } 474 }
477 475
478 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const { 476 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
479 return file_system_info_; 477 return file_system_info_;
480 } 478 }
481 479
482 RequestManager* ProvidedFileSystem::GetRequestManager() { 480 RequestManager* ProvidedFileSystem::GetRequestManager() {
483 return request_manager_.get(); 481 return request_manager_.get();
484 } 482 }
485 483
486 ObservedEntries* ProvidedFileSystem::GetObservedEntries() { 484 Watchers* ProvidedFileSystem::GetWatchers() {
487 return &observed_entries_; 485 return &watchers_;
488 } 486 }
489 487
490 void ProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) { 488 void ProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
491 DCHECK(observer); 489 DCHECK(observer);
492 observers_.AddObserver(observer); 490 observers_.AddObserver(observer);
493 } 491 }
494 492
495 void ProvidedFileSystem::RemoveObserver(ProvidedFileSystemObserver* observer) { 493 void ProvidedFileSystem::RemoveObserver(ProvidedFileSystemObserver* observer) {
496 DCHECK(observer); 494 DCHECK(observer);
497 observers_.RemoveObserver(observer); 495 observers_.RemoveObserver(observer);
498 } 496 }
499 497
500 bool ProvidedFileSystem::Notify( 498 bool ProvidedFileSystem::Notify(
501 const base::FilePath& observed_path, 499 const base::FilePath& entry_path,
502 bool recursive, 500 bool recursive,
503 ProvidedFileSystemObserver::ChangeType change_type, 501 ProvidedFileSystemObserver::ChangeType change_type,
504 scoped_ptr<ProvidedFileSystemObserver::Changes> changes, 502 scoped_ptr<ProvidedFileSystemObserver::Changes> changes,
505 const std::string& tag) { 503 const std::string& tag) {
506 const ObservedEntryKey key(observed_path, recursive); 504 const WatcherKey key(entry_path, recursive);
507 const ObservedEntries::iterator it = observed_entries_.find(key); 505 const Watchers::iterator it = watchers_.find(key);
508 if (it == observed_entries_.end()) 506 if (it == watchers_.end())
509 return false; 507 return false;
510 508
511 // The tag must be provided if and only if it's explicitly supported. 509 // The tag must be provided if and only if it's explicitly supported.
512 if (file_system_info_.supports_notify_tag() == tag.empty()) 510 if (file_system_info_.supports_notify_tag() == tag.empty())
513 return false; 511 return false;
514 512
515 // The object is owned by AutoUpdated, so the reference is valid as long as 513 // The object is owned by AutoUpdated, so the reference is valid as long as
516 // callbacks created with AutoUpdater::CreateCallback(). 514 // callbacks created with AutoUpdater::CreateCallback().
517 const ProvidedFileSystemObserver::Changes& changes_ref = *changes.get(); 515 const ProvidedFileSystemObserver::Changes& changes_ref = *changes.get();
518 516
519 scoped_refptr<AutoUpdater> auto_updater( 517 scoped_refptr<AutoUpdater> auto_updater(
520 new AutoUpdater(base::Bind(&ProvidedFileSystem::OnNotifyCompleted, 518 new AutoUpdater(base::Bind(&ProvidedFileSystem::OnNotifyCompleted,
521 weak_ptr_factory_.GetWeakPtr(), 519 weak_ptr_factory_.GetWeakPtr(),
522 observed_path, 520 entry_path,
523 recursive, 521 recursive,
524 change_type, 522 change_type,
525 base::Passed(&changes), 523 base::Passed(&changes),
526 it->second.last_tag, 524 it->second.last_tag,
527 tag))); 525 tag)));
528 526
529 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, 527 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
530 observers_, 528 observers_,
531 OnObservedEntryChanged(file_system_info_, 529 OnWatcherChanged(file_system_info_,
532 it->second, 530 it->second,
533 change_type, 531 change_type,
534 changes_ref, 532 changes_ref,
535 auto_updater->CreateCallback())); 533 auto_updater->CreateCallback()));
536 534
537 return true; 535 return true;
538 } 536 }
539 537
540 base::WeakPtr<ProvidedFileSystemInterface> ProvidedFileSystem::GetWeakPtr() { 538 base::WeakPtr<ProvidedFileSystemInterface> ProvidedFileSystem::GetWeakPtr() {
541 return weak_ptr_factory_.GetWeakPtr(); 539 return weak_ptr_factory_.GetWeakPtr();
542 } 540 }
543 541
544 void ProvidedFileSystem::Abort( 542 void ProvidedFileSystem::Abort(
545 int operation_request_id, 543 int operation_request_id,
546 const storage::AsyncFileUtil::StatusCallback& callback) { 544 const storage::AsyncFileUtil::StatusCallback& callback) {
547 request_manager_->RejectRequest(operation_request_id, 545 request_manager_->RejectRequest(operation_request_id,
548 make_scoped_ptr(new RequestValue()), 546 make_scoped_ptr(new RequestValue()),
549 base::File::FILE_ERROR_ABORT); 547 base::File::FILE_ERROR_ABORT);
550 if (!request_manager_->CreateRequest( 548 if (!request_manager_->CreateRequest(
551 ABORT, 549 ABORT,
552 scoped_ptr<RequestManager::HandlerInterface>( 550 scoped_ptr<RequestManager::HandlerInterface>(
553 new operations::Abort(event_router_, 551 new operations::Abort(event_router_,
554 file_system_info_, 552 file_system_info_,
555 operation_request_id, 553 operation_request_id,
556 callback)))) { 554 callback)))) {
557 callback.Run(base::File::FILE_ERROR_SECURITY); 555 callback.Run(base::File::FILE_ERROR_SECURITY);
558 } 556 }
559 } 557 }
560 558
561 void ProvidedFileSystem::OnObserveDirectoryCompleted( 559 void ProvidedFileSystem::OnAddWatcherCompleted(
562 const GURL& origin, 560 const GURL& origin,
563 const base::FilePath& directory_path, 561 const base::FilePath& entry_path,
564 bool recursive, 562 bool recursive,
565 bool persistent, 563 bool persistent,
566 const storage::AsyncFileUtil::StatusCallback& callback, 564 const storage::AsyncFileUtil::StatusCallback& callback,
567 base::File::Error result) { 565 base::File::Error result) {
568 if (result != base::File::FILE_OK) { 566 if (result != base::File::FILE_OK) {
569 callback.Run(result); 567 callback.Run(result);
570 return; 568 return;
571 } 569 }
572 570
573 const ObservedEntryKey key(directory_path, recursive); 571 const WatcherKey key(entry_path, recursive);
574 const ObservedEntries::iterator it = observed_entries_.find(key); 572 const Watchers::iterator it = watchers_.find(key);
575 if (it != observed_entries_.end()) { 573 if (it != watchers_.end()) {
576 callback.Run(base::File::FILE_OK); 574 callback.Run(base::File::FILE_OK);
577 return; 575 return;
578 } 576 }
579 577
580 ObservedEntry* const observed_entry = &observed_entries_[key]; 578 Watcher* const watcher = &watchers_[key];
581 observed_entry->entry_path = directory_path; 579 watcher->entry_path = entry_path;
582 observed_entry->recursive = recursive; 580 watcher->recursive = recursive;
583 observed_entry->subscribers[origin].origin = origin; 581 watcher->subscribers[origin].origin = origin;
584 observed_entry->subscribers[origin].persistent |= persistent; 582 watcher->subscribers[origin].persistent |= persistent;
585 583
586 FOR_EACH_OBSERVER( 584 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
587 ProvidedFileSystemObserver, 585 observers_,
588 observers_, 586 OnWatcherListChanged(file_system_info_, watchers_));
589 OnObservedEntryListChanged(file_system_info_, observed_entries_));
590 587
591 callback.Run(base::File::FILE_OK); 588 callback.Run(base::File::FILE_OK);
592 } 589 }
593 590
594 void ProvidedFileSystem::OnNotifyCompleted( 591 void ProvidedFileSystem::OnNotifyCompleted(
595 const base::FilePath& observed_path, 592 const base::FilePath& entry_path,
596 bool recursive, 593 bool recursive,
597 ProvidedFileSystemObserver::ChangeType change_type, 594 ProvidedFileSystemObserver::ChangeType change_type,
598 scoped_ptr<ProvidedFileSystemObserver::Changes> /* changes */, 595 scoped_ptr<ProvidedFileSystemObserver::Changes> /* changes */,
599 const std::string& last_tag, 596 const std::string& last_tag,
600 const std::string& tag) { 597 const std::string& tag) {
601 const ObservedEntryKey key(observed_path, recursive); 598 const WatcherKey key(entry_path, recursive);
602 const ObservedEntries::iterator it = observed_entries_.find(key); 599 const Watchers::iterator it = watchers_.find(key);
603 // Check if the entry is still observed. 600 // Check if the entry is still watched.
604 if (it == observed_entries_.end()) 601 if (it == watchers_.end())
605 return; 602 return;
606 603
607 // Another following notification finished earlier. 604 // Another following notification finished earlier.
608 if (it->second.last_tag != last_tag) 605 if (it->second.last_tag != last_tag)
609 return; 606 return;
610 607
611 // It's illegal to provide a tag which is not unique. As for now only an error 608 // It's illegal to provide a tag which is not unique. As for now only an error
612 // message is printed, but we may want to pass the error to the providing 609 // message is printed, but we may want to pass the error to the providing
613 // extension. TODO(mtomasz): Consider it. 610 // extension. TODO(mtomasz): Consider it.
614 if (!tag.empty() && tag == it->second.last_tag) 611 if (!tag.empty() && tag == it->second.last_tag)
615 LOG(ERROR) << "Tag specified, but same as the previous one."; 612 LOG(ERROR) << "Tag specified, but same as the previous one.";
616 613
617 it->second.last_tag = tag; 614 it->second.last_tag = tag;
618 615
619 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, 616 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
620 observers_, 617 observers_,
621 OnObservedEntryTagUpdated(file_system_info_, it->second)); 618 OnWatcherTagUpdated(file_system_info_, it->second));
622 619
623 // If the observed entry is deleted, then unobserve it. 620 // If the watched entry is deleted, then remove the watcher.
624 if (change_type == ProvidedFileSystemObserver::DELETED) { 621 if (change_type == ProvidedFileSystemObserver::DELETED) {
625 // Make a copy, since the |it| iterator will get invalidated on the last 622 // Make a copy, since the |it| iterator will get invalidated on the last
626 // subscriber. 623 // subscriber.
627 Subscribers subscribers = it->second.subscribers; 624 Subscribers subscribers = it->second.subscribers;
628 for (const auto& subscriber_it : subscribers) { 625 for (const auto& subscriber_it : subscribers) {
629 UnobserveEntry(subscriber_it.second.origin, 626 RemoveWatcher(subscriber_it.second.origin,
630 observed_path, 627 entry_path,
631 recursive, 628 recursive,
632 base::Bind(&EmptyStatusCallback)); 629 base::Bind(&EmptyStatusCallback));
633 } 630 }
634 } 631 }
635 } 632 }
636 633
637 } // namespace file_system_provider 634 } // namespace file_system_provider
638 } // namespace chromeos 635 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698