| // 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 "chrome/browser/webshare/win/fake_uri_runtime_class_factory.h" |
| |
| #include <string> |
| #include <tuple> |
| |
| #include "base/notreached.h" |
| #include "base/win/scoped_hstring.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| using ABI::Windows::Foundation::IUriRuntimeClass; |
| using ABI::Windows::Foundation::IWwwFormUrlDecoderRuntimeClass; |
| using Microsoft::WRL::Make; |
| using Microsoft::WRL::RuntimeClass; |
| using Microsoft::WRL::RuntimeClassFlags; |
| using Microsoft::WRL::WinRtClassicComMix; |
| |
| namespace webshare { |
| namespace { |
| |
| // Provides an implementation of IUriRuntimeClass for use in GTests. |
| // |
| // Note that implementations for all the functions except get_RawUri are |
| // intentionally omitted. Though they are safe APIs, they have many subtle |
| // differences from the behaviors of a GURL. To prevent inconsistencies and |
| // unexpected edge cases get_RawUri should be used to construct a GURL and its |
| // similar functionality leveraged, rather than relying on these functions. |
| class FakeUriRuntimeClass final |
| : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, |
| IUriRuntimeClass> { |
| public: |
| explicit FakeUriRuntimeClass(std::string raw_uri) : raw_uri_(raw_uri) {} |
| FakeUriRuntimeClass(const FakeUriRuntimeClass&) = delete; |
| FakeUriRuntimeClass& operator=(const FakeUriRuntimeClass&) = delete; |
| ~FakeUriRuntimeClass() final = default; |
| |
| // ABI::Windows::Foundation::IUriRuntimeClass: |
| IFACEMETHODIMP get_AbsoluteUri(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_DisplayUri(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Domain(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Extension(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Fragment(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Host(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Password(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Path(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Query(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_QueryParsed( |
| IWwwFormUrlDecoderRuntimeClass** www_form_url_decoder) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_RawUri(HSTRING* value) final { |
| auto copy = base::win::ScopedHString::Create(raw_uri_); |
| *value = copy.release(); |
| return S_OK; |
| } |
| IFACEMETHODIMP get_SchemeName(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_UserName(HSTRING* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Port(INT32* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP get_Suspicious(boolean* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP |
| Equals(IUriRuntimeClass* uri, boolean* value) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| IFACEMETHODIMP |
| CombineUri(HSTRING relative_uri, IUriRuntimeClass** instance) final { |
| NOTREACHED() << "get_RawUri should be the only function called on an " |
| "IUriRuntimeClass - see FakeUriRuntimeClass."; |
| return E_NOTIMPL; |
| } |
| |
| private: |
| std::string raw_uri_; |
| }; |
| |
| } // namespace |
| |
| FakeUriRuntimeClassFactory::FakeUriRuntimeClassFactory() = default; |
| FakeUriRuntimeClassFactory::~FakeUriRuntimeClassFactory() = default; |
| |
| IFACEMETHODIMP |
| FakeUriRuntimeClassFactory::CreateUri(HSTRING uri, |
| IUriRuntimeClass** instance) { |
| if (!uri) { |
| ADD_FAILURE() << "CreateUri called with null uri."; |
| return E_POINTER; |
| } |
| |
| // ScopedHString takes ownership of the HSTRING provided to it, but taking |
| // ownership is not an expected behavior when passing an HSTRING to a system |
| // API, so we use a temporary ScopedHString to make a copy we can safely own |
| // and release ownership of the original 'back' to the caller. |
| base::win::ScopedHString holder(uri); |
| auto uri_string = holder.GetAsUTF8(); |
| std::ignore = holder.release(); |
| |
| if (uri_string.empty()) { |
| ADD_FAILURE() << "CreateUri called with empty uri."; |
| return E_POINTER; |
| } |
| |
| auto url = GURL(uri_string); |
| if (!url.is_valid()) { |
| ADD_FAILURE() << "CreateUri called with invalid uri."; |
| return E_INVALIDARG; |
| } |
| |
| auto fake_uri_runtime_class = Make<FakeUriRuntimeClass>(uri_string); |
| HRESULT hr = fake_uri_runtime_class->QueryInterface(IID_PPV_ARGS(instance)); |
| if (FAILED(hr)) { |
| EXPECT_HRESULT_SUCCEEDED(hr); |
| return hr; |
| } |
| return S_OK; |
| } |
| |
| IFACEMETHODIMP FakeUriRuntimeClassFactory::CreateWithRelativeUri( |
| HSTRING base_uri, |
| HSTRING relative_uri, |
| IUriRuntimeClass** instance) { |
| NOTREACHED(); |
| return E_NOTIMPL; |
| } |
| |
| } // namespace webshare |