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

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

Issue 636863003: Make SpeechRecognition per RenderFrame instead of per RenderView. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes threading issues Created 6 years 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
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"
11 #include "base/prefs/pref_service.h" 11 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/synchronization/lock.h" 13 #include "base/synchronization/lock.h"
14 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
15 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/profiles/profile_manager.h" 16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/tab_contents/tab_util.h" 17 #include "chrome/browser/tab_contents/tab_util.h"
18 #include "chrome/common/pref_names.h" 18 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h" 19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/notification_registrar.h" 21 #include "content/public/browser/notification_registrar.h"
22 #include "content/public/browser/notification_source.h" 22 #include "content/public/browser/notification_source.h"
23 #include "content/public/browser/notification_types.h" 23 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_view_host.h" 26 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/resource_context.h" 27 #include "content/public/browser/resource_context.h"
27 #include "content/public/browser/speech_recognition_manager.h" 28 #include "content/public/browser/speech_recognition_manager.h"
28 #include "content/public/browser/speech_recognition_session_config.h" 29 #include "content/public/browser/speech_recognition_session_config.h"
29 #include "content/public/browser/speech_recognition_session_context.h" 30 #include "content/public/browser/speech_recognition_session_context.h"
30 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/speech_recognition_error.h" 32 #include "content/public/common/speech_recognition_error.h"
32 #include "content/public/common/speech_recognition_result.h" 33 #include "content/public/common/speech_recognition_result.h"
33 #include "net/url_request/url_request_context_getter.h" 34 #include "net/url_request/url_request_context_getter.h"
34 35
35 #if defined(OS_WIN) 36 #if defined(OS_WIN)
36 #include "chrome/installer/util/wmi.h" 37 #include "chrome/installer/util/wmi.h"
37 #endif 38 #endif
38 39
39 #if defined(ENABLE_EXTENSIONS) 40 #if defined(ENABLE_EXTENSIONS)
40 #include "chrome/browser/extensions/extension_service.h" 41 #include "chrome/browser/extensions/extension_service.h"
41 #include "extensions/browser/view_type_utils.h" 42 #include "extensions/browser/view_type_utils.h"
42 #endif 43 #endif
43 44
44 using content::BrowserThread; 45 using content::BrowserThread;
46 using content::RenderFrameHost;
45 using content::SpeechRecognitionManager; 47 using content::SpeechRecognitionManager;
46 using content::WebContents; 48 using content::WebContents;
47 49
48 namespace speech { 50 namespace speech {
49 51
50 namespace { 52 namespace {
51 53
52 void TabClosedCallbackOnIOThread(int render_process_id, int render_view_id) { 54 void AbortSpeechSessionsForFrameIO(int render_process_id, int render_frame_id) {
Charlie Reis 2014/12/01 23:49:43 nit: OnIO
mlamouri (slow - plz ping) 2014/12/08 17:41:04 Done.
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 55 DCHECK_CURRENTLY_ON(BrowserThread::IO);
54 56
55 SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); 57 SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance();
56 // |manager| becomes NULL if a browser shutdown happens between the post of 58 // |manager| becomes NULL if a browser shutdown happens between the post of
57 // this task (from the UI thread) and this call (on the IO thread). In this 59 // this task (from the UI thread) and this call (on the IO thread). In this
58 // case we just return. 60 // case we just return.
59 if (!manager) 61 if (!manager)
60 return; 62 return;
61 63
62 manager->AbortAllSessionsForRenderView(render_process_id, render_view_id); 64 manager->AbortAllSessionsForRenderFrame(render_process_id, render_frame_id);
65 }
66
67 void AbortSpeechSessionsForFrame(RenderFrameHost* render_frame_host) {
68 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69
70 BrowserThread::PostTask(
71 BrowserThread::IO, FROM_HERE,
72 base::Bind(&AbortSpeechSessionsForFrameIO,
73 render_frame_host->GetProcess()->GetID(),
74 render_frame_host->GetRoutingID()));
63 } 75 }
64 76
65 } // namespace 77 } // namespace
66 78
67 79
68 // Asynchronously fetches the PC and audio hardware/driver info if 80 // Asynchronously fetches the PC and audio hardware/driver info if
69 // the user has opted into UMA. This information is sent with speech input 81 // the user has opted into UMA. This information is sent with speech input
70 // requests to the server for identifying and improving quality issues with 82 // requests to the server for identifying and improving quality issues with
71 // specific device configurations. 83 // specific device configurations.
72 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo 84 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 145
134 // Simple utility to get notified when a WebContent (a tab or an extension's 146 // Simple utility to get notified when a WebContent (a tab or an extension's
135 // background page) is closed or crashes. The callback will always be called on 147 // background page) is closed or crashes. The callback will always be called on
136 // the UI thread. 148 // the UI thread.
137 // There is no restriction on the constructor, however this class must be 149 // There is no restriction on the constructor, however this class must be
138 // destroyed on the UI thread, due to the NotificationRegistrar dependency. 150 // destroyed on the UI thread, due to the NotificationRegistrar dependency.
139 class ChromeSpeechRecognitionManagerDelegate::TabWatcher 151 class ChromeSpeechRecognitionManagerDelegate::TabWatcher
140 : public base::RefCountedThreadSafe<TabWatcher>, 152 : public base::RefCountedThreadSafe<TabWatcher>,
141 public content::NotificationObserver { 153 public content::NotificationObserver {
142 public: 154 public:
143 typedef base::Callback<void(int render_process_id, int render_view_id)> 155 typedef base::Callback<void(WebContents* web_contents)>
144 TabClosedCallback; 156 TabClosedCallback;
145 157
146 explicit TabWatcher(TabClosedCallback tab_closed_callback) 158 explicit TabWatcher(TabClosedCallback tab_closed_callback)
147 : tab_closed_callback_(tab_closed_callback) { 159 : tab_closed_callback_(tab_closed_callback) {
148 } 160 }
149 161
150 // Starts monitoring the WebContents corresponding to the given 162 // Starts monitoring the WebContents corresponding to the given
151 // |render_process_id|, |render_view_id| pair, invoking |tab_closed_callback_| 163 // |render_process_id|, |render_frame_id| pair, invoking
152 // if closed/unloaded. 164 // |tab_closed_callback_| if closed/unloaded.
153 void Watch(int render_process_id, int render_view_id) { 165 void Watch(int render_process_id, int render_frame_id) {
154 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 166 DCHECK_CURRENTLY_ON(BrowserThread::UI);
155 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
156 &TabWatcher::Watch, this, render_process_id, render_view_id));
157 return;
158 }
159 167
160 WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, 168 WebContents* web_contents = WebContents::FromRenderFrameHost(
161 render_view_id); 169 RenderFrameHost::FromID(render_process_id, render_frame_id));
170
162 // Sessions initiated by speech input extension APIs will end up in a NULL 171 // Sessions initiated by speech input extension APIs will end up in a NULL
163 // WebContent here, but they are properly managed by the 172 // WebContent here, but they are properly managed by the
164 // chrome::SpeechInputExtensionManager. However, sessions initiated within a 173 // chrome::SpeechInputExtensionManager. However, sessions initiated within a
165 // extension using the (new) speech JS APIs, will be properly handled here. 174 // extension using the (new) speech JS APIs, will be properly handled here.
166 // TODO(primiano) turn this line into a DCHECK once speech input extension 175 // TODO(primiano) turn this line into a DCHECK once speech input extension
167 // API is deprecated. 176 // API is deprecated.
168 if (!web_contents) 177 if (!web_contents)
169 return; 178 return;
170 179
171 // Avoid multiple registrations on |registrar_| for the same |web_contents|. 180 // Avoid multiple registrations on |registrar_| for the same |web_contents|.
172 if (FindWebContents(web_contents) != registered_web_contents_.end()) { 181 if (registered_web_contents_.find(web_contents) !=
182 registered_web_contents_.end()) {
173 return; 183 return;
174 } 184 }
175 registered_web_contents_.push_back( 185 registered_web_contents_.insert(web_contents);
176 WebContentsInfo(web_contents, render_process_id, render_view_id));
177 186
178 // Lazy initialize the registrar. 187 // Lazy initialize the registrar.
179 if (!registrar_.get()) 188 if (!registrar_.get())
180 registrar_.reset(new content::NotificationRegistrar()); 189 registrar_.reset(new content::NotificationRegistrar());
181 190
182 registrar_->Add(this, 191 registrar_->Add(this,
183 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 192 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
184 content::Source<WebContents>(web_contents)); 193 content::Source<WebContents>(web_contents));
185 registrar_->Add(this, 194 registrar_->Add(this,
186 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 195 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
187 content::Source<WebContents>(web_contents)); 196 content::Source<WebContents>(web_contents));
188 } 197 }
189 198
190 // content::NotificationObserver implementation. 199 // content::NotificationObserver implementation.
191 void Observe(int type, 200 void Observe(int type,
192 const content::NotificationSource& source, 201 const content::NotificationSource& source,
193 const content::NotificationDetails& details) override { 202 const content::NotificationDetails& details) override {
194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
195 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED || 204 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED ||
196 type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED); 205 type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED);
197 206
198 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 207 WebContents* web_contents = content::Source<WebContents>(source).ptr();
199 std::vector<WebContentsInfo>::iterator iter = FindWebContents(web_contents); 208 DCHECK(registered_web_contents_.find(web_contents) !=
200 DCHECK(iter != registered_web_contents_.end()); 209 registered_web_contents_.end());
201 int render_process_id = iter->render_process_id; 210 registered_web_contents_.erase(web_contents);
202 int render_view_id = iter->render_view_id;
203 registered_web_contents_.erase(iter);
204 211
205 registrar_->Remove(this, 212 registrar_->Remove(this,
206 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 213 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
207 content::Source<WebContents>(web_contents)); 214 content::Source<WebContents>(web_contents));
208 registrar_->Remove(this, 215 registrar_->Remove(this,
209 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 216 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
210 content::Source<WebContents>(web_contents)); 217 content::Source<WebContents>(web_contents));
211 218
212 tab_closed_callback_.Run(render_process_id, render_view_id); 219 tab_closed_callback_.Run(web_contents);
213 } 220 }
214 221
215 private: 222 private:
216 struct WebContentsInfo {
217 WebContentsInfo(content::WebContents* web_contents,
218 int render_process_id,
219 int render_view_id)
220 : web_contents(web_contents),
221 render_process_id(render_process_id),
222 render_view_id(render_view_id) {}
223
224 ~WebContentsInfo() {}
225
226 content::WebContents* web_contents;
227 int render_process_id;
228 int render_view_id;
229 };
230
231 friend class base::RefCountedThreadSafe<TabWatcher>; 223 friend class base::RefCountedThreadSafe<TabWatcher>;
232 224
233 ~TabWatcher() override { 225 ~TabWatcher() override {
234 // Must be destroyed on the UI thread due to |registrar_| non thread-safety. 226 // Must be destroyed on the UI thread due to |registrar_| non thread-safety.
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
236 } 228 }
237 229
238 // Helper function to find the iterator in |registered_web_contents_| which
239 // contains |web_contents|.
240 std::vector<WebContentsInfo>::iterator FindWebContents(
241 content::WebContents* web_contents) {
242 for (std::vector<WebContentsInfo>::iterator i(
243 registered_web_contents_.begin());
244 i != registered_web_contents_.end(); ++i) {
245 if (i->web_contents == web_contents)
246 return i;
247 }
248
249 return registered_web_contents_.end();
250 }
251
252 // Lazy-initialized and used on the UI thread to handle web contents 230 // Lazy-initialized and used on the UI thread to handle web contents
253 // notifications (tab closing). 231 // notifications (tab closing).
254 scoped_ptr<content::NotificationRegistrar> registrar_; 232 scoped_ptr<content::NotificationRegistrar> registrar_;
255 233
256 // Keeps track of which WebContent(s) have been registered, in order to avoid 234 // Keeps track of which WebContent(s) have been registered, in order to avoid
257 // double registrations on |registrar_| and to pass the correct render 235 // double registrations on |registrar_| and to pass the correct render
258 // process id and render view id to |tab_closed_callback_| after the process 236 // process id and render view id to |tab_closed_callback_| after the process
Charlie Reis 2014/12/01 23:49:42 This comment looks stale.
mlamouri (slow - plz ping) 2014/12/08 17:41:04 Done.
259 // has gone away. 237 // has gone away.
260 std::vector<WebContentsInfo> registered_web_contents_; 238 std::set<WebContents*> registered_web_contents_;
261 239
262 // Callback used to notify, on the thread specified by |callback_thread_| the 240 // Callback used to notify, on the thread specified by |callback_thread_| the
Charlie Reis 2014/12/01 23:49:42 callback_thread_ looks stale. This gets called on
mlamouri (slow - plz ping) 2014/12/08 17:41:04 Done.
263 // closure of a registered tab. 241 // closure of a registered tab.
264 TabClosedCallback tab_closed_callback_; 242 TabClosedCallback tab_closed_callback_;
265 243
266 DISALLOW_COPY_AND_ASSIGN(TabWatcher); 244 DISALLOW_COPY_AND_ASSIGN(TabWatcher);
267 }; 245 };
268 246
269 ChromeSpeechRecognitionManagerDelegate 247 ChromeSpeechRecognitionManagerDelegate
270 ::ChromeSpeechRecognitionManagerDelegate() { 248 ::ChromeSpeechRecognitionManagerDelegate() {
271 } 249 }
272 250
273 ChromeSpeechRecognitionManagerDelegate 251 ChromeSpeechRecognitionManagerDelegate
274 ::~ChromeSpeechRecognitionManagerDelegate() { 252 ::~ChromeSpeechRecognitionManagerDelegate() {
275 } 253 }
276 254
277 void ChromeSpeechRecognitionManagerDelegate::TabClosedCallback( 255 void ChromeSpeechRecognitionManagerDelegate::TabClosedCallback(
278 int render_process_id, int render_view_id) { 256 WebContents* web_contents) {
279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 257 DCHECK_CURRENTLY_ON(BrowserThread::UI);
280 258
281 // Tell the S.R. Manager (which lives on the IO thread) to abort all the 259 web_contents->ForEachFrame(base::Bind(&AbortSpeechSessionsForFrame));
282 // sessions for the given renderer view.
283 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
284 &TabClosedCallbackOnIOThread, render_process_id, render_view_id));
285 } 260 }
286 261
287 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart( 262 void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart(
288 int session_id) { 263 int session_id) {
289 const content::SpeechRecognitionSessionContext& context = 264 const content::SpeechRecognitionSessionContext& context =
290 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 265 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
291 266
292 // Register callback to auto abort session on tab closure. 267 // Register callback to auto abort session on tab closure.
293 // |tab_watcher_| is lazyly istantiated on the first call. 268 // |tab_watcher_| is lazyly istantiated on the first call.
294 if (!tab_watcher_.get()) { 269 if (!tab_watcher_.get()) {
295 tab_watcher_ = new TabWatcher( 270 tab_watcher_ = new TabWatcher(
296 base::Bind(&ChromeSpeechRecognitionManagerDelegate::TabClosedCallback, 271 base::Bind(&ChromeSpeechRecognitionManagerDelegate::TabClosedCallback,
297 base::Unretained(this))); 272 base::Unretained(this)));
298 } 273 }
299 tab_watcher_->Watch(context.render_process_id, context.render_view_id); 274
275 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
276 base::Bind(&TabWatcher::Watch,
277 tab_watcher_,
278 context.render_process_id,
279 context.render_frame_id));
300 } 280 }
301 281
302 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { 282 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
303 } 283 }
304 284
305 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( 285 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete(
306 int session_id) { 286 int session_id) {
307 } 287 }
308 288
309 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { 289 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } 330 }
351 331
352 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( 332 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed(
353 int session_id, 333 int session_id,
354 base::Callback<void(bool ask_user, bool is_allowed)> callback) { 334 base::Callback<void(bool ask_user, bool is_allowed)> callback) {
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
356 336
357 const content::SpeechRecognitionSessionContext& context = 337 const content::SpeechRecognitionSessionContext& context =
358 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); 338 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
359 339
360 // Make sure that initiators (extensions/web pages) properly set the 340 // Check that the context is appropriate, and whether or not we need to
361 // |render_process_id| field, which is needed later to retrieve the profile. 341 // request permission from the user.
362 DCHECK_NE(context.render_process_id, 0);
Charlie Reis 2014/12/01 23:49:42 I see that the rest of this block has been moved i
mlamouri (slow - plz ping) 2014/12/08 17:41:04 I removed that because the check sounded pretty ar
Charlie Reis 2014/12/08 20:02:57 Looks like it's initialized to 0 in the context's
mlamouri (slow - plz ping) 2014/12/08 21:07:59 Done.
363
364 int render_process_id = context.render_process_id;
365 int render_view_id = context.render_view_id;
366 if (context.embedder_render_process_id) {
367 // If this is a request originated from a guest, we need to re-route the
368 // permission check through the embedder (app).
369 render_process_id = context.embedder_render_process_id;
370 render_view_id = context.embedder_render_view_id;
371 }
372
373 // Check that the render view type is appropriate, and whether or not we
374 // need to request permission from the user.
375 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 342 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
376 base::Bind(&CheckRenderViewType, 343 base::Bind(&CheckRenderViewType, callback, context));
377 callback,
378 render_process_id,
379 render_view_id));
380 } 344 }
381 345
382 content::SpeechRecognitionEventListener* 346 content::SpeechRecognitionEventListener*
383 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { 347 ChromeSpeechRecognitionManagerDelegate::GetEventListener() {
384 return this; 348 return this;
385 } 349 }
386 350
387 bool ChromeSpeechRecognitionManagerDelegate::FilterProfanities( 351 bool ChromeSpeechRecognitionManagerDelegate::FilterProfanities(
388 int render_process_id) { 352 int render_process_id) {
389 content::RenderProcessHost* rph = 353 content::RenderProcessHost* rph =
390 content::RenderProcessHost::FromID(render_process_id); 354 content::RenderProcessHost::FromID(render_process_id);
391 if (!rph) // Guard against race conditions on RPH lifetime. 355 if (!rph) // Guard against race conditions on RPH lifetime.
392 return true; 356 return true;
393 357
394 return Profile::FromBrowserContext(rph->GetBrowserContext())->GetPrefs()-> 358 return Profile::FromBrowserContext(rph->GetBrowserContext())->GetPrefs()->
395 GetBoolean(prefs::kSpeechRecognitionFilterProfanities); 359 GetBoolean(prefs::kSpeechRecognitionFilterProfanities);
396 } 360 }
397 361
398 // static. 362 // static.
399 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType( 363 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType(
400 base::Callback<void(bool ask_user, bool is_allowed)> callback, 364 base::Callback<void(bool ask_user, bool is_allowed)> callback,
401 int render_process_id, 365 const content::SpeechRecognitionSessionContext& context) {
402 int render_view_id) { 366 DCHECK_CURRENTLY_ON(BrowserThread::UI);
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 const content::RenderViewHost* render_view_host =
405 content::RenderViewHost::FromID(render_process_id, render_view_id);
406 367
407 bool allowed = false; 368 bool allowed = false;
408 bool check_permission = false; 369 bool check_permission = false;
409 370
410 if (!render_view_host) { 371 RenderFrameHost* render_frame_host = RenderFrameHost::FromID(
372 context.render_process_id, context.render_frame_id);
373
374 if (context.embedder_render_process_id) {
375 // If this is a request originated from a guest, we need to re-route the
376 // permission check through the embedder (app).
377 render_frame_host = RenderFrameHost::FromID(
378 context.embedder_render_process_id, context.embedder_render_frame_id);
379 }
380
381 if (!render_frame_host) {
411 // This happens for extensions. Manifest should be checked for permission. 382 // This happens for extensions. Manifest should be checked for permission.
412 allowed = true; 383 allowed = true;
413 check_permission = false; 384 check_permission = false;
414 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 385 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
415 base::Bind(callback, check_permission, allowed)); 386 base::Bind(callback, check_permission, allowed));
416 return; 387 return;
417 } 388 }
418 389
419 WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host); 390 WebContents* web_contents =
391 WebContents::FromRenderFrameHost(render_frame_host);
420 392
421 // chrome://app-list/ uses speech recognition. 393 // chrome://app-list/ uses speech recognition.
422 if (web_contents->GetCommittedWebUI() && 394 if (web_contents->GetCommittedWebUI() &&
423 web_contents->GetLastCommittedURL().spec() == 395 web_contents->GetLastCommittedURL().spec() ==
424 chrome::kChromeUIAppListStartPageURL) { 396 chrome::kChromeUIAppListStartPageURL) {
425 allowed = true; 397 allowed = true;
426 check_permission = false; 398 check_permission = false;
427 } 399 }
428 400
429 #if defined(ENABLE_EXTENSIONS) 401 #if defined(ENABLE_EXTENSIONS)
(...skipping 13 matching lines...) Expand all
443 // Otherwise this should be a regular tab contents. 415 // Otherwise this should be a regular tab contents.
444 allowed = true; 416 allowed = true;
445 check_permission = true; 417 check_permission = true;
446 #endif 418 #endif
447 419
448 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 420 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
449 base::Bind(callback, check_permission, allowed)); 421 base::Bind(callback, check_permission, allowed));
450 } 422 }
451 423
452 } // namespace speech 424 } // namespace speech
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698