Index: chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
diff --git a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
index b09d38f82abf83a47f912a954918b8bd720ed23a..02726bec76e417ba5f34d91767db20a8073144cb 100644 |
--- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
+++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc |
@@ -164,17 +164,20 @@ class ChromeSpeechRecognitionManagerDelegate::TabWatcher |
return; |
// Avoid multiple registrations on |registrar_| for the same |web_contents|. |
- if (registered_web_contents_.find(web_contents) != |
- registered_web_contents_.end()) { |
+ if (FindWebContents(web_contents) != registered_web_contents_.end()) { |
return; |
} |
- registered_web_contents_.insert(web_contents); |
+ registered_web_contents_.push_back( |
+ WebContentsInfo(web_contents, render_process_id, render_view_id)); |
// Lazy initialize the registrar. |
if (!registrar_.get()) |
registrar_.reset(new content::NotificationRegistrar()); |
registrar_->Add(this, |
+ content::NOTIFICATION_WEB_CONTENTS_SWAPPED, |
+ content::Source<WebContents>(web_contents)); |
+ registrar_->Add(this, |
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, |
content::Source<WebContents>(web_contents)); |
} |
@@ -184,22 +187,43 @@ class ChromeSpeechRecognitionManagerDelegate::TabWatcher |
const content::NotificationSource& source, |
const content::NotificationDetails& details) OVERRIDE { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, type); |
+ DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED || |
+ type == content::NOTIFICATION_WEB_CONTENTS_SWAPPED); |
WebContents* web_contents = content::Source<WebContents>(source).ptr(); |
- int render_process_id = web_contents->GetRenderProcessHost()->GetID(); |
- int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); |
+ std::vector<WebContentsInfo>::iterator iter = FindWebContents(web_contents); |
+ DCHECK(iter != registered_web_contents_.end()); |
+ int render_process_id = iter->render_process_id; |
+ int render_view_id = iter->render_view_id; |
+ registered_web_contents_.erase(iter); |
registrar_->Remove(this, |
+ content::NOTIFICATION_WEB_CONTENTS_SWAPPED, |
+ content::Source<WebContents>(web_contents)); |
+ registrar_->Remove(this, |
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, |
content::Source<WebContents>(web_contents)); |
- registered_web_contents_.erase(web_contents); |
BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind( |
tab_closed_callback_, render_process_id, render_view_id)); |
} |
private: |
+ struct WebContentsInfo { |
+ WebContentsInfo(content::WebContents* web_contents, |
+ int render_process_id, |
+ int render_view_id) |
+ : web_contents(web_contents), |
+ render_process_id(render_process_id), |
+ render_view_id(render_view_id) {} |
+ |
+ ~WebContentsInfo() {} |
+ |
+ content::WebContents* web_contents; |
+ int render_process_id; |
+ int render_view_id; |
+ }; |
+ |
friend class base::RefCountedThreadSafe<TabWatcher>; |
virtual ~TabWatcher() { |
@@ -207,13 +231,29 @@ class ChromeSpeechRecognitionManagerDelegate::TabWatcher |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
} |
+ // Helper function to find the iterator in |registered_web_contents_| which |
+ // contains |web_contents|. |
+ std::vector<WebContentsInfo>::iterator FindWebContents( |
+ content::WebContents* web_contents) { |
+ for (std::vector<WebContentsInfo>::iterator i( |
+ registered_web_contents_.begin()); |
+ i != registered_web_contents_.end(); ++i) { |
+ if (i->web_contents == web_contents) |
+ return i; |
+ } |
+ |
+ return registered_web_contents_.end(); |
+ } |
+ |
// Lazy-initialized and used on the UI thread to handle web contents |
// notifications (tab closing). |
scoped_ptr<content::NotificationRegistrar> registrar_; |
// Keeps track of which WebContent(s) have been registered, in order to avoid |
- // double registrations on |registrar_| |
- std::set<content::WebContents*> registered_web_contents_; |
+ // double registrations on |registrar_| and to pass the correct render |
+ // process id and render view id to |tab_closed_callback_| after the process |
+ // has gone away. |
+ std::vector<WebContentsInfo> registered_web_contents_; |
// Callback used to notify, on the thread specified by |callback_thread_| the |
// closure of a registered tab. |