1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
7 #define MOZ_USE_LAUNCHER_ERROR
10 #include "mozilla/UrlmonHeaderOnlyUtils.h"
11 #include "TestUrisToValidate.h"
15 using namespace mozilla
;
17 static LauncherResult
<_bstr_t
> ShellValidateUri(const wchar_t* aUri
) {
18 LauncherResult
<UniqueAbsolutePidl
> pidlResult
= ShellParseDisplayName(aUri
);
19 if (pidlResult
.isErr()) {
20 return pidlResult
.propagateErr();
22 UniqueAbsolutePidl pidl
= pidlResult
.unwrap();
24 // |pidl| is an absolute path. IShellFolder::GetDisplayNameOf requires a
25 // valid child ID, so the first thing we need to resolve is the IShellFolder
26 // for |pidl|'s parent, as well as the childId that represents |pidl|.
27 // Fortunately SHBindToParent does exactly that!
28 PCUITEMID_CHILD childId
= nullptr;
29 RefPtr
<IShellFolder
> parentFolder
;
30 HRESULT hr
= SHBindToParent(pidl
.get(), IID_IShellFolder
,
31 getter_AddRefs(parentFolder
), &childId
);
33 return LAUNCHER_ERROR_FROM_HRESULT(hr
);
36 // Now we retrieve the display name of |childId|, telling the shell that we
37 // plan to have the string parsed.
39 hr
= parentFolder
->GetDisplayNameOf(childId
, SHGDN_FORPARSING
, &strret
);
41 return LAUNCHER_ERROR_FROM_HRESULT(hr
);
44 // StrRetToBSTR automatically takes care of freeing any dynamically
45 // allocated memory in |strret|.
47 hr
= StrRetToBSTR(&strret
, nullptr, bstrUri
.GetAddress());
49 return LAUNCHER_ERROR_FROM_HRESULT(hr
);
55 static LauncherResult
<_bstr_t
> GetFragment(const wchar_t* aUri
) {
56 constexpr DWORD flags
=
57 Uri_CREATE_NO_DECODE_EXTRA_INFO
| Uri_CREATE_CANONICALIZE
|
58 Uri_CREATE_CRACK_UNKNOWN_SCHEMES
| Uri_CREATE_PRE_PROCESS_HTML_URI
|
59 Uri_CREATE_IE_SETTINGS
;
61 HRESULT hr
= CreateUri(aUri
, flags
, 0, getter_AddRefs(uri
));
63 return LAUNCHER_ERROR_FROM_HRESULT(hr
);
67 hr
= uri
->GetFragment(bstrFragment
.GetAddress());
69 return LAUNCHER_ERROR_FROM_HRESULT(hr
);
74 static bool RunSingleTest(const wchar_t* aUri
) {
75 LauncherResult
<_bstr_t
> uriOld
= ShellValidateUri(aUri
),
76 uriNew
= UrlmonValidateUri(aUri
);
77 if (uriOld
.isErr() != uriNew
.isErr()) {
78 printf("TEST-FAILED | UriValidation | Validation result mismatch on %S\n",
84 if (uriOld
.unwrapErr().mError
!= uriNew
.unwrapErr().mError
) {
85 printf("TEST-FAILED | UriValidation | Error code mismatch on %S\n", aUri
);
91 LauncherResult
<_bstr_t
> bstrFragment
= GetFragment(aUri
);
92 if (bstrFragment
.isErr()) {
93 printf("TEST-FAILED | UriValidation | Failed to get a fragment from %S\n",
98 // We validate a uri with two logics: the current one UrlmonValidateUri and
99 // the older one ShellValidateUri, to make sure the same validation result.
100 // We introduced UrlmonValidateUri because ShellValidateUri drops a fragment
101 // in a uri due to the design of Windows. To bypass the fragment issue, we
102 // extract a fragment and appends it into the validated string, and compare.
103 _bstr_t bstrUriOldCorrected
= uriOld
.unwrap() + bstrFragment
.unwrap();
104 const _bstr_t
& bstrUriNew
= uriNew
.unwrap();
105 if (bstrUriOldCorrected
!= bstrUriNew
) {
106 printf("TEST-FAILED | UriValidation | %S %S %S\n", aUri
,
107 static_cast<const wchar_t*>(bstrUriOldCorrected
),
108 static_cast<const wchar_t*>(bstrUriNew
));
115 int wmain(int argc
, wchar_t* argv
[]) {
116 HRESULT hr
= CoInitialize(nullptr);
124 isOk
= RunSingleTest(argv
[1]);
126 for (const wchar_t*& testUri
: kTestUris
) {
127 if (!RunSingleTest(testUri
)) {