| Index: content/browser/web_contents/web_contents_impl.cc | 
| diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc | 
| index 66cd29e588a81fcfc21078e6d4d54bb9ed79667a..8f85eee4a9dd2c7c1febdc03700d71c3903b3812 100644 | 
| --- a/content/browser/web_contents/web_contents_impl.cc | 
| +++ b/content/browser/web_contents/web_contents_impl.cc | 
| @@ -284,6 +284,26 @@ WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) { | 
| return rvh->GetDelegate()->GetAsWebContents(); | 
| } | 
|  | 
| +// WebContentsImpl::DestructionObserver ---------------------------------------- | 
| + | 
| +class WebContentsImpl::DestructionObserver : public WebContentsObserver { | 
| + public: | 
| +  DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents) | 
| +      : WebContentsObserver(watched_contents), | 
| +        owner_(owner) { | 
| +  } | 
| + | 
| +  // WebContentsObserver: | 
| +  virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { | 
| +    owner_->OnWebContentsDestroyed(static_cast<WebContentsImpl*>(web_contents)); | 
| +  } | 
| + | 
| + private: | 
| +  WebContentsImpl* owner_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(DestructionObserver); | 
| +}; | 
| + | 
| // WebContentsImpl ------------------------------------------------------------- | 
|  | 
| WebContentsImpl::WebContentsImpl( | 
| @@ -371,6 +391,9 @@ WebContentsImpl::~WebContentsImpl() { | 
| WebContentsImplDestroyed()); | 
|  | 
| SetDelegate(NULL); | 
| + | 
| +  STLDeleteContainerPairSecondPointers(destruction_observers_.begin(), | 
| +                                       destruction_observers_.end()); | 
| } | 
|  | 
| WebContentsImpl* WebContentsImpl::CreateWithOpener( | 
| @@ -1113,9 +1136,6 @@ void WebContentsImpl::Observe(int type, | 
| const NotificationSource& source, | 
| const NotificationDetails& details) { | 
| switch (type) { | 
| -    case NOTIFICATION_WEB_CONTENTS_DESTROYED: | 
| -      OnWebContentsDestroyed(Source<WebContents>(source).ptr()); | 
| -      break; | 
| case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { | 
| RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr(); | 
| for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); | 
| @@ -1165,10 +1185,8 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) { | 
| view_->CreateView(initial_size, params.context); | 
|  | 
| // Listen for whether our opener gets destroyed. | 
| -  if (opener_) { | 
| -    registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                   Source<WebContents>(opener_)); | 
| -  } | 
| +  if (opener_) | 
| +    AddDestructionObserver(opener_); | 
|  | 
| registrar_.Add(this, | 
| NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | 
| @@ -1183,11 +1201,11 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) { | 
| #endif | 
| } | 
|  | 
| -void WebContentsImpl::OnWebContentsDestroyed(WebContents* web_contents) { | 
| +void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) { | 
| +  RemoveDestructionObserver(web_contents); | 
| + | 
| // Clear the opener if it has been closed. | 
| if (web_contents == opener_) { | 
| -    registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                      Source<WebContents>(opener_)); | 
| opener_ = NULL; | 
| return; | 
| } | 
| @@ -1198,13 +1216,27 @@ void WebContentsImpl::OnWebContentsDestroyed(WebContents* web_contents) { | 
| if (iter->second != web_contents) | 
| continue; | 
| pending_contents_.erase(iter); | 
| -    registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                      Source<WebContents>(web_contents)); | 
| return; | 
| } | 
| NOTREACHED(); | 
| } | 
|  | 
| +void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) { | 
| +  if (!ContainsKey(destruction_observers_, web_contents)) { | 
| +    destruction_observers_[web_contents] = | 
| +        new DestructionObserver(this, web_contents); | 
| +  } | 
| +} | 
| + | 
| +void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) { | 
| +  DestructionObservers::iterator iter = | 
| +      destruction_observers_.find(web_contents); | 
| +  if (iter != destruction_observers_.end()) { | 
| +    delete destruction_observers_[web_contents]; | 
| +    destruction_observers_.erase(iter); | 
| +  } | 
| +} | 
| + | 
| void WebContentsImpl::AddObserver(WebContentsObserver* observer) { | 
| observers_.AddObserver(observer); | 
| } | 
| @@ -1413,8 +1445,7 @@ void WebContentsImpl::CreateNewWindow( | 
| // later. | 
| DCHECK_NE(MSG_ROUTING_NONE, route_id); | 
| pending_contents_[route_id] = new_contents; | 
| -    registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                   Source<WebContents>(new_contents)); | 
| +    AddDestructionObserver(new_contents); | 
| } | 
|  | 
| if (delegate_) { | 
| @@ -1549,8 +1580,7 @@ WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) { | 
|  | 
| WebContentsImpl* new_contents = iter->second; | 
| pending_contents_.erase(route_id); | 
| -  registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                    Source<WebContents>(new_contents)); | 
| +  RemoveDestructionObserver(new_contents); | 
|  | 
| // Don't initialize the guest WebContents immediately. | 
| if (new_contents->GetRenderProcessHost()->IsGuest()) | 
| @@ -2997,8 +3027,7 @@ void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) { | 
| if (opener_) { | 
| // Clear our opener so that future cross-process navigations don't have an | 
| // opener assigned. | 
| -    registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, | 
| -                      Source<WebContents>(opener_)); | 
| +    RemoveDestructionObserver(opener_); | 
| opener_ = NULL; | 
| } | 
|  | 
|  |