Commit be11946a authored by Jeroen Dhollander's avatar Jeroen Dhollander Committed by Commit Bot

Finish BloomController by adding BloomServerProxy

|BloomServerProxy| will handle all communication with the Bloom servers.

Bug: b/165356952
Tests: chromeos_components_unittests --gtest_filter="Bloom*.*"
Change-Id: I0fbcdf1c35b0a2f29ebb963a363ce51eeb742b28
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2364065
Commit-Queue: Jeroen Dhollander <jeroendh@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803519}
parent 48d758b1
...@@ -11,6 +11,9 @@ source_set("bloom") { ...@@ -11,6 +11,9 @@ source_set("bloom") {
"bloom_interaction_observer.h", "bloom_interaction_observer.h",
"bloom_interaction_observer_impl.cc", "bloom_interaction_observer_impl.cc",
"bloom_interaction_observer_impl.h", "bloom_interaction_observer_impl.h",
"bloom_server_proxy.h",
"bloom_server_proxy_impl.cc",
"bloom_server_proxy_impl.h",
"screenshot_grabber.h", "screenshot_grabber.h",
] ]
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "chromeos/components/bloom/bloom_interaction.h" #include "chromeos/components/bloom/bloom_interaction.h"
#include "chromeos/components/bloom/bloom_server_proxy.h"
#include "chromeos/components/bloom/screenshot_grabber.h" #include "chromeos/components/bloom/screenshot_grabber.h"
namespace chromeos { namespace chromeos {
...@@ -13,11 +14,14 @@ namespace bloom { ...@@ -13,11 +14,14 @@ namespace bloom {
BloomControllerImpl::BloomControllerImpl( BloomControllerImpl::BloomControllerImpl(
signin::IdentityManager* identity_manager, signin::IdentityManager* identity_manager,
std::unique_ptr<ScreenshotGrabber> screenshot_grabber) std::unique_ptr<ScreenshotGrabber> screenshot_grabber,
std::unique_ptr<BloomServerProxy> server_proxy)
: identity_manager_(identity_manager), : identity_manager_(identity_manager),
screenshot_grabber_(std::move(screenshot_grabber)) { screenshot_grabber_(std::move(screenshot_grabber)),
server_proxy_(std::move(server_proxy)) {
DCHECK(identity_manager_); DCHECK(identity_manager_);
DCHECK(screenshot_grabber_); DCHECK(screenshot_grabber_);
DCHECK(server_proxy_);
} }
BloomControllerImpl::~BloomControllerImpl() = default; BloomControllerImpl::~BloomControllerImpl() = default;
...@@ -39,6 +43,11 @@ void BloomControllerImpl::ShowUI() { ...@@ -39,6 +43,11 @@ void BloomControllerImpl::ShowUI() {
observer.OnShowUI(); observer.OnShowUI();
} }
void BloomControllerImpl::ShowResult(const std::string& result) {
for (auto& observer : interaction_observers_)
observer.OnShowResult(result);
}
void BloomControllerImpl::StopInteraction( void BloomControllerImpl::StopInteraction(
BloomInteractionResolution resolution) { BloomInteractionResolution resolution) {
DCHECK(current_interaction_); DCHECK(current_interaction_);
......
...@@ -20,12 +20,14 @@ namespace chromeos { ...@@ -20,12 +20,14 @@ namespace chromeos {
namespace bloom { namespace bloom {
class BloomInteraction; class BloomInteraction;
class BloomServerProxy;
class ScreenshotGrabber; class ScreenshotGrabber;
class BloomControllerImpl : public BloomController { class BloomControllerImpl : public BloomController {
public: public:
BloomControllerImpl(signin::IdentityManager* identity_manager, BloomControllerImpl(signin::IdentityManager* identity_manager,
std::unique_ptr<ScreenshotGrabber> screenshot_grabber); std::unique_ptr<ScreenshotGrabber> screenshot_grabber,
std::unique_ptr<BloomServerProxy> server_proxy);
BloomControllerImpl(const BloomControllerImpl&) = delete; BloomControllerImpl(const BloomControllerImpl&) = delete;
BloomControllerImpl& operator=(const BloomControllerImpl&) = delete; BloomControllerImpl& operator=(const BloomControllerImpl&) = delete;
~BloomControllerImpl() override; ~BloomControllerImpl() override;
...@@ -38,8 +40,10 @@ class BloomControllerImpl : public BloomController { ...@@ -38,8 +40,10 @@ class BloomControllerImpl : public BloomController {
void AddObserver(std::unique_ptr<BloomInteractionObserver> observer) override; void AddObserver(std::unique_ptr<BloomInteractionObserver> observer) override;
void ShowUI(); void ShowUI();
void ShowResult(const std::string& result);
ScreenshotGrabber* screenshot_grabber() { return screenshot_grabber_.get(); } ScreenshotGrabber* screenshot_grabber() { return screenshot_grabber_.get(); }
BloomServerProxy* server_proxy() { return server_proxy_.get(); }
signin::IdentityManager* identity_manager() { return identity_manager_; } signin::IdentityManager* identity_manager() { return identity_manager_; }
void SetScreenshotGrabberForTesting(std::unique_ptr<ScreenshotGrabber>); void SetScreenshotGrabberForTesting(std::unique_ptr<ScreenshotGrabber>);
...@@ -47,6 +51,7 @@ class BloomControllerImpl : public BloomController { ...@@ -47,6 +51,7 @@ class BloomControllerImpl : public BloomController {
private: private:
signin::IdentityManager* const identity_manager_; signin::IdentityManager* const identity_manager_;
std::unique_ptr<ScreenshotGrabber> screenshot_grabber_; std::unique_ptr<ScreenshotGrabber> screenshot_grabber_;
std::unique_ptr<BloomServerProxy> server_proxy_;
base::ObserverList<BloomInteractionObserver> interaction_observers_; base::ObserverList<BloomInteractionObserver> interaction_observers_;
std::vector<std::unique_ptr<BloomInteractionObserver>> std::vector<std::unique_ptr<BloomInteractionObserver>>
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chromeos/components/bloom/bloom_controller_impl.h" #include "chromeos/components/bloom/bloom_controller_impl.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "chromeos/components/bloom/bloom_interaction_observer.h" #include "chromeos/components/bloom/bloom_interaction_observer.h"
#include "chromeos/components/bloom/bloom_server_proxy.h"
#include "chromeos/components/bloom/public/cpp/bloom_interaction_resolution.h" #include "chromeos/components/bloom/public/cpp/bloom_interaction_resolution.h"
#include "chromeos/components/bloom/screenshot_grabber.h" #include "chromeos/components/bloom/screenshot_grabber.h"
#include "chromeos/services/assistant/public/shared/constants.h" #include "chromeos/services/assistant/public/shared/constants.h"
...@@ -19,11 +20,14 @@ namespace bloom { ...@@ -19,11 +20,14 @@ namespace bloom {
namespace { namespace {
using ::testing::_;
using ::testing::AnyNumber; using ::testing::AnyNumber;
using ::testing::NiceMock; using ::testing::NiceMock;
const char kEmail[] = "test@gmail.com"; const char kEmail[] = "test@gmail.com";
#define EXPECT_NO_CALLS(args...) EXPECT_CALL(args).Times(0)
class ScreenshotGrabberMock : public ScreenshotGrabber { class ScreenshotGrabberMock : public ScreenshotGrabber {
public: public:
ScreenshotGrabberMock() { ScreenshotGrabberMock() {
...@@ -95,7 +99,35 @@ class BloomInteractionTracker : public BloomInteractionObserver { ...@@ -95,7 +99,35 @@ class BloomInteractionTracker : public BloomInteractionObserver {
BloomInteractionResolution::kNormal; BloomInteractionResolution::kNormal;
}; };
#define EXPECT_NO_CALLS(args...) EXPECT_CALL(args).Times(0) class BloomServerProxyMock : public BloomServerProxy {
public:
BloomServerProxyMock() {
ON_CALL(*this, AnalyzeProblem)
.WillByDefault([this](const std::string& access_token,
const Screenshot screenshot, Callback callback) {
// Store the callback passed to AnalyzeProblem() so we can invoke it
// later from our tests.
this->callback_ = std::move(callback);
});
}
MOCK_METHOD(void,
AnalyzeProblem,
(const std::string& access_token,
const Screenshot screenshot,
Callback callback));
void SendResponse(base::Optional<std::string> html = std::string("<html/>")) {
EXPECT_TRUE(callback_) << "AnalyzeProblem() was never called.";
if (callback_)
std::move(callback_).Run(html);
}
void SendResponseFailure() { SendResponse(base::nullopt); }
private:
Callback callback_;
};
} // namespace } // namespace
...@@ -111,6 +143,7 @@ void PrintTo(const BloomInteractionResolution& value, std::ostream* output) { ...@@ -111,6 +143,7 @@ void PrintTo(const BloomInteractionResolution& value, std::ostream* output) {
CASE(kNormal); CASE(kNormal);
CASE(kNoScreenshot); CASE(kNoScreenshot);
CASE(kNoAccessToken); CASE(kNoAccessToken);
CASE(kServerError);
} }
} }
...@@ -121,6 +154,14 @@ class BloomControllerImplTest : public testing::Test { ...@@ -121,6 +154,14 @@ class BloomControllerImplTest : public testing::Test {
} }
protected: protected:
void StartInteractionAndSendAccessTokenAndScreenshot(
std::string access_token = "<access-token>",
Screenshot screenshot = Screenshot()) {
controller().StartInteraction();
IssueAccessToken(access_token);
screenshot_grabber_mock().SendScreenshot(screenshot);
}
// Returns the |ScopeSet| that was passed to the access token request. // Returns the |ScopeSet| that was passed to the access token request.
// Fails the test and returns an empty |ScopeSet| if there were no access // Fails the test and returns an empty |ScopeSet| if there were no access
// token requests. // token requests.
...@@ -156,6 +197,10 @@ class BloomControllerImplTest : public testing::Test { ...@@ -156,6 +197,10 @@ class BloomControllerImplTest : public testing::Test {
return raw_ptr; return raw_ptr;
} }
BloomServerProxyMock& bloom_server() {
return *static_cast<BloomServerProxyMock*>(controller_.server_proxy());
}
void IssueAccessToken(std::string token = std::string("<access-token>")) { void IssueAccessToken(std::string token = std::string("<access-token>")) {
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
token, /*expiration=*/base::Time::Max()); token, /*expiration=*/base::Time::Max());
...@@ -172,7 +217,8 @@ class BloomControllerImplTest : public testing::Test { ...@@ -172,7 +217,8 @@ class BloomControllerImplTest : public testing::Test {
BloomControllerImpl controller_{ BloomControllerImpl controller_{
identity_test_env_.identity_manager(), identity_test_env_.identity_manager(),
std::make_unique<NiceMock<ScreenshotGrabberMock>>()}; std::make_unique<NiceMock<ScreenshotGrabberMock>>(),
std::make_unique<NiceMock<BloomServerProxyMock>>()};
}; };
TEST_F(BloomControllerImplTest, ShouldBeReturnedWhenCallingGet) { TEST_F(BloomControllerImplTest, ShouldBeReturnedWhenCallingGet) {
...@@ -221,6 +267,27 @@ TEST_F(BloomControllerImplTest, ShouldAbortWhenFetchingScreenshotFails) { ...@@ -221,6 +267,27 @@ TEST_F(BloomControllerImplTest, ShouldAbortWhenFetchingScreenshotFails) {
interaction_tracker->GetLastInteractionResolution()); interaction_tracker->GetLastInteractionResolution());
} }
TEST_F(BloomControllerImplTest,
ShouldPassAccessTokenAndScreenshotToBloomServer) {
const std::string& access_token = "<the-access-token>";
const Screenshot screenshot{1, 2, 3, 4, 5};
EXPECT_CALL(bloom_server(), AnalyzeProblem(access_token, screenshot, _));
StartInteractionAndSendAccessTokenAndScreenshot(access_token, screenshot);
}
TEST_F(BloomControllerImplTest, ShouldAbortWhenBloomServerFails) {
auto* interaction_tracker = AddInteractionTracker();
StartInteractionAndSendAccessTokenAndScreenshot();
bloom_server().SendResponseFailure();
EXPECT_FALSE(interaction_tracker->HasInteraction());
EXPECT_EQ(BloomInteractionResolution::kServerError,
interaction_tracker->GetLastInteractionResolution());
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// ///
/// Below are the tests to ensure the BloomInteractionObserver is invoked. /// Below are the tests to ensure the BloomInteractionObserver is invoked.
...@@ -240,7 +307,6 @@ TEST_F(BloomInteractionObserverTest, ...@@ -240,7 +307,6 @@ TEST_F(BloomInteractionObserverTest,
TEST_F(BloomInteractionObserverTest, TEST_F(BloomInteractionObserverTest,
ShouldCallOnShowUIWhenAccessTokenAndScreenshotAreReady) { ShouldCallOnShowUIWhenAccessTokenAndScreenshotAreReady) {
auto* observer = AddInteractionObserverMock(); auto* observer = AddInteractionObserverMock();
EXPECT_CALL(*observer, OnInteractionStarted);
EXPECT_CALL(*observer, OnShowUI); EXPECT_CALL(*observer, OnShowUI);
...@@ -252,7 +318,6 @@ TEST_F(BloomInteractionObserverTest, ...@@ -252,7 +318,6 @@ TEST_F(BloomInteractionObserverTest,
TEST_F(BloomInteractionObserverTest, TEST_F(BloomInteractionObserverTest,
ShouldNotCallOnShowUIBeforeAccessTokenArrives) { ShouldNotCallOnShowUIBeforeAccessTokenArrives) {
auto* observer = AddInteractionObserverMock(); auto* observer = AddInteractionObserverMock();
EXPECT_CALL(*observer, OnInteractionStarted);
EXPECT_NO_CALLS(*observer, OnShowUI); EXPECT_NO_CALLS(*observer, OnShowUI);
...@@ -263,7 +328,6 @@ TEST_F(BloomInteractionObserverTest, ...@@ -263,7 +328,6 @@ TEST_F(BloomInteractionObserverTest,
TEST_F(BloomInteractionObserverTest, TEST_F(BloomInteractionObserverTest,
ShouldNotCallOnShowUIBeforeScreenshotArrives) { ShouldNotCallOnShowUIBeforeScreenshotArrives) {
auto* observer = AddInteractionObserverMock(); auto* observer = AddInteractionObserverMock();
EXPECT_CALL(*observer, OnInteractionStarted);
EXPECT_NO_CALLS(*observer, OnShowUI); EXPECT_NO_CALLS(*observer, OnShowUI);
...@@ -271,5 +335,14 @@ TEST_F(BloomInteractionObserverTest, ...@@ -271,5 +335,14 @@ TEST_F(BloomInteractionObserverTest,
IssueAccessToken(); IssueAccessToken();
} }
TEST_F(BloomInteractionObserverTest, ShouldForwardServerResponse) {
auto* observer = AddInteractionObserverMock();
StartInteractionAndSendAccessTokenAndScreenshot();
EXPECT_CALL(*observer, OnShowResult("<html>response</html>"));
bloom_server().SendResponse("<html>response</html>");
}
} // namespace bloom } // namespace bloom
} // namespace chromeos } // namespace chromeos
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chromeos/components/bloom/bloom_controller_impl.h" #include "chromeos/components/bloom/bloom_controller_impl.h"
#include "chromeos/components/bloom/bloom_interaction.h" #include "chromeos/components/bloom/bloom_interaction.h"
#include "chromeos/components/bloom/bloom_server_proxy.h"
#include "chromeos/components/bloom/public/cpp/future_value.h" #include "chromeos/components/bloom/public/cpp/future_value.h"
#include "chromeos/components/bloom/screenshot_grabber.h" #include "chromeos/components/bloom/screenshot_grabber.h"
#include "chromeos/services/assistant/public/shared/constants.h" #include "chromeos/services/assistant/public/shared/constants.h"
...@@ -34,7 +35,17 @@ void BloomInteraction::Start() { ...@@ -34,7 +35,17 @@ void BloomInteraction::Start() {
void BloomInteraction::StartAssistantInteraction(std::string&& access_token, void BloomInteraction::StartAssistantInteraction(std::string&& access_token,
Screenshot&& screenshot) { Screenshot&& screenshot) {
controller_->ShowUI(); controller_->ShowUI();
// TODO(jeroendh): continue here by contacting the Bloom service. controller_->server_proxy()->AnalyzeProblem(
access_token, screenshot, Bind(&BloomInteraction::OnServerResponse));
}
void BloomInteraction::OnServerResponse(base::Optional<std::string> html) {
if (!html) {
controller_->StopInteraction(BloomInteractionResolution ::kServerError);
return;
}
controller_->ShowResult(html.value());
} }
void BloomInteraction::FetchAccessTokenAsync() { void BloomInteraction::FetchAccessTokenAsync() {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string> #include <string>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/optional.h"
#include "chromeos/components/bloom/screenshot_grabber.h" #include "chromeos/components/bloom/screenshot_grabber.h"
class GoogleServiceAuthError; class GoogleServiceAuthError;
...@@ -48,6 +49,8 @@ class BloomInteraction { ...@@ -48,6 +49,8 @@ class BloomInteraction {
void StartAssistantInteraction(std::string&& access_token, void StartAssistantInteraction(std::string&& access_token,
Screenshot&& screenshot); Screenshot&& screenshot);
void OnServerResponse(base::Optional<std::string> html);
void FetchAccessTokenAsync(); void FetchAccessTokenAsync();
void FetchScreenshotAsync(); void FetchScreenshotAsync();
......
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_H_
#define CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_H_
#include <string>
#include "base/callback.h"
#include "chromeos/components/bloom/screenshot_grabber.h"
namespace chromeos {
namespace bloom {
// Local object that handles all communication with the Bloom servers.
class BloomServerProxy {
public:
using Callback =
base::OnceCallback<void(base::Optional<std::string> response)>;
BloomServerProxy() = default;
BloomServerProxy(BloomServerProxy&) = delete;
BloomServerProxy& operator=(BloomServerProxy&) = delete;
virtual ~BloomServerProxy() = default;
// Send the screenshot to the Bloom server for analysis, and send the response
// to |callback|.
virtual void AnalyzeProblem(const std::string& access_token,
const Screenshot screenshot,
Callback callback) = 0;
};
} // namespace bloom
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_H_
// Copyright 2020 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 "chromeos/components/bloom/bloom_server_proxy_impl.h"
namespace chromeos {
namespace bloom {
BloomServerProxyImpl::BloomServerProxyImpl() = default;
BloomServerProxyImpl::~BloomServerProxyImpl() = default;
void BloomServerProxyImpl::AnalyzeProblem(const std::string& access_token,
const Screenshot screenshot,
Callback callback) {
// TODO(jeroendh): implement
}
} // namespace bloom
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_IMPL_H_
#define CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_IMPL_H_
#include "chromeos/components/bloom/bloom_server_proxy.h"
namespace chromeos {
namespace bloom {
class BloomServerProxyImpl : public BloomServerProxy {
public:
BloomServerProxyImpl();
~BloomServerProxyImpl() override;
void AnalyzeProblem(const std::string& access_token,
const Screenshot screenshot,
Callback callback) override;
};
} // namespace bloom
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_BLOOM_BLOOM_SERVER_PROXY_IMPL_H_
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
#include "chromeos/components/bloom/public/cpp/bloom_controller_factory.h" #include "chromeos/components/bloom/public/cpp/bloom_controller_factory.h"
#include <memory>
#include "base/callback.h" #include "base/callback.h"
#include "chromeos/components/bloom/bloom_controller_impl.h" #include "chromeos/components/bloom/bloom_controller_impl.h"
#include "chromeos/components/bloom/bloom_interaction_observer_impl.h" #include "chromeos/components/bloom/bloom_interaction_observer_impl.h"
#include "chromeos/components/bloom/bloom_server_proxy_impl.h"
#include "chromeos/components/bloom/screenshot_grabber.h" #include "chromeos/components/bloom/screenshot_grabber.h"
namespace chromeos { namespace chromeos {
...@@ -28,9 +31,12 @@ std::unique_ptr<BloomController> BloomControllerFactory::Create( ...@@ -28,9 +31,12 @@ std::unique_ptr<BloomController> BloomControllerFactory::Create(
signin::IdentityManager* identity_manager, signin::IdentityManager* identity_manager,
ash::AssistantInteractionController* assistant_interaction_controller) { ash::AssistantInteractionController* assistant_interaction_controller) {
auto result = std::make_unique<BloomControllerImpl>( auto result = std::make_unique<BloomControllerImpl>(
identity_manager, std::make_unique<FakeScreenshotGrabber>()); identity_manager, std::make_unique<FakeScreenshotGrabber>(),
std::make_unique<BloomServerProxyImpl>());
result->AddObserver(std::make_unique<BloomInteractionObserverImpl>( result->AddObserver(std::make_unique<BloomInteractionObserverImpl>(
assistant_interaction_controller)); assistant_interaction_controller));
return std::move(result); return std::move(result);
} }
......
...@@ -16,6 +16,7 @@ std::string ToString(BloomInteractionResolution resolution) { ...@@ -16,6 +16,7 @@ std::string ToString(BloomInteractionResolution resolution) {
CASE(kNormal); CASE(kNormal);
CASE(kNoAccessToken); CASE(kNoAccessToken);
CASE(kNoScreenshot); CASE(kNoScreenshot);
CASE(kServerError);
} }
} }
......
...@@ -16,10 +16,12 @@ enum class BloomInteractionResolution { ...@@ -16,10 +16,12 @@ enum class BloomInteractionResolution {
// Bloom interaction completed normally. // Bloom interaction completed normally.
kNormal = 0, kNormal = 0,
// Bloom interaction failed to fetch an access token. // Bloom interaction failed to fetch an access token.
kNoAccessToken = 1, kNoAccessToken,
// Bloom interaction failed to take a screenshot // Bloom interaction failed to take a screenshot
// (or the user aborted while taking a screenshot). // (or the user aborted while taking a screenshot).
kNoScreenshot = 2, kNoScreenshot,
// Bloom server returned an error.
kServerError,
}; };
std::string COMPONENT_EXPORT(BLOOM) std::string COMPONENT_EXPORT(BLOOM)
......
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