15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/media_file_system_registry.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/media_galleries/gallery_watch_manager.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/media_file_system_context.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/media_galleries/media_galleries_histograms.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media_galleries/media_galleries_preferences_factory.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/media_galleries/media_scan_manager.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/media_storage_util.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/storage_monitor/storage_monitor.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/navigation_details.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_process_host_observer.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/external_mount_points.h"
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_mount_option.h"
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_types.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderProcessHost;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::ExternalMountPoints;
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using storage_monitor::MediaStorageUtil;
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using storage_monitor::StorageInfo;
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using storage_monitor::StorageMonitor;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct InvalidatedGalleriesInfo {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<ExtensionGalleriesHost*> extension_hosts;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<MediaGalleryPrefId> pref_ids;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tracks the liveness of multiple RenderProcessHosts that the caller is
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// interested in. Once all of the RPHs have closed or been destroyed a call
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// back informs the caller.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class RPHReferenceManager {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |no_references_callback| is called when the last RenderViewHost reference
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // goes away. RenderViewHost references are added through ReferenceFromRVH().
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit RPHReferenceManager(const base::Closure& no_references_callback);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~RPHReferenceManager();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Remove all references, but don't call |no_references_callback|.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Reset() { STLDeleteValues(&observer_map_); }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if there are no references;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool empty() const { return observer_map_.empty(); }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds a reference to the passed |rvh|. Calling this multiple times with
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the same |rvh| is a no-op.
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ReferenceFromRVH(const content::RenderViewHost* rvh);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class RPHWebContentsObserver : public content::WebContentsObserver {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHWebContentsObserver(RPHReferenceManager* manager,
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           WebContents* web_contents);
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   private:
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // content::WebContentsObserver
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    virtual void WebContentsDestroyed() OVERRIDE;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void NavigationEntryCommitted(
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const content::LoadCommittedDetails& load_details) OVERRIDE;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHReferenceManager* manager_;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class RPHObserver : public content::RenderProcessHostObserver {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHObserver(RPHReferenceManager* manager, RenderProcessHost* host);
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual ~RPHObserver();
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    void AddWebContentsObserver(WebContents* web_contents);
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    void RemoveWebContentsObserver(WebContents* web_contents);
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool HasWebContentsObservers() {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return observed_web_contentses_.size() > 0;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   private:
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHReferenceManager* manager_;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RenderProcessHost* host_;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    typedef std::map<WebContents*, RPHWebContentsObserver*> WCObserverMap;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WCObserverMap observed_web_contentses_;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef std::map<const RenderProcessHost*, RPHObserver*> RPHObserverMap;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Handlers for observed events.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnRenderProcessHostDestroyed(RenderProcessHost* rph);
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnWebContentsDestroyedOrNavigated(WebContents* contents);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A callback to call when the last RVH reference goes away.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure no_references_callback_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The set of render processes and web contents that may have references to
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the file system ids this instance manages.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RPHObserverMap observer_map_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RPHReferenceManager::RPHReferenceManager(
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Closure& no_references_callback)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : no_references_callback_(no_references_callback) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RPHReferenceManager::~RPHReferenceManager() {
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::ReferenceFromRVH(const content::RenderViewHost* rvh) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebContents* contents = WebContents::FromRenderViewHost(rvh);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RenderProcessHost* rph = contents->GetRenderProcessHost();
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RPHObserver* state = NULL;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ContainsKey(observer_map_, rph)) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state = new RPHObserver(this, rph);
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    observer_map_[rph] = state;
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state = observer_map_[rph];
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state->AddWebContentsObserver(contents);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RPHReferenceManager::RPHWebContentsObserver::RPHWebContentsObserver(
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHReferenceManager* manager,
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* web_contents)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : content::WebContentsObserver(web_contents),
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      manager_(manager) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RPHReferenceManager::RPHWebContentsObserver::WebContentsDestroyed() {
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  manager_->OnWebContentsDestroyedOrNavigated(web_contents());
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::RPHWebContentsObserver::NavigationEntryCommitted(
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const content::LoadCommittedDetails& load_details) {
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (load_details.is_in_page)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_->OnWebContentsDestroyedOrNavigated(web_contents());
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RPHReferenceManager::RPHObserver::RPHObserver(
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RPHReferenceManager* manager, RenderProcessHost* host)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : manager_(manager),
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      host_(host) {
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->AddObserver(this);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RPHReferenceManager::RPHObserver::~RPHObserver() {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  STLDeleteValues(&observed_web_contentses_);
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (host_)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    host_->RemoveObserver(this);
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::RPHObserver::AddWebContentsObserver(
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* web_contents) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ContainsKey(observed_web_contentses_, web_contents))
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RPHWebContentsObserver* observer =
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    new RPHWebContentsObserver(manager_, web_contents);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observed_web_contentses_[web_contents] = observer;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::RPHObserver::RemoveWebContentsObserver(
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* web_contents) {
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WCObserverMap::iterator wco_iter =
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      observed_web_contentses_.find(web_contents);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(wco_iter != observed_web_contentses_.end());
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete wco_iter->second;
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observed_web_contentses_.erase(wco_iter);
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::RPHObserver::RenderProcessHostDestroyed(
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RenderProcessHost* host) {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host_ = NULL;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_->OnRenderProcessHostDestroyed(host);
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::OnRenderProcessHostDestroyed(
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RenderProcessHost* rph) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RPHObserverMap::iterator rph_info = observer_map_.find(rph);
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This could be a potential problem if the RPH is navigated to a page on the
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // same renderer (triggering OnWebContentsDestroyedOrNavigated()) and then the
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // renderer crashes.
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (rph_info == observer_map_.end()) {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NOTREACHED();
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete rph_info->second;
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observer_map_.erase(rph_info);
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (observer_map_.empty())
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    no_references_callback_.Run();
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RPHReferenceManager::OnWebContentsDestroyedOrNavigated(
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* contents) {
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RenderProcessHost* rph = contents->GetRenderProcessHost();
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RPHObserverMap::iterator rph_info = observer_map_.find(rph);
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(rph_info != observer_map_.end());
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rph_info->second->RemoveWebContentsObserver(contents);
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!rph_info->second->HasWebContentsObservers())
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnRenderProcessHostDestroyed(rph);
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name,
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         const base::FilePath& fs_path,
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         const std::string& filesystem_id,
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         MediaGalleryPrefId pref_id,
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         const std::string& transient_device_id,
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         bool removable,
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         bool media_device)
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : name(fs_name),
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      path(fs_path),
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      fsid(filesystem_id),
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pref_id(pref_id),
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      transient_device_id(transient_device_id),
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      removable(removable),
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      media_device(media_device) {
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MediaFileSystemInfo::MediaFileSystemInfo() {}
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MediaFileSystemInfo::~MediaFileSystemInfo() {}
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main owner of this class is
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |MediaFileSystemRegistry::extension_hosts_map_|, but a callback may
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporarily hold a reference.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionGalleriesHost
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public base::RefCountedThreadSafe<ExtensionGalleriesHost> {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |no_references_callback| is called when the last RenderViewHost reference
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // goes away. RenderViewHost references are added through ReferenceFromRVH().
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionGalleriesHost(MediaFileSystemContext* file_system_context,
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         const base::FilePath& profile_path,
267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         const std::string& extension_id,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const base::Closure& no_references_callback)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : file_system_context_(file_system_context),
270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        profile_path_(profile_path),
271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        extension_id_(extension_id),
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        no_references_callback_(no_references_callback),
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rph_refs_(base::Bind(&ExtensionGalleriesHost::CleanUp,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::Unretained(this))) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each gallery in the list of permitted |galleries|, checks if the
278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // device is attached and if so looks up or creates a file system name and
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // passes the information needed for the renderer to create those file
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // system objects to the |callback|.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetMediaFileSystems(const MediaGalleryPrefIdSet& galleries,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const MediaGalleriesPrefInfoMap& galleries_info,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const MediaFileSystemsCallback& callback) {
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::UI);
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Extract all the device ids so we can make sure they are attached.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStorageUtil::DeviceIdSet* device_ids =
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new MediaStorageUtil::DeviceIdSet;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<MediaGalleryPrefId>::const_iterator id = galleries.begin();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         id != galleries.end();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++id) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_ids->insert(galleries_info.find(*id)->second.device_id);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStorageUtil::FilterAttachedDevices(device_ids, base::Bind(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &ExtensionGalleriesHost::GetMediaFileSystemsForAttachedDevices, this,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Owned(device_ids), galleries, galleries_info, callback));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Checks if |gallery| is attached and if so, registers the file system and
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // then calls |callback| with the result.
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void RegisterMediaFileSystem(
302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const MediaGalleryPrefInfo& gallery,
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const base::Callback<void(base::File::Error result)>& callback) {
304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Extract all the device ids so we can make sure they are attached.
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MediaStorageUtil::DeviceIdSet* device_ids =
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        new MediaStorageUtil::DeviceIdSet;
307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    device_ids->insert(gallery.device_id);
308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MediaStorageUtil::FilterAttachedDevices(device_ids, base::Bind(
309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        &ExtensionGalleriesHost::RegisterAttachedMediaFileSystem, this,
310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Owned(device_ids), gallery, callback));
311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Revoke the file system for |id| if this extension has created one for |id|.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RevokeGalleryByPrefId(MediaGalleryPrefId id) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gallery == pref_id_map_.end())
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_system_context_->RevokeFileSystem(gallery->second.fsid);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_id_map_.erase(gallery);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pref_id_map_.empty()) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rph_refs_.Reset();
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CleanUp();
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicate that the passed |rvh| will reference the file system ids created
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by this class.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReferenceFromRVH(const content::RenderViewHost* rvh) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rph_refs_.ReferenceFromRVH(rvh);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> PrefIdFsInfoMap;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Private destructor and friend declaration for ref counted implementation.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<ExtensionGalleriesHost>;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionGalleriesHost() {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(rph_refs_.empty());
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(pref_id_map_.empty());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetMediaFileSystemsForAttachedDevices(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaStorageUtil::DeviceIdSet* attached_devices,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaGalleryPrefIdSet& galleries,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaGalleriesPrefInfoMap& galleries_info,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaFileSystemsCallback& callback) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<MediaFileSystemInfo> result;
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (rph_refs_.empty()) {
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We're actually in the middle of shutdown, and Filter...() lagging
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // which can invoke this method interleaved in the destruction callback
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // sequence and re-populate pref_id_map_.
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(result);
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<MediaGalleryPrefId>::const_iterator pref_id_it =
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             galleries.begin();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         pref_id_it != galleries.end();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++pref_id_it) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaGalleryPrefId& pref_id = *pref_id_it;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MediaGalleryPrefInfo& gallery_info =
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          galleries_info.find(pref_id)->second;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& device_id = gallery_info.device_id;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ContainsKey(*attached_devices, device_id))
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrefIdFsInfoMap::const_iterator existing_info =
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pref_id_map_.find(pref_id);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_info != pref_id_map_.end()) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.push_back(existing_info->second);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath path = gallery_info.AbsolutePath();
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!MediaStorageUtil::CanCreateFileSystem(device_id, path))
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      std::string fs_name = MediaFileSystemBackend::ConstructMountName(
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          profile_path_, extension_id_, pref_id);
384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!file_system_context_->RegisterFileSystem(device_id, fs_name, path))
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MediaFileSystemInfo new_entry(
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          gallery_info.GetGalleryDisplayName(),
389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          file_system_context_->GetRegisteredPath(fs_name),
390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          fs_name,
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          pref_id,
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetTransientIdForRemovableDeviceId(device_id),
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          StorageInfo::IsRemovableDevice(device_id),
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          StorageInfo::IsMediaDevice(device_id));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.push_back(new_entry);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pref_id_map_[pref_id] = new_entry;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result.size() == 0) {
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rph_refs_.Reset();
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CleanUp();
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(pref_id_map_.size(), result.size());
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(result);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void RegisterAttachedMediaFileSystem(
409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const MediaStorageUtil::DeviceIdSet* attached_device,
410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const MediaGalleryPrefInfo& gallery,
411effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const base::Callback<void(base::File::Error result)>& callback) {
412effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    base::File::Error result = base::File::FILE_ERROR_NOT_FOUND;
413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // If rph_refs is empty then we're actually in the middle of shutdown, and
415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Filter...() lagging which can invoke this method interleaved in the
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // destruction callback sequence and re-populate pref_id_map_.
417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (!attached_device->empty() && !rph_refs_.empty()) {
418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      std::string fs_name = MediaFileSystemBackend::ConstructMountName(
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          profile_path_, extension_id_, gallery.pref_id);
420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::FilePath path = gallery.AbsolutePath();
421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const std::string& device_id = gallery.device_id;
422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (ContainsKey(pref_id_map_, gallery.pref_id)) {
424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        result = base::File::FILE_OK;
425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      } else if (MediaStorageUtil::CanCreateFileSystem(device_id, path) &&
426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 file_system_context_->RegisterFileSystem(device_id, fs_name,
427effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                          path)) {
428effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        result = base::File::FILE_OK;
429effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        pref_id_map_[gallery.pref_id] = MediaFileSystemInfo(
430effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            gallery.GetGalleryDisplayName(),
431effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            file_system_context_->GetRegisteredPath(fs_name),
432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            fs_name,
433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            gallery.pref_id,
434effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            GetTransientIdForRemovableDeviceId(device_id),
435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            StorageInfo::IsRemovableDevice(device_id),
436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            StorageInfo::IsMediaDevice(device_id));
437effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
438effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
439effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
440effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (pref_id_map_.empty()) {
441effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      rph_refs_.Reset();
442effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CleanUp();
443effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
444effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
445effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            base::Bind(callback, result));
446effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
447effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) {
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!StorageInfo::IsRemovableDevice(device_id))
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return std::string();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return StorageMonitor::GetInstance()->GetTransientIdForDeviceId(device_id);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CleanUp() {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(rph_refs_.empty());
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin();
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != pref_id_map_.end();
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++it) {
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_system_context_->RevokeFileSystem(it->second.fsid);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pref_id_map_.clear();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    no_references_callback_.Run();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MediaFileSystemRegistry owns |this| and |file_system_context_|, so it's
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safe to store a raw pointer.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaFileSystemContext* file_system_context_;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
471effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Path for the active profile.
472effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const base::FilePath profile_path_;
473effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
474effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Id of the extension this host belongs to.
475effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const std::string extension_id_;
476effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A callback to call when the last RVH reference goes away.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure no_references_callback_;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A map from the gallery preferences id to the file system information.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefIdFsInfoMap pref_id_map_;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of render processes and web contents that may have references to
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the file system ids this instance manages.
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RPHReferenceManager rph_refs_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionGalleriesHost);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Public methods
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ******************/
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaFileSystemRegistry::GetMediaFileSystemsForExtension(
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::RenderViewHost* rvh,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const extensions::Extension* extension,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MediaFileSystemsCallback& callback) {
498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(tommycli): Change to DCHECK after fixing http://crbug.com/374330.
499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile =
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext());
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaGalleriesPreferences* preferences = GetPreferences(profile);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaGalleryPrefIdSet galleries =
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preferences->GalleriesForExtension(*extension);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (galleries.empty()) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(std::vector<MediaFileSystemInfo>());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionGalleriesHost* extension_host =
513effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      GetExtensionGalleryHost(profile, preferences, extension->id());
514effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This must come before the GetMediaFileSystems call to make sure the
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // RVH of the context is referenced before the filesystems are retrieved.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_host->ReferenceFromRVH(rvh);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_host->GetMediaFileSystems(galleries, preferences->known_galleries(),
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      callback);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
523effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaFileSystemRegistry::RegisterMediaFileSystemForExtension(
524effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const content::RenderViewHost* rvh,
525effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const extensions::Extension* extension,
526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MediaGalleryPrefId pref_id,
527effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::Callback<void(base::File::Error result)>& callback) {
528e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
529effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_NE(kInvalidMediaGalleryPrefId, pref_id);
530effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
531effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Profile* profile =
532effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext());
533effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MediaGalleriesPreferences* preferences = GetPreferences(profile);
534effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MediaGalleriesPrefInfoMap::const_iterator gallery =
535effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      preferences->known_galleries().find(pref_id);
536effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MediaGalleryPrefIdSet permitted_galleries =
537effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      preferences->GalleriesForExtension(*extension);
538effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
539effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (gallery == preferences->known_galleries().end() ||
540effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !ContainsKey(permitted_galleries, pref_id)) {
541effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    BrowserThread::PostTask(
542effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        BrowserThread::IO, FROM_HERE,
543effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
544effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
545effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
546effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
547effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ExtensionGalleriesHost* extension_host =
548effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      GetExtensionGalleryHost(profile, preferences, extension->id());
549effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
550effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // This must come before the GetMediaFileSystems call to make sure the
551effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // RVH of the context is referenced before the filesystems are retrieved.
552effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  extension_host->ReferenceFromRVH(rvh);
553effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
554effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  extension_host->RegisterMediaFileSystem(gallery->second, callback);
555effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
556effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaGalleriesPreferences* MediaFileSystemRegistry::GetPreferences(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
5594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Create an empty ExtensionHostMap for this profile on first initialization.
560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!ContainsKey(extension_hosts_map_, profile)) {
5614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    extension_hosts_map_[profile] = ExtensionHostMap();
562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media_galleries::UsageCount(media_galleries::PROFILES_WITH_USAGE);
563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return MediaGalleriesPreferencesFactory::GetForProfile(profile);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaScanManager* MediaFileSystemRegistry::media_scan_manager() {
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!media_scan_manager_)
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media_scan_manager_.reset(new MediaScanManager);
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return media_scan_manager_.get();
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
574116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGalleryWatchManager* MediaFileSystemRegistry::gallery_watch_manager() {
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!gallery_watch_manager_)
576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    gallery_watch_manager_.reset(new GalleryWatchManager);
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return gallery_watch_manager_.get();
578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaFileSystemRegistry::OnRemovableStorageDetached(
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StorageInfo& info) {
582e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since revoking a gallery in the ExtensionGalleriesHost may cause it
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be removed from the map and therefore invalidate any iterator pointing
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to it, this code first copies all the invalid gallery ids and the
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension hosts in which they may appear (per profile) and revoked it in
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a second step.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<InvalidatedGalleriesInfo> invalid_galleries_info;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionGalleriesHostMap::iterator profile_it =
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           extension_hosts_map_.begin();
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       profile_it != extension_hosts_map_.end();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++profile_it) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaGalleriesPreferences* preferences = GetPreferences(profile_it->first);
5964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // If |preferences| is not yet initialized, it won't contain any galleries.
5974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!preferences->IsInitialized())
5984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      continue;
5994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InvalidatedGalleriesInfo invalid_galleries_in_profile;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalid_galleries_in_profile.pref_ids =
60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        preferences->LookUpGalleriesByDeviceId(info.device_id());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ExtensionHostMap::const_iterator extension_host_it =
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             profile_it->second.begin();
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         extension_host_it != profile_it->second.end();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++extension_host_it) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalid_galleries_in_profile.extension_hosts.insert(
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_host_it->second.get());
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalid_galleries_info.push_back(invalid_galleries_in_profile);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < invalid_galleries_info.size(); i++) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<ExtensionGalleriesHost*>::const_iterator extension_host_it =
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             invalid_galleries_info[i].extension_hosts.begin();
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         extension_host_it != invalid_galleries_info[i].extension_hosts.end();
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++extension_host_it) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (std::set<MediaGalleryPrefId>::const_iterator pref_id_it =
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               invalid_galleries_info[i].pref_ids.begin();
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pref_id_it != invalid_galleries_info[i].pref_ids.end();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ++pref_id_it) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*extension_host_it)->RevokeGalleryByPrefId(*pref_id_it);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Private methods
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ******************/
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaFileSystemRegistry::MediaFileSystemContextImpl
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public MediaFileSystemContext {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
637effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MediaFileSystemContextImpl() {}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MediaFileSystemContextImpl() {}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual bool RegisterFileSystem(const std::string& device_id,
641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  const std::string& fs_name,
642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  const base::FilePath& path) OVERRIDE {
6431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (StorageInfo::IsMassStorageDevice(device_id)) {
644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return RegisterFileSystemForMassStorage(device_id, fs_name, path);
6451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
646effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return RegisterFileSystemForMTPDevice(device_id, fs_name, path);
6471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
6481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
6491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE {
6511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ImportedMediaGalleryRegistry* imported_registry =
6521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ImportedMediaGalleryRegistry::GetInstance();
653effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (imported_registry->RevokeImportedFilesystemOnUIThread(fs_name))
6541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return;
6551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
6571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
658effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        &MTPDeviceMapService::RevokeMTPFileSystem,
660effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Unretained(MTPDeviceMapService::GetInstance()),
661effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        fs_name));
662effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
663effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual base::FilePath GetRegisteredPath(
665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const std::string& fs_name) const OVERRIDE {
666effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    base::FilePath result;
667effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (!ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(fs_name,
668effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                                     &result)) {
669effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return base::FilePath();
670effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return result;
6721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
6731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
6741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private:
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers and returns the file system id for the mass storage device
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified by |device_id| and |path|.
677effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool RegisterFileSystemForMassStorage(const std::string& device_id,
678effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        const std::string& fs_name,
679effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        const base::FilePath& path) {
680e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::UI);
68190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(StorageInfo::IsMassStorageDevice(device_id));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sanity checks for |path|.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(path.IsAbsolute());
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!path.ReferencesParent());
68690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // TODO(gbillock): refactor ImportedMediaGalleryRegistry to delegate this
6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // call tree, probably by having it figure out by device id what
6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // registration is needed, or having per-device-type handlers at the
6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // next higher level.
691effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool result = false;
69290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (StorageInfo::IsITunesDevice(device_id)) {
693effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      ImportedMediaGalleryRegistry* registry =
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ImportedMediaGalleryRegistry::GetInstance();
695effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      result = registry->RegisterITunesFilesystemOnUIThread(fs_name, path);
69690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else if (StorageInfo::IsPicasaDevice(device_id)) {
697effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      ImportedMediaGalleryRegistry* registry =
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ImportedMediaGalleryRegistry::GetInstance();
699effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      result = registry->RegisterPicasaFilesystemOnUIThread(fs_name, path);
7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else if (StorageInfo::IsIPhotoDevice(device_id)) {
701effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      ImportedMediaGalleryRegistry* registry =
7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          ImportedMediaGalleryRegistry::GetInstance();
703effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      result = registry->RegisterIPhotoFilesystemOnUIThread(fs_name, path);
70490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
705effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
70603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          fs_name,
70703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          storage::kFileSystemTypeNativeMedia,
70803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          storage::FileSystemMountOption(),
70903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          path);
71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
711effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return result;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
714effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool RegisterFileSystemForMTPDevice(const std::string& device_id,
715effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                      const std::string fs_name,
716effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                      const base::FilePath& path) {
717e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::UI);
71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(!StorageInfo::IsMassStorageDevice(device_id));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sanity checks for |path|.
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(MediaStorageUtil::CanCreateFileSystem(device_id, path));
722effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
72303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        fs_name,
72403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        storage::kFileSystemTypeDeviceMedia,
72503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        storage::FileSystemMountOption(),
72603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        path);
727effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CHECK(result);
728effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
729effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        &MTPDeviceMapService::RegisterMTPFileSystem,
730effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Unretained(MTPDeviceMapService::GetInstance()),
731effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        path.value(), fs_name));
732effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return result;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MediaFileSystemContextImpl);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Constructor in 'private' section because depends on private class definition.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaFileSystemRegistry::MediaFileSystemRegistry()
740effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : file_system_context_(new MediaFileSystemContextImpl) {
741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StorageMonitor::GetInstance()->AddObserver(this);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaFileSystemRegistry::~MediaFileSystemRegistry() {
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(gbillock): This is needed because the unit test uses the
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // g_browser_process registry. We should create one in the unit test,
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // and then can remove this.
748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (StorageMonitor::GetInstance())
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StorageMonitor::GetInstance()->RemoveObserver(this);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
752d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void MediaFileSystemRegistry::OnPermissionRemoved(
753d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    MediaGalleriesPreferences* prefs,
754d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const std::string& extension_id,
755d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    MediaGalleryPrefId pref_id) {
756d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Profile* profile = prefs->profile();
757d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ExtensionGalleriesHostMap::const_iterator host_map_it =
758d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      extension_hosts_map_.find(profile);
759d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(host_map_it != extension_hosts_map_.end());
760d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const ExtensionHostMap& extension_host_map = host_map_it->second;
761d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ExtensionHostMap::const_iterator gallery_host_it =
762d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      extension_host_map.find(extension_id);
763d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (gallery_host_it == extension_host_map.end())
764d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
765d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  gallery_host_it->second->RevokeGalleryByPrefId(pref_id);
766d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
768d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void MediaFileSystemRegistry::OnGalleryRemoved(
769d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    MediaGalleriesPreferences* prefs,
770d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    MediaGalleryPrefId pref_id) {
771d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Profile* profile = prefs->profile();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the Extensions, MediaGalleriesPreferences and ExtensionHostMap for
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |profile|.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionService* extension_service =
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const extensions::ExtensionSet* extensions_set =
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extension_service->extensions();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionGalleriesHostMap::const_iterator host_map_it =
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_hosts_map_.find(profile);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(host_map_it != extension_hosts_map_.end());
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionHostMap& extension_host_map = host_map_it->second;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
783d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Go through ExtensionHosts, and remove indicated gallery, if any.
784d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // RevokeGalleryByPrefId() may end up deleting from |extension_host_map| and
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // even delete |extension_host_map| altogether. So do this in two loops to
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // avoid using an invalidated iterator or deleted map.
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<const extensions::Extension*> extensions;
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ExtensionHostMap::const_iterator it = extension_host_map.begin();
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != extension_host_map.end();
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    extensions.push_back(extensions_set->GetByID(it->first));
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < extensions.size(); ++i) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ContainsKey(extension_hosts_map_, profile))
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExtensionHostMap::const_iterator gallery_host_it =
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_host_map.find(extensions[i]->id());
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (gallery_host_it == extension_host_map.end())
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
800d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    gallery_host_it->second->RevokeGalleryByPrefId(pref_id);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
804effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochExtensionGalleriesHost* MediaFileSystemRegistry::GetExtensionGalleryHost(
805effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    Profile* profile,
806effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MediaGalleriesPreferences* preferences,
807effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const std::string& extension_id) {
808effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ExtensionGalleriesHostMap::iterator extension_hosts =
809effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      extension_hosts_map_.find(profile);
810effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // GetPreferences(), which had to be called because preferences is an
811effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // argument, ensures that profile is in the map.
812effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(extension_hosts != extension_hosts_map_.end());
813effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (extension_hosts->second.empty())
814effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    preferences->AddGalleryChangeObserver(this);
815effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
816effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ExtensionGalleriesHost* result = extension_hosts->second[extension_id].get();
817effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!result) {
818effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    result = new ExtensionGalleriesHost(
819effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        file_system_context_.get(),
820effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        profile->GetPath(),
821effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        extension_id,
822effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty,
823effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   base::Unretained(this),
824effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   profile,
825effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   extension_id));
826effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    extension_hosts_map_[profile][extension_id] = result;
827effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
828effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return result;
829effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
830effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty(
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile, const std::string& extension_id) {
833e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionGalleriesHostMap::iterator extension_hosts =
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_hosts_map_.find(profile);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(extension_hosts != extension_hosts_map_.end());
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHostMap::size_type erase_count =
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_hosts->second.erase(extension_id);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(1U, erase_count);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_hosts->second.empty()) {
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // When a profile has no ExtensionGalleriesHosts left, remove the
843d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // matching gallery-change-watcher since it is no longer needed. Leave the
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |extension_hosts| entry alone, since it indicates the profile has been
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // previously used.
846d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    MediaGalleriesPreferences* preferences = GetPreferences(profile);
847d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    preferences->RemoveGalleryChangeObserver(this);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
850