Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // MediaFileSystemRegistry implementation. | |
| 6 | |
| 7 #include "chrome/browser/media_galleries/media_file_system_registry.h" | 5 #include "chrome/browser/media_galleries/media_file_system_registry.h" |
| 8 | 6 |
| 9 #include <set> | 7 #include <set> |
| 10 #include <vector> | 8 #include <vector> |
| 11 | 9 |
| 12 #include "base/bind.h" | 10 #include "base/bind.h" |
| 13 #include "base/callback.h" | 11 #include "base/callback.h" |
| 14 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 15 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
| 16 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 17 #include "chrome/browser/chrome_notification_types.h" | |
| 18 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
| 19 #include "chrome/browser/extensions/extension_system.h" | 16 #include "chrome/browser/extensions/extension_system.h" |
| 20 #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" | 17 #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" |
| 21 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" | 18 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" |
| 22 #include "chrome/browser/media_galleries/media_file_system_context.h" | 19 #include "chrome/browser/media_galleries/media_file_system_context.h" |
| 23 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" | 20 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" |
| 24 #include "chrome/browser/media_galleries/media_galleries_histograms.h" | 21 #include "chrome/browser/media_galleries/media_galleries_histograms.h" |
| 25 #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h" | 22 #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h" |
| 26 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
| 27 #include "chrome/browser/storage_monitor/media_storage_util.h" | 24 #include "chrome/browser/storage_monitor/media_storage_util.h" |
| 28 #include "chrome/browser/storage_monitor/storage_monitor.h" | 25 #include "chrome/browser/storage_monitor/storage_monitor.h" |
| 29 #include "chrome/common/chrome_paths.h" | 26 #include "chrome/common/chrome_paths.h" |
| 30 #include "chrome/common/extensions/extension_constants.h" | 27 #include "chrome/common/extensions/extension_constants.h" |
| 31 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
| 32 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 33 #include "content/public/browser/navigation_details.h" | 30 #include "content/public/browser/navigation_details.h" |
| 34 #include "content/public/browser/notification_details.h" | |
| 35 #include "content/public/browser/notification_observer.h" | |
| 36 #include "content/public/browser/notification_registrar.h" | |
| 37 #include "content/public/browser/notification_source.h" | |
| 38 #include "content/public/browser/notification_types.h" | |
| 39 #include "content/public/browser/render_process_host.h" | 31 #include "content/public/browser/render_process_host.h" |
| 32 #include "content/public/browser/render_process_host_observer.h" | |
| 40 #include "content/public/browser/render_view_host.h" | 33 #include "content/public/browser/render_view_host.h" |
| 41 #include "content/public/browser/web_contents.h" | 34 #include "content/public/browser/web_contents.h" |
| 35 #include "content/public/browser/web_contents_observer.h" | |
| 42 #include "extensions/common/extension.h" | 36 #include "extensions/common/extension.h" |
| 43 #include "extensions/common/extension_set.h" | 37 #include "extensions/common/extension_set.h" |
| 44 #include "webkit/browser/fileapi/isolated_context.h" | 38 #include "webkit/browser/fileapi/isolated_context.h" |
| 45 #include "webkit/common/fileapi/file_system_types.h" | 39 #include "webkit/common/fileapi/file_system_types.h" |
| 46 | 40 |
| 47 using content::BrowserThread; | 41 using content::BrowserThread; |
| 48 using content::NavigationController; | 42 using content::NavigationController; |
| 49 using content::RenderProcessHost; | 43 using content::RenderProcessHost; |
| 50 using content::WebContents; | 44 using content::WebContents; |
| 51 using fileapi::IsolatedContext; | 45 using fileapi::IsolatedContext; |
| 52 | 46 |
| 53 namespace { | 47 namespace { |
| 54 | 48 |
| 55 struct InvalidatedGalleriesInfo { | 49 struct InvalidatedGalleriesInfo { |
| 56 std::set<ExtensionGalleriesHost*> extension_hosts; | 50 std::set<ExtensionGalleriesHost*> extension_hosts; |
| 57 std::set<MediaGalleryPrefId> pref_ids; | 51 std::set<MediaGalleryPrefId> pref_ids; |
| 58 }; | 52 }; |
| 59 | 53 |
| 60 // Tracks the liveness of multiple RenderProcessHosts that the caller is | 54 // Tracks the liveness of multiple RenderProcessHosts that the caller is |
| 61 // interested in. Once all of the RPHs have closed or been terminated a call | 55 // interested in. Once all of the RPHs have closed or been terminated a call |
|
Lei Zhang
2014/01/09 22:49:48
s/terminated/destroyed/
Avi (use Gerrit)
2014/01/10 15:42:24
Done.
| |
| 62 // back informs the caller. | 56 // back informs the caller. |
| 63 class RPHReferenceManager : public content::NotificationObserver { | 57 class RPHReferenceManager { |
| 64 public: | 58 public: |
| 65 // |no_references_callback| is called when the last RenderViewHost reference | 59 // |no_references_callback| is called when the last RenderViewHost reference |
| 66 // goes away. RenderViewHost references are added through ReferenceFromRVH(). | 60 // goes away. RenderViewHost references are added through ReferenceFromRVH(). |
| 67 explicit RPHReferenceManager(const base::Closure& no_references_callback) | 61 explicit RPHReferenceManager(const base::Closure& no_references_callback); |
| 68 : no_references_callback_(no_references_callback) { | 62 virtual ~RPHReferenceManager(); |
| 69 } | |
| 70 | |
| 71 virtual ~RPHReferenceManager() { | |
| 72 Reset(); | |
| 73 } | |
| 74 | 63 |
| 75 // Remove all references, but don't call |no_references_callback|. | 64 // Remove all references, but don't call |no_references_callback|. |
| 76 void Reset() { | 65 void Reset() { STLDeleteValues(&observer_map_); } |
| 77 STLDeleteValues(&refs_); | |
| 78 } | |
| 79 | 66 |
| 80 // Returns true if there are no references; | 67 // Returns true if there are no references; |
| 81 bool empty() const { | 68 bool empty() const { return observer_map_.empty(); } |
| 82 return refs_.empty(); | |
| 83 } | |
| 84 | 69 |
| 85 // Adds a reference to the passed |rvh|. Calling this multiple times with | 70 // Adds a reference to the passed |rvh|. Calling this multiple times with |
| 86 // the same |rvh| is a no-op. | 71 // the same |rvh| is a no-op. |
| 87 void ReferenceFromRVH(const content::RenderViewHost* rvh) { | 72 void ReferenceFromRVH(const content::RenderViewHost* rvh); |
| 88 WebContents* contents = WebContents::FromRenderViewHost(rvh); | |
| 89 RenderProcessHost* rph = contents->GetRenderProcessHost(); | |
| 90 RPHReferenceState* state = NULL; | |
| 91 if (!ContainsKey(refs_, rph)) { | |
| 92 state = new RPHReferenceState; | |
| 93 refs_[rph] = state; | |
| 94 state->registrar.Add( | |
| 95 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
| 96 content::Source<RenderProcessHost>(rph)); | |
| 97 } else { | |
| 98 state = refs_[rph]; | |
| 99 } | |
| 100 | |
| 101 if (state->web_contents_set.insert(contents).second) { | |
| 102 state->registrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 103 content::Source<WebContents>(contents)); | |
| 104 state->registrar.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | |
| 105 content::Source<NavigationController>(&contents->GetController())); | |
| 106 } | |
| 107 } | |
| 108 | 73 |
| 109 private: | 74 private: |
| 110 struct RPHReferenceState { | 75 class RPHWebContentsObserver : public content::WebContentsObserver { |
| 111 content::NotificationRegistrar registrar; | 76 public: |
| 112 std::set<const WebContents*> web_contents_set; | 77 RPHWebContentsObserver(RPHReferenceManager* manager, |
| 78 WebContents* web_contents); | |
| 79 | |
| 80 private: | |
| 81 // content::WebContentsObserver | |
| 82 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; | |
| 83 virtual void NavigationEntryCommitted( | |
| 84 const content::LoadCommittedDetails& load_details) OVERRIDE; | |
| 85 | |
| 86 RPHReferenceManager* manager_; | |
| 113 }; | 87 }; |
|
Lei Zhang
2014/01/09 22:49:48
nit: blank line between class decl
Avi (use Gerrit)
2014/01/10 15:42:24
Done.
| |
| 114 typedef std::map<const RenderProcessHost*, RPHReferenceState*> RPHRefCount; | 88 class RPHObserver : public content::RenderProcessHostObserver { |
| 89 public: | |
| 90 RPHObserver(RPHReferenceManager* manager, RenderProcessHost* host); | |
| 91 virtual ~RPHObserver(); | |
| 115 | 92 |
| 116 // NotificationObserver implementation. | 93 void AddWebContentsObserver(WebContents* web_contents); |
| 117 virtual void Observe(int type, | 94 void RemoveWebContentsObserver(WebContents* web_contents); |
| 118 const content::NotificationSource& source, | 95 size_t ObserverCount() { return observed_web_contentses_.size(); } |
|
Lei Zhang
2014/01/09 22:49:48
We only need to know if |observed_web_contentses_|
Avi (use Gerrit)
2014/01/10 15:42:24
Done.
| |
| 119 const content::NotificationDetails& details) OVERRIDE { | |
| 120 switch (type) { | |
| 121 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { | |
| 122 OnRendererProcessTerminated( | |
| 123 content::Source<RenderProcessHost>(source).ptr()); | |
| 124 break; | |
| 125 } | |
| 126 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | |
| 127 OnWebContentsDestroyedOrNavigated( | |
| 128 content::Source<WebContents>(source).ptr()); | |
| 129 break; | |
| 130 } | |
| 131 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | |
| 132 content::LoadCommittedDetails* load_details = | |
| 133 content::Details<content::LoadCommittedDetails>(details).ptr(); | |
| 134 if (load_details->is_in_page) | |
| 135 break; | |
| 136 NavigationController* controller = | |
| 137 content::Source<NavigationController>(source).ptr(); | |
| 138 WebContents* contents = controller->GetWebContents(); | |
| 139 OnWebContentsDestroyedOrNavigated(contents); | |
| 140 break; | |
| 141 } | |
| 142 default: { | |
| 143 NOTREACHED(); | |
| 144 break; | |
| 145 } | |
| 146 } | |
| 147 } | |
| 148 | 96 |
| 149 void OnRendererProcessTerminated(const RenderProcessHost* rph) { | 97 private: |
| 150 RPHRefCount::iterator rph_info = refs_.find(rph); | 98 virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE; |
| 151 // This could be a potential problem if the RPH is navigated to | |
| 152 // a page on the same renderer (triggering OWCDON()) and then | |
| 153 // the renderer crashes. | |
| 154 if (rph_info == refs_.end()) { | |
| 155 NOTREACHED(); | |
| 156 return; | |
| 157 } | |
| 158 | 99 |
| 159 delete rph_info->second; | 100 RPHReferenceManager* manager_; |
| 160 refs_.erase(rph_info); | 101 RenderProcessHost* host_; |
| 161 if (refs_.empty()) | 102 typedef std::map<WebContents*, RPHWebContentsObserver*> WCObserverMap; |
| 162 no_references_callback_.Run(); | 103 WCObserverMap observed_web_contentses_; |
| 163 } | 104 }; |
| 105 typedef std::map<const RenderProcessHost*, RPHObserver*> RPHObserverMap; | |
| 164 | 106 |
| 165 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { | 107 // Handlers for observed events. |
| 166 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 108 void OnRenderProcessHostDestroyed(RenderProcessHost* rph); |
| 167 RPHRefCount::iterator rph_info = refs_.find(rph); | 109 void OnWebContentsDestroyedOrNavigated(WebContents* contents); |
| 168 DCHECK(rph_info != refs_.end()); | |
| 169 | |
| 170 rph_info->second->registrar.Remove( | |
| 171 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 172 content::Source<WebContents>(contents)); | |
| 173 rph_info->second->registrar.Remove( | |
| 174 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | |
| 175 content::Source<NavigationController>(&contents->GetController())); | |
| 176 | |
| 177 rph_info->second->web_contents_set.erase(contents); | |
| 178 if (rph_info->second->web_contents_set.empty()) | |
| 179 OnRendererProcessTerminated(rph); | |
| 180 } | |
| 181 | 110 |
| 182 // A callback to call when the last RVH reference goes away. | 111 // A callback to call when the last RVH reference goes away. |
| 183 base::Closure no_references_callback_; | 112 base::Closure no_references_callback_; |
| 184 | 113 |
| 185 // The set of render processes and web contents that may have references to | 114 // The set of render processes and web contents that may have references to |
| 186 // the file system ids this instance manages. | 115 // the file system ids this instance manages. |
| 187 RPHRefCount refs_; | 116 RPHObserverMap observer_map_; |
| 188 }; | 117 }; |
| 189 | 118 |
| 119 RPHReferenceManager::RPHReferenceManager( | |
| 120 const base::Closure& no_references_callback) | |
| 121 : no_references_callback_(no_references_callback) { | |
| 122 } | |
| 123 | |
| 124 RPHReferenceManager::~RPHReferenceManager() { | |
| 125 Reset(); | |
| 126 } | |
| 127 | |
| 128 void RPHReferenceManager::ReferenceFromRVH(const content::RenderViewHost* rvh) { | |
| 129 WebContents* contents = WebContents::FromRenderViewHost(rvh); | |
| 130 RenderProcessHost* rph = contents->GetRenderProcessHost(); | |
| 131 RPHObserver* state = NULL; | |
| 132 if (!ContainsKey(observer_map_, rph)) { | |
| 133 state = new RPHObserver(this, rph); | |
| 134 observer_map_[rph] = state; | |
| 135 } else { | |
| 136 state = observer_map_[rph]; | |
| 137 } | |
| 138 | |
| 139 state->AddWebContentsObserver(contents); | |
| 140 } | |
| 141 | |
| 142 RPHReferenceManager::RPHWebContentsObserver::RPHWebContentsObserver( | |
| 143 RPHReferenceManager* manager, | |
| 144 WebContents* web_contents) | |
| 145 : content::WebContentsObserver(web_contents), | |
| 146 manager_(manager) { | |
| 147 } | |
| 148 | |
| 149 void RPHReferenceManager::RPHWebContentsObserver::WebContentsDestroyed( | |
| 150 WebContents* web_contents) { | |
| 151 manager_->OnWebContentsDestroyedOrNavigated(web_contents); | |
| 152 } | |
| 153 | |
| 154 void RPHReferenceManager::RPHWebContentsObserver::NavigationEntryCommitted( | |
| 155 const content::LoadCommittedDetails& load_details) { | |
| 156 if (load_details.is_in_page) | |
| 157 return; | |
| 158 | |
| 159 manager_->OnWebContentsDestroyedOrNavigated(web_contents()); | |
| 160 } | |
| 161 | |
| 162 RPHReferenceManager::RPHObserver::RPHObserver( | |
| 163 RPHReferenceManager* manager, RenderProcessHost* host) | |
| 164 : manager_(manager), | |
| 165 host_(host) { | |
| 166 host->AddObserver(this); | |
| 167 } | |
| 168 | |
| 169 RPHReferenceManager::RPHObserver::~RPHObserver() { | |
| 170 STLDeleteValues(&observed_web_contentses_); | |
| 171 if (host_) | |
| 172 host_->RemoveObserver(this); | |
| 173 } | |
| 174 | |
| 175 void RPHReferenceManager::RPHObserver::AddWebContentsObserver( | |
| 176 WebContents* web_contents) { | |
| 177 if (observed_web_contentses_.find(web_contents) | |
|
Lei Zhang
2014/01/09 22:49:48
nit: ContainsKey()
| |
| 178 != observed_web_contentses_.end()) { | |
| 179 return; | |
| 180 } | |
| 181 | |
| 182 RPHWebContentsObserver* observer = | |
| 183 new RPHWebContentsObserver(manager_, web_contents); | |
| 184 observed_web_contentses_[web_contents] = observer; | |
| 185 } | |
| 186 | |
| 187 void RPHReferenceManager::RPHObserver::RemoveWebContentsObserver( | |
| 188 WebContents* web_contents) { | |
| 189 WCObserverMap::iterator wco_iter = | |
| 190 observed_web_contentses_.find(web_contents); | |
| 191 DCHECK(wco_iter != observed_web_contentses_.end()); | |
| 192 delete wco_iter->second; | |
| 193 observed_web_contentses_.erase(wco_iter); | |
| 194 } | |
| 195 | |
| 196 void RPHReferenceManager::RPHObserver::RenderProcessHostDestroyed( | |
| 197 RenderProcessHost* host) { | |
| 198 host_ = NULL; | |
| 199 manager_->OnRenderProcessHostDestroyed(host); | |
| 200 } | |
| 201 | |
| 202 void RPHReferenceManager::OnRenderProcessHostDestroyed( | |
| 203 RenderProcessHost* rph) { | |
| 204 RPHObserverMap::iterator rph_info = observer_map_.find(rph); | |
| 205 // This could be a potential problem if the RPH is navigated to a page on the | |
| 206 // same renderer (triggering OnWebContentsDestroyedOrNavigated()) and then the | |
| 207 // renderer crashes. | |
| 208 if (rph_info == observer_map_.end()) { | |
| 209 NOTREACHED(); | |
| 210 return; | |
| 211 } | |
| 212 delete rph_info->second; | |
| 213 observer_map_.erase(rph_info); | |
| 214 if (observer_map_.empty()) | |
| 215 no_references_callback_.Run(); | |
| 216 } | |
| 217 | |
| 218 void RPHReferenceManager::OnWebContentsDestroyedOrNavigated( | |
| 219 WebContents* contents) { | |
| 220 RenderProcessHost* rph = contents->GetRenderProcessHost(); | |
| 221 RPHObserverMap::iterator rph_info = observer_map_.find(rph); | |
| 222 DCHECK(rph_info != observer_map_.end()); | |
| 223 | |
| 224 rph_info->second->RemoveWebContentsObserver(contents); | |
| 225 if (!rph_info->second->ObserverCount()) | |
| 226 OnRenderProcessHostDestroyed(rph); | |
| 227 } | |
| 228 | |
| 190 } // namespace | 229 } // namespace |
| 191 | 230 |
| 192 MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, | 231 MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, |
| 193 const base::FilePath& fs_path, | 232 const base::FilePath& fs_path, |
| 194 const std::string& filesystem_id, | 233 const std::string& filesystem_id, |
| 195 MediaGalleryPrefId pref_id, | 234 MediaGalleryPrefId pref_id, |
| 196 const std::string& transient_device_id, | 235 const std::string& transient_device_id, |
| 197 bool removable, | 236 bool removable, |
| 198 bool media_device) | 237 bool media_device) |
| 199 : name(fs_name), | 238 : name(fs_name), |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 683 DCHECK_EQ(1U, erase_count); | 722 DCHECK_EQ(1U, erase_count); |
| 684 if (extension_hosts->second.empty()) { | 723 if (extension_hosts->second.empty()) { |
| 685 // When a profile has no ExtensionGalleriesHosts left, remove the | 724 // When a profile has no ExtensionGalleriesHosts left, remove the |
| 686 // matching gallery-change-watcher since it is no longer needed. Leave the | 725 // matching gallery-change-watcher since it is no longer needed. Leave the |
| 687 // |extension_hosts| entry alone, since it indicates the profile has been | 726 // |extension_hosts| entry alone, since it indicates the profile has been |
| 688 // previously used. | 727 // previously used. |
| 689 MediaGalleriesPreferences* preferences = GetPreferences(profile); | 728 MediaGalleriesPreferences* preferences = GetPreferences(profile); |
| 690 preferences->RemoveGalleryChangeObserver(this); | 729 preferences->RemoveGalleryChangeObserver(this); |
| 691 } | 730 } |
| 692 } | 731 } |
| OLD | NEW |