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

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

Issue 1134773004: Fix speech crash on render view swap. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments from thestig@ Created 5 years, 7 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
« 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // Sessions initiated by speech input extension APIs will end up in a NULL 159 // Sessions initiated by speech input extension APIs will end up in a NULL
160 // WebContent here, but they are properly managed by the 160 // WebContent here, but they are properly managed by the
161 // chrome::SpeechInputExtensionManager. However, sessions initiated within a 161 // chrome::SpeechInputExtensionManager. However, sessions initiated within a
162 // extension using the (new) speech JS APIs, will be properly handled here. 162 // extension using the (new) speech JS APIs, will be properly handled here.
163 // TODO(primiano) turn this line into a DCHECK once speech input extension 163 // TODO(primiano) turn this line into a DCHECK once speech input extension
164 // API is deprecated. 164 // API is deprecated.
165 if (!web_contents) 165 if (!web_contents)
166 return; 166 return;
167 167
168 // Avoid multiple registrations for the same |web_contents|. 168 // Avoid multiple registrations for the same |web_contents|.
169 if (FindWebContents(web_contents) != registered_web_contents_.end()) { 169 if (FindWebContents(web_contents) != registered_web_contents_.end())
170 return; 170 return;
171 } 171
172 registered_web_contents_.push_back(new WebContentsTracker( 172 registered_web_contents_.push_back(new WebContentsTracker(
173 web_contents, base::Bind(&TabWatcher::OnTabClosed, 173 web_contents, base::Bind(&TabWatcher::OnTabClosed,
174 // |this| outlives WebContentsTracker. 174 // |this| outlives WebContentsTracker.
175 base::Unretained(this), web_contents), 175 base::Unretained(this), web_contents),
176 render_process_id, render_view_id)); 176 render_process_id, render_view_id));
177 } 177 }
178 178
179 void OnTabClosed(content::WebContents* web_contents) { 179 void OnTabClosed(content::WebContents* web_contents) {
180 ScopedVector<WebContentsTracker>::iterator iter = 180 ScopedVector<WebContentsTracker>::iterator iter =
181 FindWebContents(web_contents); 181 FindWebContents(web_contents);
182 DCHECK(iter != registered_web_contents_.end()); 182 DCHECK(iter != registered_web_contents_.end());
183 int render_process_id = (*iter)->render_process_id(); 183 int render_process_id = (*iter)->render_process_id();
184 int render_view_id = (*iter)->render_view_id(); 184 int render_view_id = (*iter)->render_view_id();
185 registered_web_contents_.erase(iter); 185 registered_web_contents_.erase(iter);
186 186
187 tab_closed_callback_.Run(render_process_id, render_view_id); 187 tab_closed_callback_.Run(render_process_id, render_view_id);
188 } 188 }
189 189
190 private: 190 private:
191 class WebContentsTracker : public content::WebContentsObserver { 191 class WebContentsTracker : public content::WebContentsObserver {
192 public: 192 public:
193 WebContentsTracker(content::WebContents* web_contents, 193 WebContentsTracker(content::WebContents* web_contents,
194 const base::Closure& finished_callback, 194 const base::Closure& finished_callback,
195 int render_process_id, 195 int render_process_id,
196 int render_view_id) 196 int render_view_id)
197 : content::WebContentsObserver(web_contents), 197 : content::WebContentsObserver(web_contents),
198 web_contents_(web_contents),
198 finished_callback_(finished_callback), 199 finished_callback_(finished_callback),
199 render_process_id_(render_process_id), 200 render_process_id_(render_process_id),
200 render_view_id_(render_view_id) {} 201 render_view_id_(render_view_id) {}
201 202
202 ~WebContentsTracker() override {} 203 ~WebContentsTracker() override {}
203 204
204 int render_process_id() const { return render_process_id_; } 205 int render_process_id() const { return render_process_id_; }
205 int render_view_id() const { return render_view_id_; } 206 int render_view_id() const { return render_view_id_; }
207 const content::WebContents* GetWebContents() const { return web_contents_; }
206 208
207 private: 209 private:
208 // content::WebContentsObserver overrides. 210 // content::WebContentsObserver overrides.
209 void WebContentsDestroyed() override { 211 void WebContentsDestroyed() override {
210 Observe(nullptr); 212 Observe(nullptr);
211 finished_callback_.Run(); 213 finished_callback_.Run();
212 // NOTE: We are deleted now. 214 // NOTE: We are deleted now.
213 } 215 }
214 void RenderViewHostChanged(content::RenderViewHost* old_host, 216 void RenderViewHostChanged(content::RenderViewHost* old_host,
215 content::RenderViewHost* new_host) override { 217 content::RenderViewHost* new_host) override {
216 Observe(nullptr); 218 Observe(nullptr);
217 finished_callback_.Run(); 219 finished_callback_.Run();
218 // NOTE: We are deleted now. 220 // NOTE: We are deleted now.
219 } 221 }
220 222
223 // Raw pointer to our WebContents.
224 //
225 // Although we are a WebContentsObserver, calling
226 // WebContents::web_contents() would return NULL once we unregister
227 // ourselves in WebContentsDestroyed() or RenderViewHostChanged(). So we
228 // store a reference to perform cleanup.
229 const content::WebContents* const web_contents_;
221 const base::Closure finished_callback_; 230 const base::Closure finished_callback_;
222 const int render_process_id_; 231 const int render_process_id_;
223 const int render_view_id_; 232 const int render_view_id_;
224 }; 233 };
225 234
226 friend class base::RefCountedThreadSafe<TabWatcher>; 235 friend class base::RefCountedThreadSafe<TabWatcher>;
227 236
228 ~TabWatcher() { 237 ~TabWatcher() {
229 // Must be destroyed on the UI thread due to |registrar_| non thread-safety. 238 // Must be destroyed on the UI thread due to |registrar_| non thread-safety.
230 // TODO(lazyboy): Do we still need this? 239 // TODO(lazyboy): Do we still need this?
231 DCHECK_CURRENTLY_ON(BrowserThread::UI); 240 DCHECK_CURRENTLY_ON(BrowserThread::UI);
232 } 241 }
233 242
234 // Helper function to find the iterator in |registered_web_contents_| which 243 // Helper function to find the iterator in |registered_web_contents_| which
235 // contains |web_contents|. 244 // contains |web_contents|.
236 ScopedVector<WebContentsTracker>::iterator FindWebContents( 245 ScopedVector<WebContentsTracker>::iterator FindWebContents(
237 content::WebContents* web_contents) { 246 content::WebContents* web_contents) {
238 for (ScopedVector<WebContentsTracker>::iterator i( 247 for (ScopedVector<WebContentsTracker>::iterator i(
239 registered_web_contents_.begin()); 248 registered_web_contents_.begin());
240 i != registered_web_contents_.end(); ++i) { 249 i != registered_web_contents_.end(); ++i) {
241 if ((*i)->web_contents() == web_contents) 250 if ((*i)->GetWebContents() == web_contents)
242 return i; 251 return i;
243 } 252 }
244 253
245 return registered_web_contents_.end(); 254 return registered_web_contents_.end();
246 } 255 }
247 256
248 // Keeps track of which WebContent(s) have been registered, in order to avoid 257 // Keeps track of which WebContent(s) have been registered, in order to avoid
249 // double registrations on WebContentsObserver and to pass the correct render 258 // double registrations on WebContentsObserver and to pass the correct render
250 // process id and render view id to |tab_closed_callback_| after the process 259 // process id and render view id to |tab_closed_callback_| after the process
251 // has gone away. 260 // has gone away.
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 // Otherwise this should be a regular tab contents. 435 // Otherwise this should be a regular tab contents.
427 allowed = true; 436 allowed = true;
428 check_permission = true; 437 check_permission = true;
429 #endif 438 #endif
430 439
431 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 440 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
432 base::Bind(callback, check_permission, allowed)); 441 base::Bind(callback, check_permission, allowed));
433 } 442 }
434 443
435 } // namespace speech 444 } // 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