text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h"
  
  #include <string>
  
  #include "base/bind.h"
  #include "base/macros.h"
  #include "base/threading/thread_restrictions.h"
  #include "build/build_config.h"
  #include "chrome/browser/profiles/profile_manager.h"
  #include "chrome/common/pref_names.h"
  #include "components/prefs/pref_service.h"
  #include "content/public/browser/browser_thread.h"
  #include "content/public/browser/render_frame_host.h"
  #include "content/public/browser/render_process_host.h"
  #include "content/public/browser/speech_recognition_manager.h"
  #include "content/public/browser/speech_recognition_session_context.h"
  #include "content/public/browser/web_contents.h"
  #include "content/public/common/speech_recognition_error.h"
  #include "content/public/common/speech_recognition_result.h"
  
  #if BUILDFLAG(ENABLE_EXTENSIONS)
  #include "chrome/browser/extensions/extension_service.h"
  #include "extensions/browser/view_type_utils.h"
  #endif
  
  using content::BrowserThread;
  using content::SpeechRecognitionManager;
  using content::WebContents;
  
  namespace speech {
  
  ChromeSpeechRecognitionManagerDelegate
  ::ChromeSpeechRecognitionManagerDelegate() {
  }
  
  ChromeSpeechRecognitionManagerDelegate
  ::~ChromeSpeechRecognitionManagerDelegate() {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart(
      int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete(
      int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnRecognitionResults(
      int session_id, const content::SpeechRecognitionResults& result) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError(
      int session_id, const content::SpeechRecognitionError& error) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnAudioLevelsChange(
      int session_id, float volume, float noise_volume) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) {
  }
  
  void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed(
      int session_id,
      base::OnceCallback<void(bool ask_user, bool is_allowed)> callback) {
    DCHECK_CURRENTLY_ON(BrowserThread::IO);
  
    const content::SpeechRecognitionSessionContext& context =
        SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
  
    // Make sure that initiators (extensions/web pages) properly set the
    // |render_process_id| field, which is needed later to retrieve the profile.
    DCHECK_NE(context.render_process_id, 0);
  
    int render_process_id = context.render_process_id;
    int render_frame_id = context.render_frame_id;
    if (context.embedder_render_process_id) {
      // If this is a request originated from a guest, we need to re-route the
      // permission check through the embedder (app).
      render_process_id = context.embedder_render_process_id;
      render_frame_id = context.embedder_render_frame_id;
    }
  
    // Check that the render frame type is appropriate, and whether or not we
    // need to request permission from the user.
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&CheckRenderFrameType, std::move(callback),
                       render_process_id, render_frame_id));
  }
  
  content::SpeechRecognitionEventListener*
  ChromeSpeechRecognitionManagerDelegate::GetEventListener() {
    return this;
  }
  
  bool ChromeSpeechRecognitionManagerDelegate::FilterProfanities(
      int render_process_id) {
    content::RenderProcessHost* rph =
        content::RenderProcessHost::FromID(render_process_id);
    if (!rph)  // Guard against race conditions on RPH lifetime.
      return true;
  
    return Profile::FromBrowserContext(rph->GetBrowserContext())->GetPrefs()->
        GetBoolean(prefs::kSpeechRecognitionFilterProfanities);
  }
  
  // static.
  void ChromeSpeechRecognitionManagerDelegate::CheckRenderFrameType(
      base::OnceCallback<void(bool ask_user, bool is_allowed)> callback,
      int render_process_id,
      int render_frame_id) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    content::RenderFrameHost* render_frame_host =
        content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  
    bool allowed = false;
    bool check_permission = false;
  
    if (!render_frame_host) {
      // This happens for extensions. Manifest should be checked for permission.
      allowed = true;
      check_permission = false;
      BrowserThread::PostTask(
          BrowserThread::IO, FROM_HERE,
          base::BindOnce(std::move(callback), check_permission, allowed));
      return;
    }
  
  #if BUILDFLAG(ENABLE_EXTENSIONS)
    WebContents* web_contents =
        WebContents::FromRenderFrameHost(render_frame_host);
    extensions::ViewType view_type = extensions::GetViewType(web_contents);
  
    if (view_type == extensions::VIEW_TYPE_TAB_CONTENTS ||
        view_type == extensions::VIEW_TYPE_APP_WINDOW ||
        view_type == extensions::VIEW_TYPE_COMPONENT ||
        view_type == extensions::VIEW_TYPE_EXTENSION_POPUP ||
        view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
      // If it is a tab, we can check for permission. For apps, this means
      // manifest would be checked for permission.
      allowed = true;
      check_permission = true;
    }
  #else
    // Otherwise this should be a regular tab contents.
    allowed = true;
    check_permission = true;
  #endif
  
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::BindOnce(std::move(callback), check_permission, allowed));
  }
  
  }  // namespace speech
  