1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/webshare/win/fake_uri_runtime_class_factory.h"
6
7 #include <string>
8
9 #include "base/macros.h"
10 #include "base/notreached.h"
11 #include "base/win/scoped_hstring.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "url/gurl.h"
14
15 using ABI::Windows::Foundation::IUriRuntimeClass;
16 using ABI::Windows::Foundation::IWwwFormUrlDecoderRuntimeClass;
17 using Microsoft::WRL::Make;
18 using Microsoft::WRL::RuntimeClass;
19 using Microsoft::WRL::RuntimeClassFlags;
20 using Microsoft::WRL::WinRtClassicComMix;
21
22 namespace webshare {
23 namespace {
24
25 // Provides an implementation of IUriRuntimeClass for use in GTests.
26 //
27 // Note that implementations for all the functions except get_RawUri are
28 // intentionally omitted. Though they are safe APIs, they have many subtle
29 // differences from the behaviors of a GURL. To prevent inconsistencies and
30 // unexpected edge cases get_RawUri should be used to construct a GURL and its
31 // similar functionality leveraged, rather than relying on these functions.
32 class FakeUriRuntimeClass final
33 : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
34 IUriRuntimeClass> {
35 public:
FakeUriRuntimeClass(std::string raw_uri)36 explicit FakeUriRuntimeClass(std::string raw_uri) : raw_uri_(raw_uri) {}
37 FakeUriRuntimeClass(const FakeUriRuntimeClass&) = delete;
38 FakeUriRuntimeClass& operator=(const FakeUriRuntimeClass&) = delete;
39 ~FakeUriRuntimeClass() final = default;
40
41 // ABI::Windows::Foundation::IUriRuntimeClass:
get_AbsoluteUri(HSTRING * value)42 IFACEMETHODIMP get_AbsoluteUri(HSTRING* value) final {
43 NOTREACHED() << "get_RawUri should be the only function called on an "
44 "IUriRuntimeClass - see FakeUriRuntimeClass.";
45 return E_NOTIMPL;
46 }
get_DisplayUri(HSTRING * value)47 IFACEMETHODIMP get_DisplayUri(HSTRING* value) final {
48 NOTREACHED() << "get_RawUri should be the only function called on an "
49 "IUriRuntimeClass - see FakeUriRuntimeClass.";
50 return E_NOTIMPL;
51 }
get_Domain(HSTRING * value)52 IFACEMETHODIMP get_Domain(HSTRING* value) final {
53 NOTREACHED() << "get_RawUri should be the only function called on an "
54 "IUriRuntimeClass - see FakeUriRuntimeClass.";
55 return E_NOTIMPL;
56 }
get_Extension(HSTRING * value)57 IFACEMETHODIMP get_Extension(HSTRING* value) final {
58 NOTREACHED() << "get_RawUri should be the only function called on an "
59 "IUriRuntimeClass - see FakeUriRuntimeClass.";
60 return E_NOTIMPL;
61 }
get_Fragment(HSTRING * value)62 IFACEMETHODIMP get_Fragment(HSTRING* value) final {
63 NOTREACHED() << "get_RawUri should be the only function called on an "
64 "IUriRuntimeClass - see FakeUriRuntimeClass.";
65 return E_NOTIMPL;
66 }
get_Host(HSTRING * value)67 IFACEMETHODIMP get_Host(HSTRING* value) final {
68 NOTREACHED() << "get_RawUri should be the only function called on an "
69 "IUriRuntimeClass - see FakeUriRuntimeClass.";
70 return E_NOTIMPL;
71 }
get_Password(HSTRING * value)72 IFACEMETHODIMP get_Password(HSTRING* value) final {
73 NOTREACHED() << "get_RawUri should be the only function called on an "
74 "IUriRuntimeClass - see FakeUriRuntimeClass.";
75 return E_NOTIMPL;
76 }
get_Path(HSTRING * value)77 IFACEMETHODIMP get_Path(HSTRING* value) final {
78 NOTREACHED() << "get_RawUri should be the only function called on an "
79 "IUriRuntimeClass - see FakeUriRuntimeClass.";
80 return E_NOTIMPL;
81 }
get_Query(HSTRING * value)82 IFACEMETHODIMP get_Query(HSTRING* value) final {
83 NOTREACHED() << "get_RawUri should be the only function called on an "
84 "IUriRuntimeClass - see FakeUriRuntimeClass.";
85 return E_NOTIMPL;
86 }
get_QueryParsed(IWwwFormUrlDecoderRuntimeClass ** www_form_url_decoder)87 IFACEMETHODIMP get_QueryParsed(
88 IWwwFormUrlDecoderRuntimeClass** www_form_url_decoder) final {
89 NOTREACHED() << "get_RawUri should be the only function called on an "
90 "IUriRuntimeClass - see FakeUriRuntimeClass.";
91 return E_NOTIMPL;
92 }
get_RawUri(HSTRING * value)93 IFACEMETHODIMP get_RawUri(HSTRING* value) final {
94 auto copy = base::win::ScopedHString::Create(raw_uri_);
95 *value = copy.release();
96 return S_OK;
97 }
get_SchemeName(HSTRING * value)98 IFACEMETHODIMP get_SchemeName(HSTRING* value) final {
99 NOTREACHED() << "get_RawUri should be the only function called on an "
100 "IUriRuntimeClass - see FakeUriRuntimeClass.";
101 return E_NOTIMPL;
102 }
get_UserName(HSTRING * value)103 IFACEMETHODIMP get_UserName(HSTRING* value) final {
104 NOTREACHED() << "get_RawUri should be the only function called on an "
105 "IUriRuntimeClass - see FakeUriRuntimeClass.";
106 return E_NOTIMPL;
107 }
get_Port(INT32 * value)108 IFACEMETHODIMP get_Port(INT32* value) final {
109 NOTREACHED() << "get_RawUri should be the only function called on an "
110 "IUriRuntimeClass - see FakeUriRuntimeClass.";
111 return E_NOTIMPL;
112 }
get_Suspicious(boolean * value)113 IFACEMETHODIMP get_Suspicious(boolean* value) final {
114 NOTREACHED() << "get_RawUri should be the only function called on an "
115 "IUriRuntimeClass - see FakeUriRuntimeClass.";
116 return E_NOTIMPL;
117 }
118 IFACEMETHODIMP
Equals(IUriRuntimeClass * uri,boolean * value)119 Equals(IUriRuntimeClass* uri, boolean* value) final {
120 NOTREACHED() << "get_RawUri should be the only function called on an "
121 "IUriRuntimeClass - see FakeUriRuntimeClass.";
122 return E_NOTIMPL;
123 }
124 IFACEMETHODIMP
CombineUri(HSTRING relative_uri,IUriRuntimeClass ** instance)125 CombineUri(HSTRING relative_uri, IUriRuntimeClass** instance) final {
126 NOTREACHED() << "get_RawUri should be the only function called on an "
127 "IUriRuntimeClass - see FakeUriRuntimeClass.";
128 return E_NOTIMPL;
129 }
130
131 private:
132 std::string raw_uri_;
133 };
134
135 } // namespace
136
137 FakeUriRuntimeClassFactory::FakeUriRuntimeClassFactory() = default;
138 FakeUriRuntimeClassFactory::~FakeUriRuntimeClassFactory() = default;
139
140 IFACEMETHODIMP
CreateUri(HSTRING uri,IUriRuntimeClass ** instance)141 FakeUriRuntimeClassFactory::CreateUri(HSTRING uri,
142 IUriRuntimeClass** instance) {
143 if (!uri) {
144 ADD_FAILURE() << "CreateUri called with null uri.";
145 return E_POINTER;
146 }
147
148 // ScopedHString takes ownership of the HSTRING provided to it, but taking
149 // ownership is not an expected behavior when passing an HSTRING to a system
150 // API, so we use a temporary ScopedHString to make a copy we can safely own
151 // and release ownership of the original 'back' to the caller.
152 base::win::ScopedHString holder(uri);
153 auto uri_string = holder.GetAsUTF8();
154 ignore_result(holder.release());
155
156 if (uri_string.empty()) {
157 ADD_FAILURE() << "CreateUri called with empty uri.";
158 return E_POINTER;
159 }
160
161 auto url = GURL(uri_string);
162 if (!url.is_valid()) {
163 ADD_FAILURE() << "CreateUri called with invalid uri.";
164 return E_INVALIDARG;
165 }
166
167 auto fake_uri_runtime_class = Make<FakeUriRuntimeClass>(uri_string);
168 HRESULT hr = fake_uri_runtime_class->QueryInterface(IID_PPV_ARGS(instance));
169 if (FAILED(hr)) {
170 EXPECT_HRESULT_SUCCEEDED(hr);
171 return hr;
172 }
173 return S_OK;
174 }
175
CreateWithRelativeUri(HSTRING base_uri,HSTRING relative_uri,IUriRuntimeClass ** instance)176 IFACEMETHODIMP FakeUriRuntimeClassFactory::CreateWithRelativeUri(
177 HSTRING base_uri,
178 HSTRING relative_uri,
179 IUriRuntimeClass** instance) {
180 NOTREACHED();
181 return E_NOTIMPL;
182 }
183
184 } // namespace webshare
185