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 |