Commit 4e477b49 authored by avi@chromium.org's avatar avi@chromium.org

Remove notifications from MediaFileSystemRegistry.

BUG=170921
TEST=everything still works

Review URL: https://codereview.chromium.org/129743003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244301 0039d316-1c4b-4281-b951-d872f2087c98
parent bb51168f
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// MediaFileSystemRegistry implementation.
#include "chrome/browser/media_galleries/media_file_system_registry.h" #include "chrome/browser/media_galleries/media_file_system_registry.h"
#include <set> #include <set>
...@@ -14,7 +12,6 @@ ...@@ -14,7 +12,6 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/prefs/pref_service.h" #include "base/prefs/pref_service.h"
#include "base/stl_util.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_service.h"
#include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
...@@ -31,14 +28,11 @@ ...@@ -31,14 +28,11 @@
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.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.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.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.h"
#include "extensions/common/extension_set.h" #include "extensions/common/extension_set.h"
#include "webkit/browser/fileapi/isolated_context.h" #include "webkit/browser/fileapi/isolated_context.h"
...@@ -58,135 +52,181 @@ struct InvalidatedGalleriesInfo { ...@@ -58,135 +52,181 @@ struct InvalidatedGalleriesInfo {
}; };
// Tracks the liveness of multiple RenderProcessHosts that the caller is // 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. // back informs the caller.
class RPHReferenceManager : public content::NotificationObserver { class RPHReferenceManager {
public: public:
// |no_references_callback| is called when the last RenderViewHost reference // |no_references_callback| is called when the last RenderViewHost reference
// goes away. RenderViewHost references are added through ReferenceFromRVH(). // goes away. RenderViewHost references are added through ReferenceFromRVH().
explicit RPHReferenceManager(const base::Closure& no_references_callback) explicit RPHReferenceManager(const base::Closure& no_references_callback);
: no_references_callback_(no_references_callback) { virtual ~RPHReferenceManager();
}
virtual ~RPHReferenceManager() {
Reset();
}
// Remove all references, but don't call |no_references_callback|. // Remove all references, but don't call |no_references_callback|.
void Reset() { void Reset() { STLDeleteValues(&observer_map_); }
STLDeleteValues(&refs_);
}
// Returns true if there are no references; // Returns true if there are no references;
bool empty() const { bool empty() const { return observer_map_.empty(); }
return refs_.empty();
}
// Adds a reference to the passed |rvh|. Calling this multiple times with // Adds a reference to the passed |rvh|. Calling this multiple times with
// the same |rvh| is a no-op. // the same |rvh| is a no-op.
void ReferenceFromRVH(const content::RenderViewHost* rvh) { 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()));
}
}
private: private:
struct RPHReferenceState { class RPHWebContentsObserver : public content::WebContentsObserver {
content::NotificationRegistrar registrar; public:
std::set<const WebContents*> web_contents_set; 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) { class RPHObserver : public content::RenderProcessHostObserver {
RPHRefCount::iterator rph_info = refs_.find(rph); public:
// This could be a potential problem if the RPH is navigated to RPHObserver(RPHReferenceManager* manager, RenderProcessHost* host);
// a page on the same renderer (triggering OWCDON()) and then virtual ~RPHObserver();
// the renderer crashes.
if (rph_info == refs_.end()) { void AddWebContentsObserver(WebContents* web_contents);
NOTREACHED(); void RemoveWebContentsObserver(WebContents* web_contents);
return; bool HasWebContentsObservers() {
return observed_web_contentses_.size() > 0;
} }
delete rph_info->second; private:
refs_.erase(rph_info); virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
if (refs_.empty())
no_references_callback_.Run();
}
void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { RPHReferenceManager* manager_;
RenderProcessHost* rph = contents->GetRenderProcessHost(); RenderProcessHost* host_;
RPHRefCount::iterator rph_info = refs_.find(rph); typedef std::map<WebContents*, RPHWebContentsObserver*> WCObserverMap;
DCHECK(rph_info != refs_.end()); WCObserverMap observed_web_contentses_;
};
rph_info->second->registrar.Remove( typedef std::map<const RenderProcessHost*, RPHObserver*> RPHObserverMap;
this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<WebContents>(contents)); // Handlers for observed events.
rph_info->second->registrar.Remove( void OnRenderProcessHostDestroyed(RenderProcessHost* rph);
this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, void OnWebContentsDestroyedOrNavigated(WebContents* contents);
content::Source<NavigationController>(&contents->GetController()));
rph_info->second->web_contents_set.erase(contents);
if (rph_info->second->web_contents_set.empty())
OnRendererProcessTerminated(rph);
}
// A callback to call when the last RVH reference goes away. // A callback to call when the last RVH reference goes away.
base::Closure no_references_callback_; base::Closure no_references_callback_;
// The set of render processes and web contents that may have references to // The set of render processes and web contents that may have references to
// the file system ids this instance manages. // 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 } // namespace
MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name, MediaFileSystemInfo::MediaFileSystemInfo(const base::string16& fs_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment