Commit 8f953478 authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[base/win] add winrt helpers for foundation and collections types

Provides convenience templates that dispatch to correct type in
winrt system, as well as helpers for copy, equality and comparison.

BUG=728870
TBR=gab@chromium.org, robliao@chromium.org

Change-Id: I3d4f19471778d5a25c13a30ea9203add0aadb4c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1695407
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#679932}
parent 4f2d7da9
...@@ -1125,6 +1125,7 @@ jumbo_component("base") { ...@@ -1125,6 +1125,7 @@ jumbo_component("base") {
"win/windows_version.cc", "win/windows_version.cc",
"win/windows_version.h", "win/windows_version.h",
"win/windowsx_shim.h", "win/windowsx_shim.h",
"win/winrt_foundation_helpers.h",
"win/winrt_storage_util.cc", "win/winrt_storage_util.cc",
"win/winrt_storage_util.h", "win/winrt_storage_util.h",
"win/wmi.cc", "win/wmi.cc",
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "base/win/winrt_foundation_helpers.h"
namespace base { namespace base {
namespace win { namespace win {
...@@ -70,70 +71,20 @@ namespace win { ...@@ -70,70 +71,20 @@ namespace win {
namespace internal { namespace internal {
// Template tricks needed to dispatch to the correct implementation below. // Template tricks needed to dispatch to the correct implementation below.
// // See base/win/winrt_foundation_helpers.h for explanation.
// For all types which are neither InterfaceGroups nor RuntimeClasses, the
// following three typedefs are synonyms for a single C++ type. But for
// InterfaceGroups and RuntimeClasses, they are different types:
// LogicalT: The C++ Type for the InterfaceGroup or RuntimeClass, when
// used as a template parameter. Eg "RCFoo*"
// AbiT: The C++ type for the default interface used to represent the
// InterfaceGroup or RuntimeClass when passed as a method parameter.
// Eg "IFoo*"
// ComplexT: An instantiation of the Internal "AggregateType" template that
// combines LogicalT with AbiT. Eg "AggregateType<RCFoo*,IFoo*>"
//
// windows.foundation.collections.h defines the following template and
// semantics in Windows::Foundation::Internal:
//
// template <class LogicalType, class AbiType>
// struct AggregateType;
//
// LogicalType - the Windows Runtime type (eg, runtime class, inteface group,
// etc) being provided as an argument to an _impl template, when
// that type cannot be represented at the ABI.
// AbiType - the type used for marshalling, ie "at the ABI", for the
// logical type.
template <typename T>
using ComplexT =
typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
template <typename T> template <typename T>
using AbiT = using Complex =
typename ABI::Windows::Foundation::Internal::GetAbiType<ComplexT<T>>::type; typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
template <typename T>
using LogicalT = typename ABI::Windows::Foundation::Internal::GetLogicalType<
ComplexT<T>>::type;
template <typename T>
using InterfaceT = std::remove_pointer_t<AbiT<T>>;
// Compile time switch to decide what container to use for the async results for
// |T|. Depends on whether the underlying Abi type is a pointer to IUnknown or
// not. It queries the internals of Windows::Foundation to obtain this
// information.
template <typename T>
using ResultT =
std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
AbiT<T>>;
template <typename T> template <typename T>
using StorageT = using Abi = AbiType<Complex<T>>;
std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
base::Optional<AbiT<T>>>;
template <typename T> template <typename T>
HRESULT CopyStorage(const Microsoft::WRL::ComPtr<T>& storage, T** results) { using OptionalStorageT = OptionalStorageType<Complex<T>>;
return storage.CopyTo(results);
}
template <typename T> template <typename T>
HRESULT CopyStorage(const base::Optional<T>& storage, T* results) { using StorageT = StorageType<Complex<T>>;
*results = *storage;
return S_OK;
}
} // namespace internal } // namespace internal
...@@ -144,10 +95,11 @@ class AsyncOperation ...@@ -144,10 +95,11 @@ class AsyncOperation
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ABI::Windows::Foundation::IAsyncOperation<T>> { ABI::Windows::Foundation::IAsyncOperation<T>> {
public: public:
using AbiT = internal::Abi<T>;
using OptionalStorageT = internal::OptionalStorageT<T>;
using StorageT = internal::StorageT<T>; using StorageT = internal::StorageT<T>;
using ResultT = internal::ResultT<T>;
using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>; using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
using ResultCallback = base::OnceCallback<void(ResultT)>; using ResultCallback = base::OnceCallback<void(StorageT)>;
AsyncOperation() : weak_factory_(this) { AsyncOperation() : weak_factory_(this) {
// Note: This can't be done in the constructor initializer list. This is // Note: This can't be done in the constructor initializer list. This is
...@@ -169,9 +121,9 @@ class AsyncOperation ...@@ -169,9 +121,9 @@ class AsyncOperation
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return handler_.CopyTo(handler); return handler_.CopyTo(handler);
} }
IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override { IFACEMETHODIMP GetResults(AbiT* results) override {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return storage_ ? internal::CopyStorage(storage_, results) : E_PENDING; return results_ ? internal::CopyTo(results_, results) : E_PENDING;
} }
ResultCallback callback() { ResultCallback callback() {
...@@ -185,16 +137,16 @@ class AsyncOperation ...@@ -185,16 +137,16 @@ class AsyncOperation
handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed); handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
} }
void OnResult(ResultT result) { void OnResult(StorageT result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!storage_); DCHECK(!results_);
storage_ = std::move(result); results_ = std::move(result);
InvokeCompletedHandler(); InvokeCompletedHandler();
} }
ResultCallback callback_; ResultCallback callback_;
Microsoft::WRL::ComPtr<Handler> handler_; Microsoft::WRL::ComPtr<Handler> handler_;
StorageT storage_; OptionalStorageT results_;
THREAD_CHECKER(thread_checker_); THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<AsyncOperation> weak_factory_; base::WeakPtrFactory<AsyncOperation> weak_factory_;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/win/winrt_foundation_helpers.h"
namespace base { namespace base {
namespace win { namespace win {
...@@ -26,17 +27,21 @@ class Vector; ...@@ -26,17 +27,21 @@ class Vector;
namespace internal { namespace internal {
// Template tricks needed to dispatch to the correct implementation.
// See base/win/winrt_foundation_helpers.h for explanation.
template <typename T> template <typename T>
using Complex = using Complex =
typename ABI::Windows::Foundation::Collections::IVector<T>::T_complex; typename ABI::Windows::Foundation::Collections::IVector<T>::T_complex;
template <typename T> template <typename T>
using Logical = typename ABI::Windows::Foundation::Internal::GetLogicalType< using Logical = LogicalType<Complex<T>>;
Complex<T>>::type;
template <typename T>
using Abi = AbiType<Complex<T>>;
template <typename T> template <typename T>
using Abi = using Storage = StorageType<Complex<T>>;
typename ABI::Windows::Foundation::Internal::GetAbiType<Complex<T>>::type;
template <typename T> template <typename T>
class VectorIterator class VectorIterator
...@@ -177,45 +182,6 @@ class VectorView ...@@ -177,45 +182,6 @@ class VectorView
EventRegistrationToken vector_changed_token_; EventRegistrationToken vector_changed_token_;
}; };
template <typename T>
HRESULT CopyTo(const T& value, T* ptr) {
*ptr = value;
return S_OK;
}
template <typename T>
HRESULT CopyTo(const Microsoft::WRL::ComPtr<T>& com_ptr, T** ptr) {
return com_ptr.CopyTo(ptr);
}
template <typename T>
HRESULT CopyN(typename std::vector<T>::const_iterator first,
unsigned count,
T* result) {
std::copy_n(first, count, result);
return S_OK;
}
template <typename T>
HRESULT CopyN(
typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,
unsigned count,
T** result) {
for (unsigned i = 0; i < count; ++i)
CopyTo(*first++, result++);
return S_OK;
}
template <typename T>
bool IsEqual(const T& lhs, const T& rhs) {
return lhs == rhs;
}
template <typename T>
bool IsEqual(const Microsoft::WRL::ComPtr<T>& com_ptr, const T* ptr) {
return com_ptr.Get() == ptr;
}
} // namespace internal } // namespace internal
// This file provides an implementation of Windows::Foundation::IVector. It // This file provides an implementation of Windows::Foundation::IVector. It
...@@ -238,24 +204,9 @@ class Vector ...@@ -238,24 +204,9 @@ class Vector
ABI::Windows::Foundation::Collections::IIterable< ABI::Windows::Foundation::Collections::IIterable<
internal::Logical<T>>> { internal::Logical<T>>> {
public: public:
// windows.foundation.collections.h defines the following template and
// semantics in Windows::Foundation::Internal:
//
// template <class LogicalType, class AbiType>
// struct AggregateType;
//
// LogicalType - the Windows Runtime type (eg, runtime class, interface
// group, etc) being provided as an argument to an _impl
// template, when that type cannot be represented at the ABI.
// AbiType - the type used for marshalling, ie "at the ABI", for the
// logical type.
using LogicalT = internal::Logical<T>; using LogicalT = internal::Logical<T>;
using AbiT = internal::Abi<T>; using AbiT = internal::Abi<T>;
using StorageT = internal::Storage<T>;
using StorageT =
std::conditional_t<std::is_convertible<AbiT, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT>>,
AbiT>;
Vector() = default; Vector() = default;
explicit Vector(const std::vector<StorageT>& vector) : vector_(vector) {} explicit Vector(const std::vector<StorageT>& vector) : vector_(vector) {}
......
// 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 BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
#define BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
#include <windows.foundation.h>
#include <wrl/client.h>
#include <vector>
#include "base/optional.h"
#include "base/win/hstring_compare.h"
// This file provides helpers for WinRT types.
namespace base {
namespace win {
namespace internal {
// Template tricks needed to dispatch to the correct implementation.
//
// For all types which are neither InterfaceGroups nor RuntimeClasses, the
// following three typedefs are synonyms for a single C++ type. But for
// InterfaceGroups and RuntimeClasses, they are different types:
// LogicalT: The C++ Type for the InterfaceGroup or RuntimeClass, when
// used as a template parameter. Eg "RCFoo*"
// AbiT: The C++ type for the default interface used to represent the
// InterfaceGroup or RuntimeClass when passed as a method parameter.
// Eg "IFoo*"
// ComplexT: An instantiation of the Internal "AggregateType" template that
// combines LogicalT with AbiT. Eg "AggregateType<RCFoo*,IFoo*>".
// ComplexT is tightly coupled to the interface being implemented,
// hence defined in headers which include this file.
// For instance base/win/async_operation.h or
// base/win/collection_helpers.h
//
// windows.foundation.collections.h defines the following template and
// semantics in Windows::Foundation::Internal:
//
// template <class LogicalType, class AbiType>
// struct AggregateType;
//
// LogicalType - the Windows Runtime type (eg, runtime class, interface group,
// etc) being provided as an argument to an _impl template, when
// that type cannot be represented at the ABI.
// AbiType - the type used for marshalling, ie "at the ABI", for the
// logical type.
template <typename TComplex>
using AbiType =
typename ABI::Windows::Foundation::Internal::GetAbiType<TComplex>::type;
template <typename TComplex>
using LogicalType =
typename ABI::Windows::Foundation::Internal::GetLogicalType<TComplex>::type;
// Compile time switch to decide what container to use for |TComplex|.
// Depends on whether the underlying Abi type is a pointer to IUnknown or not.
// It queries the internals of Windows::Foundation to obtain this information.
template <typename TComplex>
using StorageType = std::conditional_t<
std::is_convertible<AbiType<TComplex>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
AbiType<TComplex>>;
// Similar to StorageType, but returns a base::Optional in case underlying Abi
// type is not a pointer to IUnknown.
template <typename TComplex>
using OptionalStorageType = std::conditional_t<
std::is_convertible<AbiType<TComplex>, IUnknown*>::value,
Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
base::Optional<AbiType<TComplex>>>;
template <typename T>
HRESULT CopyTo(const T& value, T* ptr) {
*ptr = value;
return S_OK;
}
template <typename T>
HRESULT CopyTo(const Microsoft::WRL::ComPtr<T>& value, T** ptr) {
return value.CopyTo(ptr);
}
template <typename T>
HRESULT CopyTo(const base::Optional<T>& value, T* ptr) {
*ptr = *value;
return S_OK;
}
template <typename T>
HRESULT CopyN(typename std::vector<T>::const_iterator first,
unsigned count,
T* result) {
std::copy_n(first, count, result);
return S_OK;
}
template <typename T>
HRESULT CopyN(
typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,
unsigned count,
T** result) {
for (unsigned i = 0; i < count; ++i)
CopyTo(*first++, result++);
return S_OK;
}
inline bool IsEqual(const HSTRING& lhs, const HSTRING& rhs) {
INT32 result;
HRESULT hr = HStringCompare(lhs, rhs, &result);
DCHECK(SUCCEEDED(hr));
return result == 0;
}
template <typename T>
bool IsEqual(const T& lhs, const T& rhs) {
return lhs == rhs;
}
template <typename T>
bool IsEqual(const Microsoft::WRL::ComPtr<T>& com_ptr, const T* ptr) {
return com_ptr.Get() == ptr;
}
struct Less {
bool operator()(const HSTRING& lhs, const HSTRING& rhs) const {
INT32 result;
HRESULT hr = HStringCompare(lhs, rhs, &result);
DCHECK(SUCCEEDED(hr));
return result < 0;
}
template <typename T>
bool operator()(const Microsoft::WRL::ComPtr<T>& com_ptr,
const T* ptr) const {
return com_ptr.Get() < ptr;
}
template <typename T>
constexpr bool operator()(const T& lhs, const T& rhs) const {
return lhs < rhs;
}
};
} // namespace internal
} // namespace win
} // namespace base
#endif // BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
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