Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc

Issue 12982009: Fixed the speech crash when the render view has gone away then users click "try again" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: used a struct and vector instead of pair and map Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 // Sessions initiated by speech input extension APIs will end up in a NULL 157 // Sessions initiated by speech input extension APIs will end up in a NULL
158 // WebContent here, but they are properly managed by the 158 // WebContent here, but they are properly managed by the
159 // chrome::SpeechInputExtensionManager. However, sessions initiated within a 159 // chrome::SpeechInputExtensionManager. However, sessions initiated within a
160 // extension using the (new) speech JS APIs, will be properly handled here. 160 // extension using the (new) speech JS APIs, will be properly handled here.
161 // TODO(primiano) turn this line into a DCHECK once speech input extension 161 // TODO(primiano) turn this line into a DCHECK once speech input extension
162 // API is deprecated. 162 // API is deprecated.
163 if (!web_contents) 163 if (!web_contents)
164 return; 164 return;
165 165
166 // Avoid multiple registrations on |registrar_| for the same |web_contents|. 166 // Avoid multiple registrations on |registrar_| for the same |web_contents|.
167 if (registered_web_contents_.find(web_contents) != 167 if (FindWebContents(web_contents) != registered_web_contents_.end()) {
168 registered_web_contents_.end()) {
169 return; 168 return;
170 } 169 }
171 registered_web_contents_.insert(web_contents); 170 registered_web_contents_.push_back(
171 WebContentsInfo(web_contents, render_process_id, render_view_id));
172 172
173 // Lazy initialize the registrar. 173 // Lazy initialize the registrar.
174 if (!registrar_.get()) 174 if (!registrar_.get())
175 registrar_.reset(new content::NotificationRegistrar()); 175 registrar_.reset(new content::NotificationRegistrar());
176 176
177 registrar_->Add(this, 177 registrar_->Add(this,
178 content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
179 content::Source<WebContents>(web_contents));
180 registrar_->Add(this,
178 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 181 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
179 content::Source<WebContents>(web_contents)); 182 content::Source<WebContents>(web_contents));
180 } 183 }
181 184
182 // content::NotificationObserver implementation. 185 // content::NotificationObserver implementation.
183 virtual void Observe(int type, 186 virtual void Observe(int type,
184 const content::NotificationSource& source, 187 const content::NotificationSource& source,
185 const content::NotificationDetails& details) OVERRIDE { 188 const content::NotificationDetails& details) OVERRIDE {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187 DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, type); 190 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED ||
191 type == content::NOTIFICATION_WEB_CONTENTS_SWAPPED);
188 192
189 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 193 WebContents* web_contents = content::Source<WebContents>(source).ptr();
190 int render_process_id = web_contents->GetRenderProcessHost()->GetID(); 194 std::vector<WebContentsInfo>::iterator iter = FindWebContents(web_contents);
191 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); 195 DCHECK(iter != registered_web_contents_.end());
196 int render_process_id = iter->render_process_id;
197 int render_view_id = iter->render_view_id;
198 registered_web_contents_.erase(iter);
192 199
193 registrar_->Remove(this, 200 registrar_->Remove(this,
201 content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
202 content::Source<WebContents>(web_contents));
203 registrar_->Remove(this,
194 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 204 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
195 content::Source<WebContents>(web_contents)); 205 content::Source<WebContents>(web_contents));
196 registered_web_contents_.erase(web_contents);
197 206
198 BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind( 207 BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind(
199 tab_closed_callback_, render_process_id, render_view_id)); 208 tab_closed_callback_, render_process_id, render_view_id));
200 } 209 }
201 210
202 private: 211 private:
212 struct WebContentsInfo {
213 WebContentsInfo(content::WebContents* web_contents,
214 int render_process_id,
215 int render_view_id)
216 : web_contents(web_contents),
217 render_process_id(render_process_id),
218 render_view_id(render_view_id) {}
219
220 ~WebContentsInfo() {}
221
222 content::WebContents* web_contents;
223 int render_process_id;
224 int render_view_id;
225 };
226
203 friend class base::RefCountedThreadSafe<TabWatcher>; 227 friend class base::RefCountedThreadSafe<TabWatcher>;
204 228
205 virtual ~TabWatcher() { 229 virtual ~TabWatcher() {
206 // Must be destroyed on the UI thread due to |registrar_| non thread-safety. 230 // Must be destroyed on the UI thread due to |registrar_| non thread-safety.
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208 } 232 }
209 233
234 // Helper function to find the iterator in |registered_web_contents_| which
235 // contains |web_contents|.
236 std::vector<WebContentsInfo>::iterator FindWebContents(
237 content::WebContents* web_contents) {
238 for (std::vector<WebContentsInfo>::iterator i(
239 registered_web_contents_.begin());
240 i != registered_web_contents_.end(); ++i) {
241 if (i->web_contents == web_contents)
242 return i;
243 }
244
245 return registered_web_contents_.end();
246 }
247
210 // Lazy-initialized and used on the UI thread to handle web contents 248 // Lazy-initialized and used on the UI thread to handle web contents
211 // notifications (tab closing). 249 // notifications (tab closing).
212 scoped_ptr<content::NotificationRegistrar> registrar_; 250 scoped_ptr<content::NotificationRegistrar> registrar_;
213 251
214 // Keeps track of which WebContent(s) have been registered, in order to avoid 252 // Keeps track of which WebContent(s) have been registered, in order to avoid
215 // double registrations on |registrar_| 253 // double registrations on |registrar_| and to pass the correct render
216 std::set<content::WebContents*> registered_web_contents_; 254 // process id and render view id to |tab_closed_callback_| after the process
255 // has gone away.
256 std::vector<WebContentsInfo> registered_web_contents_;
217 257
218 // Callback used to notify, on the thread specified by |callback_thread_| the 258 // Callback used to notify, on the thread specified by |callback_thread_| the
219 // closure of a registered tab. 259 // closure of a registered tab.
220 TabClosedCallback tab_closed_callback_; 260 TabClosedCallback tab_closed_callback_;
221 content::BrowserThread::ID callback_thread_; 261 content::BrowserThread::ID callback_thread_;
222 262
223 DISALLOW_COPY_AND_ASSIGN(TabWatcher); 263 DISALLOW_COPY_AND_ASSIGN(TabWatcher);
224 }; 264 };
225 265
226 ChromeSpeechRecognitionManagerDelegate 266 ChromeSpeechRecognitionManagerDelegate
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 } 563 }
524 564
525 SpeechRecognitionBubbleController* 565 SpeechRecognitionBubbleController*
526 ChromeSpeechRecognitionManagerDelegate::GetBubbleController() { 566 ChromeSpeechRecognitionManagerDelegate::GetBubbleController() {
527 if (!bubble_controller_.get()) 567 if (!bubble_controller_.get())
528 bubble_controller_ = new SpeechRecognitionBubbleController(this); 568 bubble_controller_ = new SpeechRecognitionBubbleController(this);
529 return bubble_controller_.get(); 569 return bubble_controller_.get();
530 } 570 }
531 571
532 } // namespace speech 572 } // namespace speech
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698