Commit 229ba21c authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Create OverlayService model classes.

The public interface of OverlayService will use OverlayRequests and
OverlayResponses to hold user data used by clients to specify the types of
overlays being shown by the service.

OverlayRequests are used by the service to schedule the presentation of
overlays.  When a user interacts with overlay UI, an OverlayResponse is
supplied to the OverlayRequest that triggered the UI.  This response will
ultimately be passed to the callback for that overlay.

Each request and response is constructed with an OverlayUserData that
stores client information with requests and response.  OverlayRequests
should be created using an OverlayUserData subclass that holds the
information necessary to configure the overlay UI.  OverlayResponses
should be created using an OverlayUserData subclass that holds information
about the user's interaction with the overlay UI.

Bug: 1524991
Change-Id: Ia8472dd094e342998cda43dd9e5f8d5f037c1681
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1548572
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarMike Dougherty <michaeldo@chromium.org>
Auto-Submit: Kurt Horimoto <kkhorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#648304}
parent 63bcf45b
# Copyright 2019 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.
source_set("overlays") {
sources = [
"overlay_request.h",
"overlay_response.h",
"overlay_user_data.h",
]
configs += [ "//build/config/compiler:enable_arc" ]
allow_circular_includes_from = [ ":internal" ]
deps = [
":internal",
"//base",
]
}
source_set("internal") {
sources = [
"overlay_request_impl.cc",
"overlay_request_impl.h",
"overlay_response_impl.cc",
"overlay_response_impl.h",
]
deps = [
"//base",
]
}
source_set("unit_tests") {
testonly = true
sources = [
"overlay_request_unittest.cc",
"overlay_response_unittest.cc",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
":overlays",
"//base/test:test_support",
"//ios/chrome/browser/overlays/test",
"//ios/web/public",
"//ios/web/public/test/fakes",
"//testing/gtest",
]
}
# OverlayService
OverlayService is used to schedule the display of UI over the content area of a
WebState.
## Classes of note:
##### OverlayRequest
OverlayRequests are passed to OverlayService to trigger the display of overlay
UI over a WebState's content area. Service clients should create
OverlayRequests with an OverlayUserData subclass with the information necessary
to configure the overlay UI. The config user data can later be extracted from
OverlayRequests by the service's observers and UI delegate.
##### OverlayResponse
OverlayResponses are provided to each OverlayRequest to describe the user's
interaction with the overlay UI. Service clients should create OverlayResponses
with an OverlayUserData subclass with the overlay UI user interaction
information necessary to execute the callback for that overlay.
## Example usage of service:
### Showing an alert with a title, message, an OK button, and a Cancel button
#####1. Create OverlayUserData subclasses for the requests and responses:
A request configuration user data should be created with the information
necessary to set up the overlay UI being requested.
class AlertConfig : public OverlayUserData<AlertConfig> {
public:
const std::string& title() const;
const std::string& message() const;
const std::vector<std::string>& button\_titles() const;
private:
OVERLAY\_USER\_DATA\_SETUP(AlertConfig);
AlertConfig(const std::string& title, const std::string& message);
};
A response ino user data should be created with the information necessary to
execute the callback for the overlay.
class AlertInfo : public OverlayUserData<AlertInfo> {
public:
const size\_t tapped\_button\_index() const;
private:
OVERLAY\_USER\_DATA\_SETUP(AlertInfo);
AlertInfo(size\_t tapped\_button\_index);
};
#####2. Request an overlay using the request config user data.
An OverlayRequest for the alert can be created using:
OverlayRequest::CreateWithConfig<AlertConfig>(
"alert title", "message text");
*TODO: insert OverlayService calls when interface is added.*
#####3. Supply a response to the request.
An OverlayResponse for the alert can be created using:
OverlayResponse::CreateWithInfo<AlertInfo>(0);
*NOTE: this service is a work-in-progress, and this file only outlines how to
use the files currently in the repository. It will be updated with more
complete instructions as more of the service lands.*
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_
#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_
#include <memory>
#include "base/supports_user_data.h"
class OverlayResponse;
// Model object used to track overlays requested for OverlayService.
class OverlayRequest {
public:
OverlayRequest() = default;
virtual ~OverlayRequest() = default;
// Creates an OverlayRequest configured with an OverlayUserData of type
// ConfigType. The ConfigType is constructed using the arguments passed to
// this function. For example, if a configuration of type StringConfig has
// a constructor that takes a string, a request configured with a StringConfig
// can be created using:
//
// OverlayRequest::CreateWithConfig<StringConfig>("configuration string");
template <class ConfigType, typename... Args>
static std::unique_ptr<OverlayRequest> CreateWithConfig(Args&&... args) {
std::unique_ptr<OverlayRequest> request = OverlayRequest::Create();
request->data().SetUserData(
ConfigType::UserDataKey(),
ConfigType::Create(std::forward<Args>(args)...));
return request;
}
// Returns the OverlayUserData of type ConfigType stored in the request's
// user data, or nullptr if it is not found. For example, a configuration of
// type Config can be retrieved using:
//
// request->GetConfig<Config>();
template <class ConfigType>
ConfigType* GetConfig() {
return static_cast<ConfigType*>(
data().GetUserData(ConfigType::UserDataKey()));
}
// Setter for the response object for this request.
virtual void set_response(std::unique_ptr<OverlayResponse> response) = 0;
// The response for this request. It is constructed with an
// OverlayResponseInfo containing user interaction information for the overlay
// UI resulting from this request.
virtual OverlayResponse* response() const = 0;
private:
// Creates an unconfigured OverlayRequest.
static std::unique_ptr<OverlayRequest> Create();
// The container used to hold the user data.
virtual base::SupportsUserData& data() = 0;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_
// Copyright 2019 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 "ios/chrome/browser/overlays/overlay_request_impl.h"
#include "ios/chrome/browser/overlays/overlay_response.h"
// static
std::unique_ptr<OverlayRequest> OverlayRequest::Create() {
return std::make_unique<OverlayRequestImpl>();
}
OverlayRequestImpl::OverlayRequestImpl() {}
OverlayRequestImpl::~OverlayRequestImpl() {}
base::SupportsUserData& OverlayRequestImpl::data() {
return *this;
}
void OverlayRequestImpl::set_response(
std::unique_ptr<OverlayResponse> response) {
response_ = std::move(response);
}
OverlayResponse* OverlayRequestImpl::response() const {
return response_.get();
}
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_
#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_
#include <memory>
#include "ios/chrome/browser/overlays/overlay_request.h"
// Internal implementation of OverlayRequest.
class OverlayRequestImpl : public OverlayRequest,
public base::SupportsUserData {
public:
OverlayRequestImpl();
~OverlayRequestImpl() override;
private:
// OverlayRequest:
void set_response(std::unique_ptr<OverlayResponse> response) override;
OverlayResponse* response() const override;
base::SupportsUserData& data() override;
// The response containing the user interaction information for the overlay
// resulting from this response.
std::unique_ptr<OverlayResponse> response_;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_
// Copyright 2019 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 "ios/chrome/browser/overlays/overlay_request.h"
#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
#include "testing/platform_test.h"
using OverlayRequestTest = PlatformTest;
// Tests that OverlayRequests can be created.
TEST_F(OverlayRequestTest, CreateWithConfig) {
int value = 0;
std::unique_ptr<OverlayRequest> request =
OverlayRequest::CreateWithConfig<FakeOverlayUserData>(&value);
FakeOverlayUserData* config = request->GetConfig<FakeOverlayUserData>();
ASSERT_TRUE(config);
EXPECT_EQ(config->value(), &value);
}
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_
#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_
#include <memory>
#include "base/supports_user_data.h"
// Model object used to store information about user interaction with overlay
// UI.
class OverlayResponse {
public:
OverlayResponse() = default;
virtual ~OverlayResponse() = default;
// Creates an OverlayResponse with an OverlayUserData of type InfoType.
// The InfoType is constructed using the arguments passed to this function.
// For example, if an info of type IntInfo has a constructor that takes an
// int, a response with an IntInfo can be created using:
//
// OverlayResponse::CreateWithInfo<IntInfo>(0);
template <class InfoType, typename... Args>
static std::unique_ptr<OverlayResponse> CreateWithInfo(Args&&... args) {
std::unique_ptr<OverlayResponse> response = OverlayResponse::Create();
response->data().SetUserData(InfoType::UserDataKey(),
InfoType::Create(std::forward<Args>(args)...));
return response;
}
// Returns the OverlayResponseInfo of type InfoType stored in the reponse's
// user data, or nullptr if it is not found. For example, an info of type
// Info can be retrieved using:
//
// response->GetInfo<Info>();
template <class InfoType>
InfoType* GetInfo() {
return static_cast<InfoType*>(data().GetUserData(InfoType::UserDataKey()));
}
private:
// Creates an OverlayResponse with no info attached to it.
static std::unique_ptr<OverlayResponse> Create();
// The container used to hold the user data.
virtual base::SupportsUserData& data() = 0;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_
// Copyright 2019 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 "ios/chrome/browser/overlays/overlay_response_impl.h"
// static
std::unique_ptr<OverlayResponse> OverlayResponse::Create() {
return std::make_unique<OverlayResponseImpl>();
}
OverlayResponseImpl::OverlayResponseImpl() {}
OverlayResponseImpl::~OverlayResponseImpl() {}
base::SupportsUserData& OverlayResponseImpl::data() {
return *this;
}
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_
#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_
#include "ios/chrome/browser/overlays/overlay_response.h"
// Internal implementation of OverlayResponse.
class OverlayResponseImpl : public OverlayResponse,
public base::SupportsUserData {
public:
OverlayResponseImpl();
~OverlayResponseImpl() override;
private:
// OverlayResponse:
base::SupportsUserData& data() override;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_
// Copyright 2019 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 "ios/chrome/browser/overlays/overlay_response.h"
#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
#include "testing/platform_test.h"
using OverlayResponseTest = PlatformTest;
// Tests that OverlayResponses can be constructed.
TEST_F(OverlayResponseTest, CreateWithInfo) {
int value = 0;
std::unique_ptr<OverlayResponse> request =
OverlayResponse::CreateWithInfo<FakeOverlayUserData>(&value);
FakeOverlayUserData* info = request->GetInfo<FakeOverlayUserData>();
ASSERT_TRUE(info);
EXPECT_EQ(info->value(), &value);
}
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_
#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_
#include "base/memory/ptr_util.h"
#include "base/supports_user_data.h"
// Macro for OverlayUserData setup [add to .h file]:
// - Declares a static variable inside subclasses. The address of this static
// variable is used as the key to associate the OverlayUserData with its
// user data container.
// - Adds a friend specification for OverlayUserData so it can access
// specializations' private constructors and user data keys.
#define OVERLAY_USER_DATA_SETUP(Type) \
static constexpr int kUserDataKey = 0; \
friend class OverlayUserData<Type>
// Macro for OverlayUserData setup implementation [add to .cc/.mm file]:
// - Instantiates the static variable declared by the previous macro. It must
// live in a .cc/.mm file to ensure that there is only one instantiation of
// the static variable.
#define OVERLAY_USER_DATA_SETUP_IMPL(Type) const int Type::kUserDataKey
// A base class for classes attached to, and scoped to, the lifetime of a user
// data container (e.g. OverlayRequest, OverlayResponse).
//
// --- in data.h ---
// class Data : public OverlayUserData<Data> {
// public:
// ~Data() override;
// // ... more public stuff here ...
// private:
// OVERLAY_USER_DATA_SETUP(Data);
// explicit Data( \* ANY ARGUMENT LIST SUPPORTED *\);
// // ... more private stuff here ...
// };
//
// --- in data.cc ---
// OVERLAY_USER_DATA_SETUP_IMPL(Data);
template <class DataType>
class OverlayUserData : public base::SupportsUserData::Data {
public:
// Creates an OverlayUserData of type DataType. The DataType instance is
// constructed using the arguments passed to this function. For example, if
// the constructor for an OverlayUserData of type StringData takes a string,
// one can be created using:
//
// StringData::Create("string");
template <typename... Args>
static std::unique_ptr<DataType> Create(Args&&... args) {
return base::WrapUnique(new DataType(std::forward<Args>(args)...));
}
// The key under which to store the user data.
static const void* UserDataKey() { return &DataType::kUserDataKey; }
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_
# Copyright 2019 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.
source_set("test") {
testonly = true
sources = [
"fake_overlay_user_data.cc",
"fake_overlay_user_data.h",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
"//base",
"//ios/chrome/browser/overlays",
"//testing/gtest",
]
}
// Copyright 2019 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 "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
OVERLAY_USER_DATA_SETUP_IMPL(FakeOverlayUserData);
FakeOverlayUserData::FakeOverlayUserData(void* value) : value_(value) {}
// Copyright 2019 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 IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_
#define IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_
#include "ios/chrome/browser/overlays/overlay_user_data.h"
// Test OverlayUserData that can be used to store arbitrary pointers in
// OverlayRequests and OverlayResponses.
class FakeOverlayUserData : public OverlayUserData<FakeOverlayUserData> {
public:
// Accessor for value pointer.
void* value() const { return value_; }
private:
OVERLAY_USER_DATA_SETUP(FakeOverlayUserData);
FakeOverlayUserData(void* value);
void* value_ = nullptr;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_
...@@ -160,6 +160,7 @@ test("ios_chrome_unittests") { ...@@ -160,6 +160,7 @@ test("ios_chrome_unittests") {
"//ios/chrome/browser/net:unit_tests", "//ios/chrome/browser/net:unit_tests",
"//ios/chrome/browser/ntp:unit_tests", "//ios/chrome/browser/ntp:unit_tests",
"//ios/chrome/browser/omaha:unit_tests", "//ios/chrome/browser/omaha:unit_tests",
"//ios/chrome/browser/overlays:unit_tests",
"//ios/chrome/browser/overscroll_actions:unit_tests", "//ios/chrome/browser/overscroll_actions:unit_tests",
"//ios/chrome/browser/passwords:unit_tests", "//ios/chrome/browser/passwords:unit_tests",
"//ios/chrome/browser/payments:unit_tests", "//ios/chrome/browser/payments:unit_tests",
......
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