Commit 7ed44a41 authored by Hoch Hochkeppel's avatar Hoch Hochkeppel Committed by Commit Bot

WebShare: FakeDataTransferManager Deferral and test interception support

Adding support for IDataRequestDeferral to the FakeDataTransferManager,
as well as adding a test-only PostDataRequested event for easily
intercepting the data shared by a DataRequested handler. Also expanding
the corresponding tests to validate this new behavior.

Bug: 1035527
Change-Id: I44589302272e432b3ea7201b50faa2d90d254194
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500947Reviewed-by: default avatarEric Willigers <ericwilligers@chromium.org>
Commit-Queue: Hoch Hochkeppel <mhochk@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#821431}
parent 631aed2d
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/win/core_winrt_util.h" #include "base/win/core_winrt_util.h"
#include "base/win/scoped_hstring.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -27,6 +28,9 @@ using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs; ...@@ -27,6 +28,9 @@ using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs;
using ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager; using ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager;
using ABI::Windows::Foundation::DateTime; using ABI::Windows::Foundation::DateTime;
using ABI::Windows::Foundation::IUriRuntimeClass; using ABI::Windows::Foundation::IUriRuntimeClass;
using ABI::Windows::Foundation::Collections::IIterator;
using ABI::Windows::Storage::IStorageFile;
using ABI::Windows::Storage::IStorageItem;
using ABI::Windows::Storage::Streams::IRandomAccessStreamReference; using ABI::Windows::Storage::Streams::IRandomAccessStreamReference;
using Microsoft::WRL::ActivationFactory; using Microsoft::WRL::ActivationFactory;
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
...@@ -54,7 +58,9 @@ class FakeDataPackagePropertySet ...@@ -54,7 +58,9 @@ class FakeDataPackagePropertySet
IDataPackagePropertySet, IDataPackagePropertySet,
IDataPackagePropertySet3> { IDataPackagePropertySet3> {
public: public:
FakeDataPackagePropertySet() = default; FakeDataPackagePropertySet(
FakeDataTransferManager::DataRequestedContent& data_requested_content)
: data_requested_content_(data_requested_content) {}
FakeDataPackagePropertySet(const FakeDataPackagePropertySet&) = delete; FakeDataPackagePropertySet(const FakeDataPackagePropertySet&) = delete;
FakeDataPackagePropertySet& operator=(const FakeDataPackagePropertySet&) = FakeDataPackagePropertySet& operator=(const FakeDataPackagePropertySet&) =
delete; delete;
...@@ -92,7 +98,11 @@ class FakeDataPackagePropertySet ...@@ -92,7 +98,11 @@ class FakeDataPackagePropertySet
IFACEMETHODIMP put_Thumbnail(IRandomAccessStreamReference* value) override { IFACEMETHODIMP put_Thumbnail(IRandomAccessStreamReference* value) override {
return S_OK; return S_OK;
} }
IFACEMETHODIMP put_Title(HSTRING value) override { return S_OK; } IFACEMETHODIMP put_Title(HSTRING value) override {
base::win::ScopedHString wrapped_value(value);
data_requested_content_.title = wrapped_value.GetAsUTF8();
return S_OK;
}
// IDataPackagePropertySet3 // IDataPackagePropertySet3
IFACEMETHODIMP get_EnterpriseId(HSTRING* value) override { IFACEMETHODIMP get_EnterpriseId(HSTRING* value) override {
...@@ -100,6 +110,9 @@ class FakeDataPackagePropertySet ...@@ -100,6 +110,9 @@ class FakeDataPackagePropertySet
return E_NOTIMPL; return E_NOTIMPL;
} }
IFACEMETHODIMP put_EnterpriseId(HSTRING value) override { return S_OK; } IFACEMETHODIMP put_EnterpriseId(HSTRING value) override { return S_OK; }
private:
FakeDataTransferManager::DataRequestedContent& data_requested_content_;
}; };
class FakeDataPackage class FakeDataPackage
...@@ -107,7 +120,9 @@ class FakeDataPackage ...@@ -107,7 +120,9 @@ class FakeDataPackage
IDataPackage, IDataPackage,
IDataPackage2> { IDataPackage2> {
public: public:
FakeDataPackage() = default; FakeDataPackage(
FakeDataTransferManager::DataRequestedContent& data_requested_content)
: data_requested_content_(data_requested_content) {}
FakeDataPackage(const FakeDataPackage&) = delete; FakeDataPackage(const FakeDataPackage&) = delete;
FakeDataPackage& operator=(const FakeDataPackage&) = delete; FakeDataPackage& operator=(const FakeDataPackage&) = delete;
~FakeDataPackage() override { ~FakeDataPackage() override {
...@@ -137,7 +152,7 @@ class FakeDataPackage ...@@ -137,7 +152,7 @@ class FakeDataPackage
} }
IFACEMETHODIMP get_Properties(IDataPackagePropertySet** value) override { IFACEMETHODIMP get_Properties(IDataPackagePropertySet** value) override {
if (!properties_) if (!properties_)
properties_ = Make<FakeDataPackagePropertySet>(); properties_ = Make<FakeDataPackagePropertySet>(data_requested_content_);
*value = properties_.Get(); *value = properties_.Get();
properties_->AddRef(); properties_->AddRef();
return S_OK; return S_OK;
...@@ -174,15 +189,60 @@ class FakeDataPackage ...@@ -174,15 +189,60 @@ class FakeDataPackage
} }
IFACEMETHODIMP SetHtmlFormat(HSTRING value) override { return S_OK; } IFACEMETHODIMP SetHtmlFormat(HSTRING value) override { return S_OK; }
IFACEMETHODIMP SetRtf(HSTRING value) override { return S_OK; } IFACEMETHODIMP SetRtf(HSTRING value) override { return S_OK; }
IFACEMETHODIMP SetText(HSTRING value) override { return S_OK; } IFACEMETHODIMP SetText(HSTRING value) override {
base::win::ScopedHString wrapped_value(value);
data_requested_content_.text = wrapped_value.GetAsUTF8();
return S_OK;
}
IFACEMETHODIMP SetStorageItems(StorageItems* value, IFACEMETHODIMP SetStorageItems(StorageItems* value,
boolean readOnly) override { boolean readOnly) override {
return S_OK; EXPECT_TRUE(readOnly);
return SetStorageItemsReadOnly(value);
} }
IFACEMETHODIMP SetStorageItemsReadOnly(StorageItems* value) override { IFACEMETHODIMP SetStorageItemsReadOnly(StorageItems* value) override {
ComPtr<IIterator<IStorageItem*>> iterator;
HRESULT hr = value->First(&iterator);
if (FAILED(hr))
return hr;
boolean has_current;
hr = iterator->get_HasCurrent(&has_current);
if (FAILED(hr))
return hr;
while (has_current == TRUE) {
ComPtr<IStorageItem> storage_item;
hr = iterator->get_Current(&storage_item);
if (FAILED(hr))
return hr;
HSTRING name;
hr = storage_item->get_Name(&name);
base::win::ScopedHString wrapped_name(name);
if (FAILED(hr))
return hr;
ComPtr<IStorageFile> storage_file;
hr = storage_item.As(&storage_file);
if (FAILED(hr))
return hr;
FakeDataTransferManager::DataRequestedFile file;
file.name = wrapped_name.GetAsUTF8();
file.file = storage_file;
data_requested_content_.files.push_back(std::move(file));
hr = iterator->MoveNext(&has_current);
if (FAILED(hr))
return hr;
}
return S_OK;
}
IFACEMETHODIMP SetUri(IUriRuntimeClass* value) override {
HSTRING raw_uri;
value->get_RawUri(&raw_uri);
base::win::ScopedHString wrapped_value(raw_uri);
data_requested_content_.uri = wrapped_value.GetAsUTF8();
return S_OK; return S_OK;
} }
IFACEMETHODIMP SetUri(IUriRuntimeClass* value) override { return S_OK; }
// IDataPackage2 // IDataPackage2
IFACEMETHODIMP SetApplicationLink(IUriRuntimeClass* value) override { IFACEMETHODIMP SetApplicationLink(IUriRuntimeClass* value) override {
...@@ -191,23 +251,38 @@ class FakeDataPackage ...@@ -191,23 +251,38 @@ class FakeDataPackage
IFACEMETHODIMP SetWebLink(IUriRuntimeClass* value) override { return S_OK; } IFACEMETHODIMP SetWebLink(IUriRuntimeClass* value) override { return S_OK; }
private: private:
FakeDataTransferManager::DataRequestedContent& data_requested_content_;
ComPtr<IDataPackagePropertySet> properties_; ComPtr<IDataPackagePropertySet> properties_;
}; };
class FakeDataRequest class FakeDataRequest
: public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDataRequest> { : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDataRequest> {
public: public:
FakeDataRequest() = default; struct FakeDataRequestDeferral
: public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
IDataRequestDeferral> {
public:
explicit FakeDataRequestDeferral(FakeDataRequest* data_request)
: data_request_(data_request) {}
FakeDataRequestDeferral(const FakeDataRequestDeferral&) = delete;
FakeDataRequestDeferral& operator=(const FakeDataRequestDeferral&) = delete;
// IDataRequestDeferral
IFACEMETHODIMP Complete() override {
data_request_->RunPostDataRequestedCallbackImpl();
return S_OK;
}
private:
ComPtr<FakeDataRequest> data_request_;
};
FakeDataRequest(FakeDataTransferManager::PostDataRequestedCallback
post_data_requested_callback)
: post_data_requested_callback_(post_data_requested_callback) {}
FakeDataRequest(const FakeDataRequest&) = delete; FakeDataRequest(const FakeDataRequest&) = delete;
FakeDataRequest& operator=(const FakeDataRequest&) = delete; FakeDataRequest& operator=(const FakeDataRequest&) = delete;
~FakeDataRequest() override { ~FakeDataRequest() override = default;
// Though it is technically legal for consuming code to hold on to the
// DataPackage past the lifetime of the DataRequest, there is no good
// reason to do so, so any lingering references presumably point to a
// coding error.
if (data_package_)
EXPECT_EQ(0u, data_package_.Reset());
}
// IDataRequest // IDataRequest
IFACEMETHODIMP FailWithDisplayText(HSTRING value) override { IFACEMETHODIMP FailWithDisplayText(HSTRING value) override {
...@@ -216,7 +291,7 @@ class FakeDataRequest ...@@ -216,7 +291,7 @@ class FakeDataRequest
} }
IFACEMETHODIMP get_Data(IDataPackage** value) override { IFACEMETHODIMP get_Data(IDataPackage** value) override {
if (!data_package_) if (!data_package_)
data_package_ = Make<FakeDataPackage>(); data_package_ = Make<FakeDataPackage>(data_requested_content_);
*value = data_package_.Get(); *value = data_package_.Get();
data_package_->AddRef(); data_package_->AddRef();
return S_OK; return S_OK;
...@@ -227,46 +302,66 @@ class FakeDataRequest ...@@ -227,46 +302,66 @@ class FakeDataRequest
return E_NOTIMPL; return E_NOTIMPL;
} }
IFACEMETHODIMP GetDeferral(IDataRequestDeferral** value) override { IFACEMETHODIMP GetDeferral(IDataRequestDeferral** value) override {
NOTREACHED(); if (!data_request_deferral_)
return E_NOTIMPL; data_request_deferral_ = Make<FakeDataRequestDeferral>(this);
*value = data_request_deferral_.Get();
data_request_deferral_->AddRef();
return S_OK;
} }
IFACEMETHODIMP put_Data(IDataPackage* value) override { IFACEMETHODIMP put_Data(IDataPackage* value) override {
data_package_ = value; data_package_ = value;
return S_OK; return S_OK;
} }
void RunPostDataRequestedCallback() {
// If there is not a deferral trigger the callback right away, otherwise it
// will be triggered when the deferral is complete
if (!data_request_deferral_)
RunPostDataRequestedCallbackImpl();
}
private: private:
void RunPostDataRequestedCallbackImpl() {
post_data_requested_callback_.Run(data_requested_content_);
}
ComPtr<IDataPackage> data_package_; ComPtr<IDataPackage> data_package_;
ComPtr<FakeDataRequestDeferral> data_request_deferral_;
FakeDataTransferManager::DataRequestedContent data_requested_content_;
FakeDataTransferManager::PostDataRequestedCallback
post_data_requested_callback_;
}; };
class FakeDataRequestedEventArgs class FakeDataRequestedEventArgs
: public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
IDataRequestedEventArgs> { IDataRequestedEventArgs> {
public: public:
FakeDataRequestedEventArgs() = default; FakeDataRequestedEventArgs(FakeDataTransferManager::PostDataRequestedCallback
post_data_requested_callback)
: post_data_requested_callback_(post_data_requested_callback) {}
FakeDataRequestedEventArgs(const FakeDataRequestedEventArgs&) = delete; FakeDataRequestedEventArgs(const FakeDataRequestedEventArgs&) = delete;
FakeDataRequestedEventArgs& operator=(const FakeDataRequestedEventArgs&) = FakeDataRequestedEventArgs& operator=(const FakeDataRequestedEventArgs&) =
delete; delete;
~FakeDataRequestedEventArgs() override { ~FakeDataRequestedEventArgs() override = default;
// Though it is technically legal for consuming code to hold on to the
// DataRequest past the lifetime of the DataRequestedEventArgs, there is
// no good reason to do so, so any lingering references presumably point
// to a coding error.
if (data_request_)
EXPECT_EQ(0u, data_request_.Reset());
}
// IDataRequestedEventArgs // IDataRequestedEventArgs
IFACEMETHODIMP get_Request(IDataRequest** value) override { IFACEMETHODIMP get_Request(IDataRequest** value) override {
if (!data_request_) if (!data_request_)
data_request_ = Make<FakeDataRequest>(); data_request_ = Make<FakeDataRequest>(post_data_requested_callback_);
*value = data_request_.Get(); *value = data_request_.Get();
data_request_->AddRef(); data_request_->AddRef();
return S_OK; return S_OK;
} }
void RunPostDataRequestedCallback() {
if (data_request_)
data_request_->RunPostDataRequestedCallback();
}
private: private:
ComPtr<IDataRequest> data_request_; ComPtr<FakeDataRequest> data_request_;
FakeDataTransferManager::PostDataRequestedCallback
post_data_requested_callback_;
}; };
} // namespace } // namespace
...@@ -280,9 +375,20 @@ bool FakeDataTransferManager::IsSupportedEnvironment() { ...@@ -280,9 +375,20 @@ bool FakeDataTransferManager::IsSupportedEnvironment() {
return false; return false;
} }
FakeDataTransferManager::FakeDataTransferManager() = default; FakeDataTransferManager::FakeDataTransferManager() {
post_data_requested_callback_ = base::DoNothing();
}
FakeDataTransferManager::~FakeDataTransferManager() = default; FakeDataTransferManager::~FakeDataTransferManager() = default;
FakeDataTransferManager::DataRequestedFile::DataRequestedFile() = default;
FakeDataTransferManager::DataRequestedFile::DataRequestedFile(
FakeDataTransferManager::DataRequestedFile&&) = default;
FakeDataTransferManager::DataRequestedFile::~DataRequestedFile() = default;
FakeDataTransferManager::DataRequestedContent::DataRequestedContent() = default;
FakeDataTransferManager::DataRequestedContent::~DataRequestedContent() =
default;
IFACEMETHODIMP IFACEMETHODIMP
FakeDataTransferManager::add_DataRequested( FakeDataTransferManager::add_DataRequested(
DataRequestedEventHandler* event_handler, DataRequestedEventHandler* event_handler,
...@@ -334,13 +440,14 @@ base::OnceClosure FakeDataTransferManager::GetDataRequestedInvoker() { ...@@ -334,13 +440,14 @@ base::OnceClosure FakeDataTransferManager::GetDataRequestedInvoker() {
// Though multiple handlers may be registered for this event, only the // Though multiple handlers may be registered for this event, only the
// latest is invoked by the OS and then the event is considered handled. // latest is invoked by the OS and then the event is considered handled.
auto handler = data_requested_event_handlers_.back().event_handler_; auto handler = data_requested_event_handlers_.back().event_handler_;
ComPtr<IDataTransferManager> self = this; ComPtr<FakeDataTransferManager> self = this;
return base::BindOnce( return base::BindOnce(
[](ComPtr<IDataTransferManager> self, [](ComPtr<FakeDataTransferManager> self,
ComPtr<DataRequestedEventHandler> handler) { ComPtr<DataRequestedEventHandler> handler) {
ComPtr<IDataRequestedEventArgs> event_args = auto event_args = Make<FakeDataRequestedEventArgs>(
Make<FakeDataRequestedEventArgs>(); self->post_data_requested_callback_);
handler->Invoke(self.Get(), event_args.Get()); handler->Invoke(self.Get(), event_args.Get());
event_args->RunPostDataRequestedCallback();
}, },
self, handler); self, handler);
} }
...@@ -349,6 +456,11 @@ bool FakeDataTransferManager::HasDataRequestedListener() { ...@@ -349,6 +456,11 @@ bool FakeDataTransferManager::HasDataRequestedListener() {
return !data_requested_event_handlers_.empty(); return !data_requested_event_handlers_.empty();
} }
void FakeDataTransferManager::SetPostDataRequestedCallback(
PostDataRequestedCallback post_data_requested_callback) {
post_data_requested_callback_ = std::move(post_data_requested_callback);
}
FakeDataTransferManager::DataRequestedHandlerEntry:: FakeDataTransferManager::DataRequestedHandlerEntry::
DataRequestedHandlerEntry() = default; DataRequestedHandlerEntry() = default;
FakeDataTransferManager::DataRequestedHandlerEntry::DataRequestedHandlerEntry( FakeDataTransferManager::DataRequestedHandlerEntry::DataRequestedHandlerEntry(
......
...@@ -9,16 +9,45 @@ ...@@ -9,16 +9,45 @@
#include <wrl/implements.h> #include <wrl/implements.h>
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback.h"
namespace webshare { namespace webshare {
// Provides an implementation of IDataTransferManager for use in GTests. // Provides an implementation of IDataTransferManager for use in GTests.
class FakeDataTransferManager class __declspec(uuid("53CA4C00-6F19-40C1-A740-F66510E2DB40"))
FakeDataTransferManager
: public Microsoft::WRL::RuntimeClass< : public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>, Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager> { ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager> {
public: public:
// Represents a file surfaced to a DataRequested event
struct DataRequestedFile {
DataRequestedFile();
DataRequestedFile(const DataRequestedFile&) = delete;
DataRequestedFile& operator=(const DataRequestedFile&) = delete;
DataRequestedFile(DataRequestedFile&&);
~DataRequestedFile();
std::string name;
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFile> file;
};
// Represents the content surfaced to a DataRequested event
struct DataRequestedContent {
DataRequestedContent();
DataRequestedContent(const DataRequestedContent&) = delete;
DataRequestedContent& operator=(const DataRequestedContent&) = delete;
~DataRequestedContent();
std::string text;
std::string title;
std::string uri;
std::vector<DataRequestedFile> files;
};
using PostDataRequestedCallback =
base::RepeatingCallback<void(const DataRequestedContent&)>;
static bool IsSupportedEnvironment(); static bool IsSupportedEnvironment();
FakeDataTransferManager(); FakeDataTransferManager();
...@@ -49,6 +78,11 @@ class FakeDataTransferManager ...@@ -49,6 +78,11 @@ class FakeDataTransferManager
bool HasDataRequestedListener(); bool HasDataRequestedListener();
// Sets a callback that will be invoked after any DataRequested event is
// triggered and passed the content supplied by the DataRequested handler
void SetPostDataRequestedCallback(
PostDataRequestedCallback post_data_requested_callback);
private: private:
struct DataRequestedHandlerEntry { struct DataRequestedHandlerEntry {
DataRequestedHandlerEntry(); DataRequestedHandlerEntry();
...@@ -63,6 +97,7 @@ class FakeDataTransferManager ...@@ -63,6 +97,7 @@ class FakeDataTransferManager
std::vector<DataRequestedHandlerEntry> data_requested_event_handlers_; std::vector<DataRequestedHandlerEntry> data_requested_event_handlers_;
int64_t latest_token_value_ = 0; int64_t latest_token_value_ = 0;
PostDataRequestedCallback post_data_requested_callback_;
}; };
} // namespace webshare } // namespace webshare
......
...@@ -4,22 +4,63 @@ ...@@ -4,22 +4,63 @@
#include "chrome/browser/webshare/win/fake_data_transfer_manager.h" #include "chrome/browser/webshare/win/fake_data_transfer_manager.h"
#include <windows.storage.h>
#include <wrl/event.h> #include <wrl/event.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/win/core_winrt_util.h" #include "base/win/core_winrt_util.h"
#include "base/win/vector.h"
#include "chrome/browser/webshare/win/fake_storage_file_statics.h"
#include "chrome/browser/webshare/win/fake_uri_runtime_class_factory.h"
#include "testing/gtest/include/gtest/gtest-spi.h" #include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using ABI::Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs; using ABI::Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs;
using ABI::Windows::ApplicationModel::DataTransfer::DataTransferManager; using ABI::Windows::ApplicationModel::DataTransfer::DataTransferManager;
using ABI::Windows::ApplicationModel::DataTransfer::IDataPackage;
using ABI::Windows::ApplicationModel::DataTransfer::IDataPackagePropertySet;
using ABI::Windows::ApplicationModel::DataTransfer::IDataRequest;
using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestDeferral;
using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs; using ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs;
using ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager; using ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager;
using ABI::Windows::Foundation::IAsyncOperation;
using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
using ABI::Windows::Foundation::ITypedEventHandler; using ABI::Windows::Foundation::ITypedEventHandler;
using ABI::Windows::Foundation::IUriRuntimeClass;
using ABI::Windows::Storage::IStorageFile;
using ABI::Windows::Storage::IStorageItem;
using ABI::Windows::Storage::IStreamedFileDataRequestedHandler;
using ABI::Windows::Storage::StorageFile;
using ABI::Windows::Storage::Streams::IOutputStream;
using Microsoft::WRL::Callback; using Microsoft::WRL::Callback;
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
using Microsoft::WRL::Make;
namespace ABI {
namespace Windows {
namespace Foundation {
namespace Collections {
// Define template specializations for the types used. These uuids were randomly
// generated.
template <>
struct __declspec(uuid("CBE31E85-DEC8-4227-987F-9C63D6AA1A2E"))
IObservableVector<IStorageItem*> : IObservableVector_impl<IStorageItem*> {};
template <>
struct __declspec(uuid("30BE4864-5EE5-4111-916E-15126649F3C9"))
VectorChangedEventHandler<IStorageItem*>
: VectorChangedEventHandler_impl<IStorageItem*> {};
} // namespace Collections
} // namespace Foundation
} // namespace Windows
} // namespace ABI
namespace webshare { namespace webshare {
...@@ -215,4 +256,159 @@ TEST_F(FakeDataTransferManagerTest, OutOfOrderEventInvocation) { ...@@ -215,4 +256,159 @@ TEST_F(FakeDataTransferManagerTest, OutOfOrderEventInvocation) {
ASSERT_EQ(callback_3.invocation_count_, 1); ASSERT_EQ(callback_3.invocation_count_, 1);
} }
TEST_F(FakeDataTransferManagerTest, PostDataRequestedCallback) {
if (!IsSupportedEnvironment())
return;
base::test::SingleThreadTaskEnvironment task_environment;
// Create a StorageFile/Item to provide to the DataRequested event
ComPtr<IStorageFile> storage_file;
{
base::RunLoop run_loop;
auto file_name = base::win::ScopedHString::Create("MyTestFile.abc");
ComPtr<IAsyncOperation<StorageFile*>> create_operation;
auto storage_file_statics = Make<FakeStorageFileStatics>();
storage_file_statics->CreateStreamedFileAsync(
file_name.get(),
Callback<IStreamedFileDataRequestedHandler>([](IOutputStream* stream) {
ADD_FAILURE() << "DataRequestedHandler called for streamed file that "
"should never have been opened";
return S_OK;
}).Get(),
/*thumbnail*/ nullptr, &create_operation);
ASSERT_HRESULT_SUCCEEDED(create_operation->put_Completed(
Callback<IAsyncOperationCompletedHandler<StorageFile*>>(
[&run_loop, &storage_file](
IAsyncOperation<StorageFile*>* async_operation,
AsyncStatus async_status) {
EXPECT_EQ(async_status, AsyncStatus::Completed);
EXPECT_HRESULT_SUCCEEDED(
async_operation->GetResults(&storage_file));
run_loop.Quit();
return S_OK;
})
.Get()));
run_loop.Run();
}
ComPtr<IStorageItem> storage_item;
ASSERT_HRESULT_SUCCEEDED(storage_file.As(&storage_item));
// Set up a handler for the DataRequested event that provides a collection of
// content
auto callback = Callback<
ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs*>>(
[&storage_item](IDataTransferManager* data_transfer_manager,
IDataRequestedEventArgs* event_args) -> HRESULT {
ComPtr<IDataRequest> data_request;
EXPECT_HRESULT_SUCCEEDED(event_args->get_Request(&data_request));
ComPtr<IDataPackage> data_package;
EXPECT_HRESULT_SUCCEEDED(data_request->get_Data(&data_package));
ComPtr<IDataPackagePropertySet> data_prop_sets;
EXPECT_HRESULT_SUCCEEDED(data_package->get_Properties(&data_prop_sets));
auto title_h = base::win::ScopedHString::Create("my title");
EXPECT_HRESULT_SUCCEEDED(data_prop_sets->put_Title(title_h.get()));
auto text_h = base::win::ScopedHString::Create("my text");
EXPECT_HRESULT_SUCCEEDED(data_package->SetText(text_h.get()));
auto uri_factory = Make<FakeUriRuntimeClassFactory>();
auto url_h = base::win::ScopedHString::Create("https://my.url.com");
ComPtr<IUriRuntimeClass> uri;
EXPECT_HRESULT_SUCCEEDED(uri_factory->CreateUri(url_h.get(), &uri));
EXPECT_HRESULT_SUCCEEDED(data_package->SetUri(uri.Get()));
auto storage_items = Make<base::win::Vector<IStorageItem*>>();
storage_items->Append(storage_item.Get());
EXPECT_HRESULT_SUCCEEDED(data_package->SetStorageItems(
storage_items.Get(), true /*readonly*/));
return S_OK;
});
EventRegistrationToken token;
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->add_DataRequested(callback.Get(), &token));
// Set up a handler for the PostDataRequested event that validates all the
// expected data
bool post_data_requested_callback_invoked = false;
fake_data_transfer_manager_->SetPostDataRequestedCallback(
base::BindLambdaForTesting(
[&post_data_requested_callback_invoked,
&storage_file](const FakeDataTransferManager::DataRequestedContent&
data_requested_content) {
ASSERT_FALSE(post_data_requested_callback_invoked);
post_data_requested_callback_invoked = true;
ASSERT_EQ(data_requested_content.title, "my title");
ASSERT_EQ(data_requested_content.text, "my text");
ASSERT_EQ(data_requested_content.uri, "https://my.url.com");
ASSERT_EQ(data_requested_content.files.size(), 1u);
ASSERT_EQ(data_requested_content.files[0].name, "MyTestFile.abc");
ASSERT_EQ(data_requested_content.files[0].file, storage_file);
}));
// Run the flow
auto callback_invoker =
fake_data_transfer_manager_->GetDataRequestedInvoker();
ASSERT_FALSE(post_data_requested_callback_invoked);
std::move(callback_invoker).Run();
ASSERT_TRUE(post_data_requested_callback_invoked);
// Cleanup
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token));
}
TEST_F(FakeDataTransferManagerTest, PostDataRequestedCallback_Deferral) {
if (!IsSupportedEnvironment())
return;
// Set up a handler for the DataRequested event that requests a deferral
ComPtr<IDataRequestDeferral> data_request_deferral;
auto callback = Callback<
ITypedEventHandler<DataTransferManager*, DataRequestedEventArgs*>>(
[&data_request_deferral](IDataTransferManager* data_transfer_manager,
IDataRequestedEventArgs* event_args) -> HRESULT {
ComPtr<IDataRequest> data_request;
EXPECT_HRESULT_SUCCEEDED(event_args->get_Request(&data_request));
EXPECT_HRESULT_SUCCEEDED(
data_request->GetDeferral(&data_request_deferral));
return S_OK;
});
EventRegistrationToken token;
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->add_DataRequested(callback.Get(), &token));
// Set up a handler for the PostDataRequested event that records the event
bool post_data_requested_callback_invoked = false;
fake_data_transfer_manager_->SetPostDataRequestedCallback(
base::BindLambdaForTesting(
[&post_data_requested_callback_invoked](
const FakeDataTransferManager::DataRequestedContent&
data_requested_content) {
ASSERT_FALSE(post_data_requested_callback_invoked);
post_data_requested_callback_invoked = true;
}));
// Run the flow
auto callback_invoker =
fake_data_transfer_manager_->GetDataRequestedInvoker();
ASSERT_FALSE(post_data_requested_callback_invoked);
ASSERT_FALSE(data_request_deferral);
std::move(callback_invoker).Run();
ASSERT_FALSE(post_data_requested_callback_invoked);
ASSERT_TRUE(data_request_deferral);
ASSERT_HRESULT_SUCCEEDED(data_request_deferral->Complete());
ASSERT_TRUE(post_data_requested_callback_invoked);
// Cleanup
ASSERT_HRESULT_SUCCEEDED(
fake_data_transfer_manager_->remove_DataRequested(token));
}
} // namespace webshare } // namespace webshare
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