Commit 7b2266ee authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Convert Speech Recognition code to use SimplerURLLoader.

The SimplerURLLoader API is compatible with the out-of-process network
service.

This is the only code that uses chunked uploads, and the new API for
that requires the consumer handle all the complexities of that, which
makes this CL much more complicated than most URLFetcher to
SimplerURLLoader conversions.

BUG:  810555

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_mojo;master.tryserver.chromium.linux:linux_vr
Change-Id: I4cc1f5f8710d08830062e95296ae5d814a6097e8
Reviewed-on: https://chromium-review.googlesource.com/1050825Reviewed-by: default avatarBiao She <bshe@chromium.org>
Reviewed-by: default avatarTommi <tommi@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarDoug Turner <dougt@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Commit-Queue: Matt Menke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565378}
parent 8bffcae7
......@@ -55,6 +55,7 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "content/public/common/service_manager_connection.h"
......@@ -65,6 +66,7 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "jni/VrShellImpl_jni.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/android/window_android.h"
......@@ -985,7 +987,10 @@ void VrShell::SetVoiceSearchActive(bool active) {
Profile* profile = ProfileManager::GetActiveUserProfile();
std::string profile_locale = g_browser_process->GetApplicationLocale();
speech_recognizer_.reset(new SpeechRecognizer(
this, ui_, profile->GetRequestContext(), profile_locale));
this, ui_,
content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLLoaderFactoryForBrowserProcessIOThread(),
profile->GetRequestContext(), profile_locale));
}
if (active) {
speech_recognizer_->Start();
......
......@@ -11,7 +11,9 @@
#include "chrome/common/pref_names.h"
#include "chromeos/audio/chromeos_sounds.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/storage_partition.h"
#include "media/audio/sounds/sounds_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/ime_input_context_handler_interface.h"
......@@ -45,8 +47,10 @@ bool DictationChromeos::OnToggleDictation() {
}
speech_recognizer_ = std::make_unique<SpeechRecognizer>(
weak_ptr_factory_.GetWeakPtr(), profile_->GetRequestContext(),
GetUserLocale(profile_));
weak_ptr_factory_.GetWeakPtr(),
content::BrowserContext::GetDefaultStoragePartition(profile_)
->GetURLLoaderFactoryForBrowserProcessIOThread(),
profile_->GetRequestContext(), GetUserLocale(profile_));
speech_recognizer_->Start(nullptr /* preamble */);
return true;
}
......
......@@ -23,6 +23,7 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/speech_recognition_error.mojom.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
// Length of timeout to cancel recognition if there's no speech heard.
static const int kNoSpeechTimeoutInSeconds = 5;
......@@ -44,9 +45,12 @@ class SpeechRecognizer::EventListener
: public base::RefCountedThreadSafe<SpeechRecognizer::EventListener>,
public content::SpeechRecognitionEventListener {
public:
EventListener(const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
net::URLRequestContextGetter* url_request_context_getter,
const std::string& locale);
EventListener(
const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale);
void StartOnIOThread(
const std::string& auth_scope,
......@@ -90,7 +94,12 @@ class SpeechRecognizer::EventListener
base::WeakPtr<SpeechRecognizerDelegate> delegate_;
// All remaining members only accessed from the IO thread.
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info_;
// Initialized from |shared_url_loader_factory_info_| on first use.
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter_;
std::string locale_;
base::Timer speech_timeout_;
int session_;
......@@ -103,10 +112,15 @@ class SpeechRecognizer::EventListener
SpeechRecognizer::EventListener::EventListener(
const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
net::URLRequestContextGetter* url_request_context_getter,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale)
: delegate_(delegate),
url_request_context_getter_(url_request_context_getter),
shared_url_loader_factory_info_(
std::move(shared_url_loader_factory_info)),
deprecated_url_request_context_getter_(
deprecated_url_request_context_getter),
locale_(locale),
speech_timeout_(false, false),
session_(kInvalidSessionId),
......@@ -132,7 +146,14 @@ void SpeechRecognizer::EventListener::StartOnIOThread(
config.interim_results = true;
config.max_hypotheses = 1;
config.filter_profanities = true;
config.url_request_context_getter = url_request_context_getter_;
config.deprecated_url_request_context_getter =
deprecated_url_request_context_getter_;
if (!shared_url_loader_factory_) {
DCHECK(shared_url_loader_factory_info_);
shared_url_loader_factory_ = network::SharedURLLoaderFactory::Create(
std::move(shared_url_loader_factory_info_));
}
config.shared_url_loader_factory = shared_url_loader_factory_;
config.event_listener = weak_factory_.GetWeakPtr();
// kInvalidUniqueID is not a valid render process, so the speech permission
// check allows the request through.
......@@ -270,11 +291,16 @@ void SpeechRecognizer::EventListener::OnAudioEnd(int session_id) {}
SpeechRecognizer::SpeechRecognizer(
const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
net::URLRequestContextGetter* url_request_context_getter,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale)
: delegate_(delegate),
speech_event_listener_(
new EventListener(delegate, url_request_context_getter, locale)) {
new EventListener(delegate,
std::move(shared_url_loader_factory_info),
deprecated_url_request_context_getter,
locale)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
......
......@@ -5,9 +5,11 @@
#ifndef CHROME_BROWSER_SPEECH_SPEECH_RECOGNIZER_H_
#define CHROME_BROWSER_SPEECH_SPEECH_RECOGNIZER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
namespace content {
......@@ -18,6 +20,10 @@ namespace net {
class URLRequestContextGetter;
}
namespace network {
class SharedURLLoaderFactoryInfo;
}
class SpeechRecognizerDelegate;
// SpeechRecognizer is a wrapper around the speech recognition engine that
......@@ -25,9 +31,12 @@ class SpeechRecognizerDelegate;
// collection of results, error cases, and threading.
class SpeechRecognizer {
public:
SpeechRecognizer(const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
net::URLRequestContextGetter* url_request_context_getter,
const std::string& locale);
SpeechRecognizer(
const base::WeakPtr<SpeechRecognizerDelegate>& delegate,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale);
~SpeechRecognizer();
// Start/stop the speech recognizer. |preamble| contains the preamble audio to
......
......@@ -17,6 +17,7 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/fake_speech_recognition_manager.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -69,8 +70,11 @@ class AppListSpeechRecognizerBrowserTest : public InProcessBrowserTest {
};
IN_PROC_BROWSER_TEST_F(AppListSpeechRecognizerBrowserTest, RecognizeSpeech) {
SpeechRecognizer recognizer(mock_speech_delegate_->GetWeakPtr(),
browser()->profile()->GetRequestContext(), "en");
SpeechRecognizer recognizer(
mock_speech_delegate_->GetWeakPtr(),
content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
->GetURLLoaderFactoryForBrowserProcessIOThread(),
browser()->profile()->GetRequestContext(), "en");
base::RunLoop run_loop;
EXPECT_CALL(*mock_speech_delegate_,
......
......@@ -332,6 +332,7 @@ test("vr_common_unittests") {
":vr_test_support",
"//components/url_formatter",
"//mojo/public/cpp/bindings",
"//services/network:test_support",
"//testing/gmock",
"//ui/gfx/geometry",
]
......
......@@ -18,6 +18,7 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/speech_recognition_error.mojom.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/base/l10n/l10n_util.h"
namespace vr {
......@@ -57,12 +58,16 @@ class SpeechRecognizerOnIO : public content::SpeechRecognitionEventListener {
SpeechRecognizerOnIO();
~SpeechRecognizerOnIO() override;
void Start(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
const base::WeakPtr<IOBrowserUIInterface>& browser_ui,
const std::string& locale,
const std::string& auth_scope,
const std::string& auth_token);
// |shared_url_loader_factory_info| must be non-null for the first call to
// Start().
void Start(std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter,
const base::WeakPtr<IOBrowserUIInterface>& browser_ui,
const std::string& locale,
const std::string& auth_scope,
const std::string& auth_token);
void Stop();
......@@ -100,7 +105,9 @@ class SpeechRecognizerOnIO : public content::SpeechRecognitionEventListener {
base::WeakPtr<IOBrowserUIInterface> browser_ui_;
// All remaining members only accessed from the IO thread.
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter_;
std::string locale_;
std::unique_ptr<base::Timer> speech_timeout_;
int session_;
......@@ -123,7 +130,10 @@ SpeechRecognizerOnIO::~SpeechRecognizerOnIO() {
}
void SpeechRecognizerOnIO::Start(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter,
const base::WeakPtr<IOBrowserUIInterface>& browser_ui,
const std::string& locale,
const std::string& auth_scope,
......@@ -140,7 +150,13 @@ void SpeechRecognizerOnIO::Start(
config.interim_results = true;
config.max_hypotheses = 1;
config.filter_profanities = true;
config.url_request_context_getter = url_request_context_getter;
config.deprecated_url_request_context_getter =
deprecated_url_request_context_getter;
if (!shared_url_loader_factory_) {
DCHECK(shared_url_loader_factory_info);
shared_url_loader_factory_ = network::SharedURLLoaderFactory::Create(
std::move(shared_url_loader_factory_info));
}
config.event_listener = weak_factory_.GetWeakPtr();
// kInvalidUniqueID is not a valid render process, so the speech permission
// check allows the request through.
......@@ -280,11 +296,16 @@ void SpeechRecognizerOnIO::SetTimerForTest(
SpeechRecognizer::SpeechRecognizer(
VoiceResultDelegate* delegate,
BrowserUiInterface* ui,
net::URLRequestContextGetter* url_request_context_getter,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale)
: delegate_(delegate),
ui_(ui),
url_request_context_getter_(url_request_context_getter),
shared_url_loader_factory_info_(
std::move(shared_url_loader_factory_info)),
deprecated_url_request_context_getter_(
deprecated_url_request_context_getter),
locale_(locale),
speech_recognizer_on_io_(std::make_unique<SpeechRecognizerOnIO>()),
weak_factory_(this) {
......@@ -312,8 +333,10 @@ void SpeechRecognizer::Start() {
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&SpeechRecognizerOnIO::Start,
base::Unretained(speech_recognizer_on_io_.get()),
url_request_context_getter_, weak_factory_.GetWeakPtr(),
locale_, auth_scope, auth_token));
std::move(shared_url_loader_factory_info_),
deprecated_url_request_context_getter_,
weak_factory_.GetWeakPtr(), locale_, auth_scope,
auth_token));
if (ui_)
ui_->SetSpeechRecognitionEnabled(true);
final_result_.clear();
......
......@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_VR_SPEECH_RECOGNIZER_H_
#define CHROME_BROWSER_VR_SPEECH_RECOGNIZER_H_
#include <memory>
#include <string>
#include "base/macros.h"
......@@ -20,6 +21,10 @@ namespace net {
class URLRequestContextGetter;
}
namespace network {
class SharedURLLoaderFactoryInfo;
}
namespace vr {
// Note that speech recognition is activated on VR UI thread. This means it
......@@ -91,10 +96,15 @@ class IOBrowserUIInterface {
// collection of results, error cases, and threading.
class VR_EXPORT SpeechRecognizer : public IOBrowserUIInterface {
public:
SpeechRecognizer(VoiceResultDelegate* delegate,
BrowserUiInterface* ui,
net::URLRequestContextGetter* url_request_context_getter,
const std::string& locale);
// |shared_url_loader_factory_info| must be for a creating a
// SharedURLLoaderFactory that can be used on the IO Thread.
SpeechRecognizer(
VoiceResultDelegate* delegate,
BrowserUiInterface* ui,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
net::URLRequestContextGetter* deprecated_url_request_context_getter,
const std::string& locale);
~SpeechRecognizer() override;
// Start/stop the speech recognizer.
......@@ -117,7 +127,14 @@ class VR_EXPORT SpeechRecognizer : public IOBrowserUIInterface {
private:
VoiceResultDelegate* delegate_;
BrowserUiInterface* ui_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
// Non-null until first Start() call, at which point it's moved to the IO
// thread.
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info_;
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter_;
std::string locale_;
base::string16 final_result_;
......
......@@ -20,6 +20,8 @@
#include "content/public/common/speech_recognition_error.mojom.h"
#include "content/public/common/speech_recognition_result.mojom.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -43,6 +45,65 @@ enum FakeRecognitionEvent {
MULTIPLE_FINAL_RESULT,
};
// A SharedURLLoaderFactory that hangs.
class FakeSharedURLLoaderFactory : public network::SharedURLLoaderFactory {
public:
FakeSharedURLLoaderFactory() {}
// network::mojom::URLLoaderFactory:
void Clone(network::mojom::URLLoaderFactoryRequest request) override {
test_url_loader_factory_.Clone(std::move(request));
}
void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
test_url_loader_factory_.CreateLoaderAndStart(
std::move(loader), routing_id, request_id, options, request,
std::move(client), traffic_annotation);
}
// network::SharedURLLoaderFactory:
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
NOTREACHED();
return nullptr;
}
private:
friend class base::RefCounted<FakeSharedURLLoaderFactory>;
~FakeSharedURLLoaderFactory() override {}
network::TestURLLoaderFactory test_url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(FakeSharedURLLoaderFactory);
};
// Returns a SharedURLLoaderFactory that hangs.
class FakeSharedURLLoaderFactoryInfo
: public network::SharedURLLoaderFactoryInfo {
public:
FakeSharedURLLoaderFactoryInfo() {}
~FakeSharedURLLoaderFactoryInfo() override {}
protected:
friend class network::SharedURLLoaderFactory;
// network::SharedURLLoaderFactoryInfo:
scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override {
return base::MakeRefCounted<FakeSharedURLLoaderFactory>();
}
private:
DISALLOW_COPY_AND_ASSIGN(FakeSharedURLLoaderFactoryInfo);
};
class FakeSpeechRecognitionManager : public content::SpeechRecognitionManager {
public:
FakeSpeechRecognitionManager() {}
......@@ -195,8 +256,12 @@ class SpeechRecognizerTest : public testing::Test {
: fake_speech_recognition_manager_(new FakeSpeechRecognitionManager()),
ui_(new MockBrowserUiInterface),
delegate_(new MockVoiceSearchDelegate),
speech_recognizer_(
new SpeechRecognizer(delegate_.get(), ui_.get(), nullptr, "en")) {
speech_recognizer_(new SpeechRecognizer(
delegate_.get(),
ui_.get(),
std::make_unique<FakeSharedURLLoaderFactoryInfo>(),
nullptr,
"en")) {
SpeechRecognizer::SetManagerForTest(fake_speech_recognition_manager_.get());
}
......
......@@ -3340,11 +3340,8 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
&QuotaDispatcherHost::CreateForFrame, GetProcess(), routing_id_));
registry_->AddInterface(
base::BindRepeating(
SpeechRecognitionDispatcherHost::Create, GetProcess()->GetID(),
routing_id_,
base::WrapRefCounted(
GetProcess()->GetStoragePartition()->GetURLRequestContext())),
base::BindRepeating(SpeechRecognitionDispatcherHost::Create,
GetProcess()->GetID(), routing_id_),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
......
......@@ -89,7 +89,7 @@ void ChunkedByteBuffer::Append(const uint8_t* start, size_t length) {
total_bytes_stored_ += length;
}
void ChunkedByteBuffer::Append(const std::string& string) {
void ChunkedByteBuffer::Append(base::StringPiece string) {
Append(reinterpret_cast<const uint8_t*>(string.data()), string.size());
}
......
......@@ -13,6 +13,7 @@
#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
namespace content {
......@@ -36,7 +37,7 @@ class CONTENT_EXPORT ChunkedByteBuffer {
void Append(const uint8_t* start, size_t length);
// Appends bytes contained in the |string| to the buffer.
void Append(const std::string& string);
void Append(base::StringPiece string);
// Checks whether one or more complete chunks are available in the buffer.
bool HasChunks() const;
......
......@@ -20,18 +20,18 @@
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
int render_process_id,
int render_frame_id,
scoped_refptr<net::URLRequestContextGetter> context_getter)
int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
context_getter_(std::move(context_getter)),
weak_factory_(this) {
// Do not add any non-trivial initialization here, instead do it lazily when
// required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
......@@ -42,12 +42,10 @@ SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
void SpeechRecognitionDispatcherHost::Create(
int render_process_id,
int render_frame_id,
scoped_refptr<net::URLRequestContextGetter> context_getter,
mojom::SpeechRecognizerRequest request) {
mojo::MakeStrongBinding(
std::make_unique<SpeechRecognitionDispatcherHost>(
render_process_id, render_frame_id, std::move(context_getter)),
std::move(request));
mojo::MakeStrongBinding(std::make_unique<SpeechRecognitionDispatcherHost>(
render_process_id, render_frame_id),
std::move(request));
}
SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {}
......@@ -133,19 +131,28 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
->delegate()
->FilterProfanities(embedder_render_process_id);
StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&SpeechRecognitionDispatcherHost::StartSessionOnIO,
speech_recognition_dispatcher_host, std::move(params),
embedder_render_process_id, embedder_render_frame_id,
filter_profanities));
base::BindOnce(
&SpeechRecognitionDispatcherHost::StartSessionOnIO,
speech_recognition_dispatcher_host, std::move(params),
embedder_render_process_id, embedder_render_frame_id,
filter_profanities,
storage_partition->GetURLLoaderFactoryForBrowserProcessIOThread(),
base::WrapRefCounted(storage_partition->GetURLRequestContext())));
}
void SpeechRecognitionDispatcherHost::StartSessionOnIO(
mojom::StartSpeechRecognitionRequestParamsPtr params,
int embedder_render_process_id,
int embedder_render_frame_id,
bool filter_profanities) {
bool filter_profanities,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SpeechRecognitionSessionContext context;
......@@ -163,7 +170,10 @@ void SpeechRecognitionDispatcherHost::StartSessionOnIO(
config.max_hypotheses = params->max_hypotheses;
config.origin = params->origin;
config.initial_context = context;
config.url_request_context_getter = context_getter_.get();
config.shared_url_loader_factory = network::SharedURLLoaderFactory::Create(
std::move(shared_url_loader_factory_info));
config.deprecated_url_request_context_getter =
std::move(deprecated_context_getter);
config.filter_profanities = filter_profanities;
config.continuous = params->continuous;
config.interim_results = params->interim_results;
......
......@@ -17,6 +17,10 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/url_request_context_getter.h"
namespace network {
class SharedURLLoaderFactoryInfo;
}
namespace content {
class SpeechRecognitionSession;
......@@ -28,14 +32,10 @@ class SpeechRecognitionManager;
class CONTENT_EXPORT SpeechRecognitionDispatcherHost
: public mojom::SpeechRecognizer {
public:
SpeechRecognitionDispatcherHost(
int render_process_id,
int render_frame_id,
scoped_refptr<net::URLRequestContextGetter> context_getter);
SpeechRecognitionDispatcherHost(int render_process_id, int render_frame_id);
~SpeechRecognitionDispatcherHost() override;
static void Create(int render_process_id,
int render_frame_id,
scoped_refptr<net::URLRequestContextGetter> context_getter,
mojom::SpeechRecognizerRequest request);
base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
......@@ -49,14 +49,18 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
int render_process_id,
int render_frame_id,
mojom::StartSpeechRecognitionRequestParamsPtr params);
void StartSessionOnIO(mojom::StartSpeechRecognitionRequestParamsPtr params,
int embedder_render_process_id,
int embedder_render_frame_id,
bool filter_profanities);
void StartSessionOnIO(
mojom::StartSpeechRecognitionRequestParamsPtr params,
int embedder_render_process_id,
int embedder_render_frame_id,
bool filter_profanities,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
shared_url_loader_factory_info,
scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter);
const int render_process_id_;
const int render_frame_id_;
scoped_refptr<net::URLRequestContextGetter> context_getter_;
// Used for posting asynchronous tasks (on the IO thread) without worrying
// about this class being destroyed in the meanwhile (due to browser shutdown)
......
......@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
#include "content/browser/speech/audio_encoder.h"
#include "content/browser/speech/chunked_byte_buffer.h"
#include "content/common/content_export.h"
......@@ -20,12 +21,17 @@
#include "content/public/common/speech_recognition_error.mojom.h"
#include "content/public/common/speech_recognition_grammar.mojom.h"
#include "content/public/common/speech_recognition_result.mojom.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace net {
class URLRequestContextGetter;
}
namespace network {
class SharedURLLoaderFactory;
}
namespace content {
class AudioChunk;
......@@ -57,7 +63,7 @@ struct SpeechRecognitionError;
// EndRecognition. If a recognition was started, the caller can free the
// SpeechRecognitionEngine only after calling EndRecognition.
class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
class CONTENT_EXPORT SpeechRecognitionEngine {
public:
class Delegate {
public:
......@@ -97,12 +103,15 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
// Duration of each audio packet.
static const int kAudioPacketIntervalMs;
// IDs passed to URLFetcher::Create(). Used for testing.
static const int kUpstreamUrlFetcherIdForTesting;
static const int kDownstreamUrlFetcherIdForTesting;
explicit SpeechRecognitionEngine(net::URLRequestContextGetter* context);
~SpeechRecognitionEngine() override;
// |deprecated_url_request_context_getter| is only for poking at the
// Accept-Language header.
// TODO(mmenke): Remove |deprecated_url_request_context_getter| as an
// argument.
SpeechRecognitionEngine(
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter);
~SpeechRecognitionEngine();
// Sets the URL requests are sent to for tests.
static void set_web_service_base_url_for_tests(
......@@ -116,14 +125,10 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
bool IsRecognitionPending() const;
int GetDesiredAudioChunkDurationMs() const;
// net::URLFetcherDelegate methods.
void OnURLFetchComplete(const net::URLFetcher* source) override;
void OnURLFetchDownloadProgress(const net::URLFetcher* source,
int64_t current,
int64_t total,
int64_t current_network_bytes) override;
private:
class UpstreamLoader;
class DownstreamLoader;
Delegate* delegate_;
// Response status codes from the speech recognition webservice.
......@@ -173,10 +178,10 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
DISALLOW_COPY_AND_ASSIGN(FSMEventArgs);
};
// Invoked by both upstream and downstream URLFetcher callbacks to handle
// new chunk data, connection closed or errors notifications.
void DispatchHTTPResponse(const net::URLFetcher* source,
bool end_of_response);
void OnUpstreamDataComplete(bool success, int response_code);
void OnDownstreamDataReceived(base::StringPiece new_response_data);
void OnDownstreamDataComplete(bool success, int response_code);
// Entry point for pushing any new external event into the recognizer FSM.
void DispatchEvent(const FSMEventArgs& event_args);
......@@ -206,13 +211,14 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
void UploadAudioChunk(const std::string& data, FrameType type, bool is_final);
Config config_;
std::unique_ptr<net::URLFetcher> upstream_fetcher_;
std::unique_ptr<net::URLFetcher> downstream_fetcher_;
scoped_refptr<net::URLRequestContextGetter> url_context_;
std::unique_ptr<UpstreamLoader> upstream_loader_;
std::unique_ptr<DownstreamLoader> downstream_loader_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter_;
std::unique_ptr<AudioEncoder> encoder_;
std::unique_ptr<AudioEncoder> preamble_encoder_;
ChunkedByteBuffer chunked_byte_buffer_;
size_t previous_response_length_;
bool got_last_definitive_result_;
bool is_dispatching_event_;
bool use_framed_post_data_;
......
......@@ -21,6 +21,8 @@
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_context.h"
......@@ -281,7 +283,8 @@ int SpeechRecognitionManagerImpl::CreateSession(
remote_engine_config.preamble = config.preamble;
SpeechRecognitionEngine* google_remote_engine =
new SpeechRecognitionEngine(config.url_request_context_getter.get());
new SpeechRecognitionEngine(config.shared_url_loader_factory,
config.deprecated_url_request_context_getter);
google_remote_engine->SetConfig(remote_engine_config);
session->recognizer = new SpeechRecognizerImpl(
......
......@@ -16,6 +16,7 @@
#include "content/public/browser/speech_recognition_session_preamble.h"
#include "content/public/common/speech_recognition_grammar.mojom.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/origin.h"
namespace content {
......@@ -39,7 +40,11 @@ struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
std::string auth_scope;
scoped_refptr<SpeechRecognitionSessionPreamble> preamble;
SpeechRecognitionSessionContext initial_context;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory;
// TODO(mmenke): Remove this dependency.
scoped_refptr<net::URLRequestContextGetter>
deprecated_url_request_context_getter;
base::WeakPtr<SpeechRecognitionEventListener> event_listener;
};
......
......@@ -10,20 +10,22 @@
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_request_body.h"
namespace network {
TestURLLoaderFactory::PendingRequest::PendingRequest() = default;
TestURLLoaderFactory::PendingRequest::~PendingRequest() = default;
TestURLLoaderFactory::PendingRequest::PendingRequest(PendingRequest&& other) =
default;
TestURLLoaderFactory::PendingRequest& TestURLLoaderFactory::PendingRequest::
operator=(PendingRequest&& other) = default;
TestURLLoaderFactory::Response::Response() = default;
TestURLLoaderFactory::Response::~Response() = default;
TestURLLoaderFactory::Response::Response(const Response&) = default;
TestURLLoaderFactory::Pending::Pending() = default;
TestURLLoaderFactory::Pending::~Pending() = default;
TestURLLoaderFactory::Pending::Pending(Pending&& other) = default;
TestURLLoaderFactory::Pending& TestURLLoaderFactory::Pending::operator=(
Pending&& other) = default;
TestURLLoaderFactory::TestURLLoaderFactory() {}
TestURLLoaderFactory::~TestURLLoaderFactory() {}
......@@ -41,9 +43,9 @@ void TestURLLoaderFactory::AddResponse(const GURL& url,
response.status = status;
responses_[url] = response;
for (auto it = pending_.begin(); it != pending_.end();) {
for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
if (CreateLoaderAndStartInternal(it->url, it->client.get())) {
it = pending_.erase(it);
it = pending_requests_.erase(it);
} else {
++it;
}
......@@ -68,7 +70,7 @@ void TestURLLoaderFactory::AddResponse(const std::string& url,
bool TestURLLoaderFactory::IsPending(const std::string& url,
int* load_flags_out) {
base::RunLoop().RunUntilIdle();
for (const auto& candidate : pending_) {
for (const auto& candidate : pending_requests_) {
if (candidate.url == url) {
if (load_flags_out)
*load_flags_out = candidate.load_flags;
......@@ -81,7 +83,7 @@ bool TestURLLoaderFactory::IsPending(const std::string& url,
int TestURLLoaderFactory::NumPending() {
int pending = 0;
base::RunLoop().RunUntilIdle();
for (const auto& candidate : pending_) {
for (const auto& candidate : pending_requests_) {
if (!candidate.client.encountered_error())
++pending;
}
......@@ -110,11 +112,12 @@ void TestURLLoaderFactory::CreateLoaderAndStart(
if (CreateLoaderAndStartInternal(url_request.url, client.get()))
return;
Pending pending;
pending.url = url_request.url;
pending.load_flags = url_request.load_flags;
pending.client = std::move(client);
pending_.push_back(std::move(pending));
PendingRequest pending_request;
pending_request.url = url_request.url;
pending_request.load_flags = url_request.load_flags;
pending_request.client = std::move(client);
pending_request.request_body = std::move(url_request.request_body);
pending_requests_.push_back(std::move(pending_request));
}
void TestURLLoaderFactory::Clone(mojom::URLLoaderFactoryRequest request) {
......
......@@ -14,11 +14,25 @@
namespace network {
class ResourceRequestBody;
// A helper class to ease testing code that uses URLLoader interface. A test
// would pass this factory instead of the production factory to code, and
// would prime it with response data for arbitrary URLs.
class TestURLLoaderFactory : public mojom::URLLoaderFactory {
public:
struct PendingRequest {
PendingRequest();
~PendingRequest();
PendingRequest(PendingRequest&& other);
PendingRequest& operator=(PendingRequest&& other);
GURL url;
int load_flags;
mojom::URLLoaderClientPtr client;
scoped_refptr<ResourceRequestBody> request_body;
};
TestURLLoaderFactory();
~TestURLLoaderFactory() override;
......@@ -57,6 +71,11 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
using Interceptor = base::RepeatingCallback<void(const ResourceRequest&)>;
void SetInterceptor(const Interceptor& interceptor);
// Returns a mutable list of pending requests, for consumers that need direct
// access. It's recommended that consumers use AddResponse() rather than
// servicing requests themselves, whenever possible.
std::vector<PendingRequest>* pending_requests() { return &pending_requests_; }
// mojom::URLLoaderFactory implementation.
void CreateLoaderAndStart(mojom::URLLoaderRequest request,
int32_t routing_id,
......@@ -84,16 +103,7 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
};
std::map<GURL, Response> responses_;
struct Pending {
Pending();
~Pending();
Pending(Pending&& other);
Pending& operator=(Pending&& other);
GURL url;
int load_flags;
mojom::URLLoaderClientPtr client;
};
std::vector<Pending> pending_;
std::vector<PendingRequest> pending_requests_;
Interceptor interceptor_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment