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 destroyed a call |
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); | 73 |
89 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 74 private: |
90 RPHReferenceState* state = NULL; | 75 class RPHWebContentsObserver : public content::WebContentsObserver { |
91 if (!ContainsKey(refs_, rph)) { | 76 public: |
92 state = new RPHReferenceState; | 77 RPHWebContentsObserver(RPHReferenceManager* manager, |
93 refs_[rph] = state; | 78 WebContents* web_contents); |
94 state->registrar.Add( | 79 |
95 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 80 private: |
96 content::Source<RenderProcessHost>(rph)); | 81 // content::WebContentsObserver |
97 } else { | 82 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; |
98 state = refs_[rph]; | 83 virtual void NavigationEntryCommitted( |
| 84 const content::LoadCommittedDetails& load_details) OVERRIDE; |
| 85 |
| 86 RPHReferenceManager* manager_; |
| 87 }; |
| 88 |
| 89 class RPHObserver : public content::RenderProcessHostObserver { |
| 90 public: |
| 91 RPHObserver(RPHReferenceManager* manager, RenderProcessHost* host); |
| 92 virtual ~RPHObserver(); |
| 93 |
| 94 void AddWebContentsObserver(WebContents* web_contents); |
| 95 void RemoveWebContentsObserver(WebContents* web_contents); |
| 96 bool HasWebContentsObservers() { |
| 97 return observed_web_contentses_.size() > 0; |
99 } | 98 } |
100 | 99 |
101 if (state->web_contents_set.insert(contents).second) { | 100 private: |
102 state->registrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 101 virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE; |
103 content::Source<WebContents>(contents)); | |
104 state->registrar.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | |
105 content::Source<NavigationController>(&contents->GetController())); | |
106 } | |
107 } | |
108 | 102 |
109 private: | 103 RPHReferenceManager* manager_; |
110 struct RPHReferenceState { | 104 RenderProcessHost* host_; |
111 content::NotificationRegistrar registrar; | 105 typedef std::map<WebContents*, RPHWebContentsObserver*> WCObserverMap; |
112 std::set<const WebContents*> web_contents_set; | 106 WCObserverMap observed_web_contentses_; |
113 }; | 107 }; |
114 typedef std::map<const RenderProcessHost*, RPHReferenceState*> RPHRefCount; | 108 typedef std::map<const RenderProcessHost*, RPHObserver*> RPHObserverMap; |
115 | 109 |
116 // NotificationObserver implementation. | 110 // Handlers for observed events. |
117 virtual void Observe(int type, | 111 void OnRenderProcessHostDestroyed(RenderProcessHost* rph); |
118 const content::NotificationSource& source, | 112 void OnWebContentsDestroyedOrNavigated(WebContents* contents); |
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 | |
149 void OnRendererProcessTerminated(const RenderProcessHost* rph) { | |
150 RPHRefCount::iterator rph_info = refs_.find(rph); | |
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 | |
159 delete rph_info->second; | |
160 refs_.erase(rph_info); | |
161 if (refs_.empty()) | |
162 no_references_callback_.Run(); | |
163 } | |
164 | |
165 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { | |
166 RenderProcessHost* rph = contents->GetRenderProcessHost(); | |
167 RPHRefCount::iterator rph_info = refs_.find(rph); | |
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 | 113 |
182 // A callback to call when the last RVH reference goes away. | 114 // A callback to call when the last RVH reference goes away. |
183 base::Closure no_references_callback_; | 115 base::Closure no_references_callback_; |
184 | 116 |
185 // The set of render processes and web contents that may have references to | 117 // The set of render processes and web contents that may have references to |
186 // the file system ids this instance manages. | 118 // the file system ids this instance manages. |
187 RPHRefCount refs_; | 119 RPHObserverMap observer_map_; |
188 }; | 120 }; |
189 | 121 |
| 122 RPHReferenceManager::RPHReferenceManager( |
| 123 const base::Closure& no_references_callback) |
| 124 : no_references_callback_(no_references_callback) { |
| 125 } |
| 126 |
| 127 RPHReferenceManager::~RPHReferenceManager() { |
| 128 Reset(); |
| 129 } |
| 130 |
| 131 void RPHReferenceManager::ReferenceFromRVH(const content::RenderViewHost* rvh) { |
| 132 WebContents* contents = WebContents::FromRenderViewHost(rvh); |
| 133 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 134 RPHObserver* state = NULL; |
| 135 if (!ContainsKey(observer_map_, rph)) { |
| 136 state = new RPHObserver(this, rph); |
| 137 observer_map_[rph] = state; |
| 138 } else { |
| 139 state = observer_map_[rph]; |
| 140 } |
| 141 |
| 142 state->AddWebContentsObserver(contents); |
| 143 } |
| 144 |
| 145 RPHReferenceManager::RPHWebContentsObserver::RPHWebContentsObserver( |
| 146 RPHReferenceManager* manager, |
| 147 WebContents* web_contents) |
| 148 : content::WebContentsObserver(web_contents), |
| 149 manager_(manager) { |
| 150 } |
| 151 |
| 152 void RPHReferenceManager::RPHWebContentsObserver::WebContentsDestroyed( |
| 153 WebContents* web_contents) { |
| 154 manager_->OnWebContentsDestroyedOrNavigated(web_contents); |
| 155 } |
| 156 |
| 157 void RPHReferenceManager::RPHWebContentsObserver::NavigationEntryCommitted( |
| 158 const content::LoadCommittedDetails& load_details) { |
| 159 if (load_details.is_in_page) |
| 160 return; |
| 161 |
| 162 manager_->OnWebContentsDestroyedOrNavigated(web_contents()); |
| 163 } |
| 164 |
| 165 RPHReferenceManager::RPHObserver::RPHObserver( |
| 166 RPHReferenceManager* manager, RenderProcessHost* host) |
| 167 : manager_(manager), |
| 168 host_(host) { |
| 169 host->AddObserver(this); |
| 170 } |
| 171 |
| 172 RPHReferenceManager::RPHObserver::~RPHObserver() { |
| 173 STLDeleteValues(&observed_web_contentses_); |
| 174 if (host_) |
| 175 host_->RemoveObserver(this); |
| 176 } |
| 177 |
| 178 void RPHReferenceManager::RPHObserver::AddWebContentsObserver( |
| 179 WebContents* web_contents) { |
| 180 if (ContainsKey(observed_web_contentses_, web_contents)) |
| 181 return; |
| 182 |
| 183 RPHWebContentsObserver* observer = |
| 184 new RPHWebContentsObserver(manager_, web_contents); |
| 185 observed_web_contentses_[web_contents] = observer; |
| 186 } |
| 187 |
| 188 void RPHReferenceManager::RPHObserver::RemoveWebContentsObserver( |
| 189 WebContents* web_contents) { |
| 190 WCObserverMap::iterator wco_iter = |
| 191 observed_web_contentses_.find(web_contents); |
| 192 DCHECK(wco_iter != observed_web_contentses_.end()); |
| 193 delete wco_iter->second; |
| 194 observed_web_contentses_.erase(wco_iter); |
| 195 } |
| 196 |
| 197 void RPHReferenceManager::RPHObserver::RenderProcessHostDestroyed( |
| 198 RenderProcessHost* host) { |
| 199 host_ = NULL; |
| 200 manager_->OnRenderProcessHostDestroyed(host); |
| 201 } |
| 202 |
| 203 void RPHReferenceManager::OnRenderProcessHostDestroyed( |
| 204 RenderProcessHost* rph) { |
| 205 RPHObserverMap::iterator rph_info = observer_map_.find(rph); |
| 206 // This could be a potential problem if the RPH is navigated to a page on the |
| 207 // same renderer (triggering OnWebContentsDestroyedOrNavigated()) and then the |
| 208 // renderer crashes. |
| 209 if (rph_info == observer_map_.end()) { |
| 210 NOTREACHED(); |
| 211 return; |
| 212 } |
| 213 delete rph_info->second; |
| 214 observer_map_.erase(rph_info); |
| 215 if (observer_map_.empty()) |
| 216 no_references_callback_.Run(); |
| 217 } |
| 218 |
| 219 void RPHReferenceManager::OnWebContentsDestroyedOrNavigated( |
| 220 WebContents* contents) { |
| 221 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 222 RPHObserverMap::iterator rph_info = observer_map_.find(rph); |
| 223 DCHECK(rph_info != observer_map_.end()); |
| 224 |
| 225 rph_info->second->RemoveWebContentsObserver(contents); |
| 226 if (!rph_info->second->HasWebContentsObservers()) |
| 227 OnRenderProcessHostDestroyed(rph); |
| 228 } |
| 229 |
190 } // namespace | 230 } // namespace |
191 | 231 |
192 MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, | 232 MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, |
193 const base::FilePath& fs_path, | 233 const base::FilePath& fs_path, |
194 const std::string& filesystem_id, | 234 const std::string& filesystem_id, |
195 MediaGalleryPrefId pref_id, | 235 MediaGalleryPrefId pref_id, |
196 const std::string& transient_device_id, | 236 const std::string& transient_device_id, |
197 bool removable, | 237 bool removable, |
198 bool media_device) | 238 bool media_device) |
199 : name(fs_name), | 239 : name(fs_name), |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 DCHECK_EQ(1U, erase_count); | 723 DCHECK_EQ(1U, erase_count); |
684 if (extension_hosts->second.empty()) { | 724 if (extension_hosts->second.empty()) { |
685 // When a profile has no ExtensionGalleriesHosts left, remove the | 725 // When a profile has no ExtensionGalleriesHosts left, remove the |
686 // matching gallery-change-watcher since it is no longer needed. Leave the | 726 // matching gallery-change-watcher since it is no longer needed. Leave the |
687 // |extension_hosts| entry alone, since it indicates the profile has been | 727 // |extension_hosts| entry alone, since it indicates the profile has been |
688 // previously used. | 728 // previously used. |
689 MediaGalleriesPreferences* preferences = GetPreferences(profile); | 729 MediaGalleriesPreferences* preferences = GetPreferences(profile); |
690 preferences->RemoveGalleryChangeObserver(this); | 730 preferences->RemoveGalleryChangeObserver(this); |
691 } | 731 } |
692 } | 732 } |
OLD | NEW |