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