Index: chrome/browser/media_galleries/media_file_system_registry.cc |
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc |
index e173dfb9ea3a6674365c34ac38e466194f7be2f7..6102cdd613ba408a7c81f42d2a16e5363ef0813a 100644 |
--- a/chrome/browser/media_galleries/media_file_system_registry.cc |
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc |
@@ -2,8 +2,6 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-// MediaFileSystemRegistry implementation. |
- |
#include "chrome/browser/media_galleries/media_file_system_registry.h" |
#include <set> |
@@ -14,7 +12,6 @@ |
#include "base/files/file_path.h" |
#include "base/prefs/pref_service.h" |
#include "base/stl_util.h" |
-#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/extensions/extension_service.h" |
#include "chrome/browser/extensions/extension_system.h" |
#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" |
@@ -31,14 +28,11 @@ |
#include "chrome/common/pref_names.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/navigation_details.h" |
-#include "content/public/browser/notification_details.h" |
-#include "content/public/browser/notification_observer.h" |
-#include "content/public/browser/notification_registrar.h" |
-#include "content/public/browser/notification_source.h" |
-#include "content/public/browser/notification_types.h" |
#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/render_process_host_observer.h" |
#include "content/public/browser/render_view_host.h" |
#include "content/public/browser/web_contents.h" |
+#include "content/public/browser/web_contents_observer.h" |
#include "extensions/common/extension.h" |
#include "extensions/common/extension_set.h" |
#include "webkit/browser/fileapi/isolated_context.h" |
@@ -58,135 +52,181 @@ struct InvalidatedGalleriesInfo { |
}; |
// Tracks the liveness of multiple RenderProcessHosts that the caller is |
-// interested in. Once all of the RPHs have closed or been terminated a call |
+// interested in. Once all of the RPHs have closed or been destroyed a call |
// back informs the caller. |
-class RPHReferenceManager : public content::NotificationObserver { |
+class RPHReferenceManager { |
public: |
// |no_references_callback| is called when the last RenderViewHost reference |
// goes away. RenderViewHost references are added through ReferenceFromRVH(). |
- explicit RPHReferenceManager(const base::Closure& no_references_callback) |
- : no_references_callback_(no_references_callback) { |
- } |
- |
- virtual ~RPHReferenceManager() { |
- Reset(); |
- } |
+ explicit RPHReferenceManager(const base::Closure& no_references_callback); |
+ virtual ~RPHReferenceManager(); |
// Remove all references, but don't call |no_references_callback|. |
- void Reset() { |
- STLDeleteValues(&refs_); |
- } |
+ void Reset() { STLDeleteValues(&observer_map_); } |
// Returns true if there are no references; |
- bool empty() const { |
- return refs_.empty(); |
- } |
+ bool empty() const { return observer_map_.empty(); } |
// Adds a reference to the passed |rvh|. Calling this multiple times with |
// the same |rvh| is a no-op. |
- void ReferenceFromRVH(const content::RenderViewHost* rvh) { |
- WebContents* contents = WebContents::FromRenderViewHost(rvh); |
- RenderProcessHost* rph = contents->GetRenderProcessHost(); |
- RPHReferenceState* state = NULL; |
- if (!ContainsKey(refs_, rph)) { |
- state = new RPHReferenceState; |
- refs_[rph] = state; |
- state->registrar.Add( |
- this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
- content::Source<RenderProcessHost>(rph)); |
- } else { |
- state = refs_[rph]; |
- } |
- |
- if (state->web_contents_set.insert(contents).second) { |
- state->registrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
- content::Source<WebContents>(contents)); |
- state->registrar.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
- content::Source<NavigationController>(&contents->GetController())); |
- } |
- } |
+ void ReferenceFromRVH(const content::RenderViewHost* rvh); |
private: |
- struct RPHReferenceState { |
- content::NotificationRegistrar registrar; |
- std::set<const WebContents*> web_contents_set; |
+ class RPHWebContentsObserver : public content::WebContentsObserver { |
+ public: |
+ RPHWebContentsObserver(RPHReferenceManager* manager, |
+ WebContents* web_contents); |
+ |
+ private: |
+ // content::WebContentsObserver |
+ virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; |
+ virtual void NavigationEntryCommitted( |
+ const content::LoadCommittedDetails& load_details) OVERRIDE; |
+ |
+ RPHReferenceManager* manager_; |
}; |
- typedef std::map<const RenderProcessHost*, RPHReferenceState*> RPHRefCount; |
- |
- // NotificationObserver implementation. |
- virtual void Observe(int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) OVERRIDE { |
- switch (type) { |
- case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
- OnRendererProcessTerminated( |
- content::Source<RenderProcessHost>(source).ptr()); |
- break; |
- } |
- case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
- OnWebContentsDestroyedOrNavigated( |
- content::Source<WebContents>(source).ptr()); |
- break; |
- } |
- case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
- content::LoadCommittedDetails* load_details = |
- content::Details<content::LoadCommittedDetails>(details).ptr(); |
- if (load_details->is_in_page) |
- break; |
- NavigationController* controller = |
- content::Source<NavigationController>(source).ptr(); |
- WebContents* contents = controller->GetWebContents(); |
- OnWebContentsDestroyedOrNavigated(contents); |
- break; |
- } |
- default: { |
- NOTREACHED(); |
- break; |
- } |
- } |
- } |
- void OnRendererProcessTerminated(const RenderProcessHost* rph) { |
- RPHRefCount::iterator rph_info = refs_.find(rph); |
- // This could be a potential problem if the RPH is navigated to |
- // a page on the same renderer (triggering OWCDON()) and then |
- // the renderer crashes. |
- if (rph_info == refs_.end()) { |
- NOTREACHED(); |
- return; |
+ class RPHObserver : public content::RenderProcessHostObserver { |
+ public: |
+ RPHObserver(RPHReferenceManager* manager, RenderProcessHost* host); |
+ virtual ~RPHObserver(); |
+ |
+ void AddWebContentsObserver(WebContents* web_contents); |
+ void RemoveWebContentsObserver(WebContents* web_contents); |
+ bool HasWebContentsObservers() { |
+ return observed_web_contentses_.size() > 0; |
} |
- delete rph_info->second; |
- refs_.erase(rph_info); |
- if (refs_.empty()) |
- no_references_callback_.Run(); |
- } |
+ private: |
+ virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE; |
- void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { |
- RenderProcessHost* rph = contents->GetRenderProcessHost(); |
- RPHRefCount::iterator rph_info = refs_.find(rph); |
- DCHECK(rph_info != refs_.end()); |
- |
- rph_info->second->registrar.Remove( |
- this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
- content::Source<WebContents>(contents)); |
- rph_info->second->registrar.Remove( |
- this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
- content::Source<NavigationController>(&contents->GetController())); |
- |
- rph_info->second->web_contents_set.erase(contents); |
- if (rph_info->second->web_contents_set.empty()) |
- OnRendererProcessTerminated(rph); |
- } |
+ RPHReferenceManager* manager_; |
+ RenderProcessHost* host_; |
+ typedef std::map<WebContents*, RPHWebContentsObserver*> WCObserverMap; |
+ WCObserverMap observed_web_contentses_; |
+ }; |
+ typedef std::map<const RenderProcessHost*, RPHObserver*> RPHObserverMap; |
+ |
+ // Handlers for observed events. |
+ void OnRenderProcessHostDestroyed(RenderProcessHost* rph); |
+ void OnWebContentsDestroyedOrNavigated(WebContents* contents); |
// A callback to call when the last RVH reference goes away. |
base::Closure no_references_callback_; |
// The set of render processes and web contents that may have references to |
// the file system ids this instance manages. |
- RPHRefCount refs_; |
+ RPHObserverMap observer_map_; |
}; |
+RPHReferenceManager::RPHReferenceManager( |
+ const base::Closure& no_references_callback) |
+ : no_references_callback_(no_references_callback) { |
+} |
+ |
+RPHReferenceManager::~RPHReferenceManager() { |
+ Reset(); |
+} |
+ |
+void RPHReferenceManager::ReferenceFromRVH(const content::RenderViewHost* rvh) { |
+ WebContents* contents = WebContents::FromRenderViewHost(rvh); |
+ RenderProcessHost* rph = contents->GetRenderProcessHost(); |
+ RPHObserver* state = NULL; |
+ if (!ContainsKey(observer_map_, rph)) { |
+ state = new RPHObserver(this, rph); |
+ observer_map_[rph] = state; |
+ } else { |
+ state = observer_map_[rph]; |
+ } |
+ |
+ state->AddWebContentsObserver(contents); |
+} |
+ |
+RPHReferenceManager::RPHWebContentsObserver::RPHWebContentsObserver( |
+ RPHReferenceManager* manager, |
+ WebContents* web_contents) |
+ : content::WebContentsObserver(web_contents), |
+ manager_(manager) { |
+} |
+ |
+void RPHReferenceManager::RPHWebContentsObserver::WebContentsDestroyed( |
+ WebContents* web_contents) { |
+ manager_->OnWebContentsDestroyedOrNavigated(web_contents); |
+} |
+ |
+void RPHReferenceManager::RPHWebContentsObserver::NavigationEntryCommitted( |
+ const content::LoadCommittedDetails& load_details) { |
+ if (load_details.is_in_page) |
+ return; |
+ |
+ manager_->OnWebContentsDestroyedOrNavigated(web_contents()); |
+} |
+ |
+RPHReferenceManager::RPHObserver::RPHObserver( |
+ RPHReferenceManager* manager, RenderProcessHost* host) |
+ : manager_(manager), |
+ host_(host) { |
+ host->AddObserver(this); |
+} |
+ |
+RPHReferenceManager::RPHObserver::~RPHObserver() { |
+ STLDeleteValues(&observed_web_contentses_); |
+ if (host_) |
+ host_->RemoveObserver(this); |
+} |
+ |
+void RPHReferenceManager::RPHObserver::AddWebContentsObserver( |
+ WebContents* web_contents) { |
+ if (ContainsKey(observed_web_contentses_, web_contents)) |
+ return; |
+ |
+ RPHWebContentsObserver* observer = |
+ new RPHWebContentsObserver(manager_, web_contents); |
+ observed_web_contentses_[web_contents] = observer; |
+} |
+ |
+void RPHReferenceManager::RPHObserver::RemoveWebContentsObserver( |
+ WebContents* web_contents) { |
+ WCObserverMap::iterator wco_iter = |
+ observed_web_contentses_.find(web_contents); |
+ DCHECK(wco_iter != observed_web_contentses_.end()); |
+ delete wco_iter->second; |
+ observed_web_contentses_.erase(wco_iter); |
+} |
+ |
+void RPHReferenceManager::RPHObserver::RenderProcessHostDestroyed( |
+ RenderProcessHost* host) { |
+ host_ = NULL; |
+ manager_->OnRenderProcessHostDestroyed(host); |
+} |
+ |
+void RPHReferenceManager::OnRenderProcessHostDestroyed( |
+ RenderProcessHost* rph) { |
+ RPHObserverMap::iterator rph_info = observer_map_.find(rph); |
+ // This could be a potential problem if the RPH is navigated to a page on the |
+ // same renderer (triggering OnWebContentsDestroyedOrNavigated()) and then the |
+ // renderer crashes. |
+ if (rph_info == observer_map_.end()) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ delete rph_info->second; |
+ observer_map_.erase(rph_info); |
+ if (observer_map_.empty()) |
+ no_references_callback_.Run(); |
+} |
+ |
+void RPHReferenceManager::OnWebContentsDestroyedOrNavigated( |
+ WebContents* contents) { |
+ RenderProcessHost* rph = contents->GetRenderProcessHost(); |
+ RPHObserverMap::iterator rph_info = observer_map_.find(rph); |
+ DCHECK(rph_info != observer_map_.end()); |
+ |
+ rph_info->second->RemoveWebContentsObserver(contents); |
+ if (!rph_info->second->HasWebContentsObservers()) |
+ OnRenderProcessHostDestroyed(rph); |
+} |
+ |
} // namespace |
MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, |