summaryrefslogtreecommitdiffstats
path: root/widget/windows/tests/TestUriValidation.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--widget/windows/tests/TestUriValidation.cpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/widget/windows/tests/TestUriValidation.cpp b/widget/windows/tests/TestUriValidation.cpp
new file mode 100644
index 0000000000..d8a0ca09ce
--- /dev/null
+++ b/widget/windows/tests/TestUriValidation.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#define MOZ_USE_LAUNCHER_ERROR
+
+#define UNICODE
+#include "mozilla/UrlmonHeaderOnlyUtils.h"
+#include "TestUrisToValidate.h"
+
+#include <urlmon.h>
+
+using namespace mozilla;
+
+static LauncherResult<_bstr_t> ShellValidateUri(const wchar_t* aUri) {
+ LauncherResult<UniqueAbsolutePidl> pidlResult = ShellParseDisplayName(aUri);
+ if (pidlResult.isErr()) {
+ return pidlResult.propagateErr();
+ }
+ UniqueAbsolutePidl pidl = pidlResult.unwrap();
+
+ // |pidl| is an absolute path. IShellFolder::GetDisplayNameOf requires a
+ // valid child ID, so the first thing we need to resolve is the IShellFolder
+ // for |pidl|'s parent, as well as the childId that represents |pidl|.
+ // Fortunately SHBindToParent does exactly that!
+ PCUITEMID_CHILD childId = nullptr;
+ RefPtr<IShellFolder> parentFolder;
+ HRESULT hr = SHBindToParent(pidl.get(), IID_IShellFolder,
+ getter_AddRefs(parentFolder), &childId);
+ if (FAILED(hr)) {
+ return LAUNCHER_ERROR_FROM_HRESULT(hr);
+ }
+
+ // Now we retrieve the display name of |childId|, telling the shell that we
+ // plan to have the string parsed.
+ STRRET strret;
+ hr = parentFolder->GetDisplayNameOf(childId, SHGDN_FORPARSING, &strret);
+ if (FAILED(hr)) {
+ return LAUNCHER_ERROR_FROM_HRESULT(hr);
+ }
+
+ // StrRetToBSTR automatically takes care of freeing any dynamically
+ // allocated memory in |strret|.
+ _bstr_t bstrUri;
+ hr = StrRetToBSTR(&strret, nullptr, bstrUri.GetAddress());
+ if (FAILED(hr)) {
+ return LAUNCHER_ERROR_FROM_HRESULT(hr);
+ }
+
+ return bstrUri;
+}
+
+static LauncherResult<_bstr_t> GetFragment(const wchar_t* aUri) {
+ constexpr DWORD flags =
+ Uri_CREATE_NO_DECODE_EXTRA_INFO | Uri_CREATE_CANONICALIZE |
+ Uri_CREATE_CRACK_UNKNOWN_SCHEMES | Uri_CREATE_PRE_PROCESS_HTML_URI |
+ Uri_CREATE_IE_SETTINGS;
+ RefPtr<IUri> uri;
+ HRESULT hr = CreateUri(aUri, flags, 0, getter_AddRefs(uri));
+ if (FAILED(hr)) {
+ return LAUNCHER_ERROR_FROM_HRESULT(hr);
+ }
+
+ _bstr_t bstrFragment;
+ hr = uri->GetFragment(bstrFragment.GetAddress());
+ if (FAILED(hr)) {
+ return LAUNCHER_ERROR_FROM_HRESULT(hr);
+ }
+ return bstrFragment;
+}
+
+static bool RunSingleTest(const wchar_t* aUri) {
+ LauncherResult<_bstr_t> uriOld = ShellValidateUri(aUri),
+ uriNew = UrlmonValidateUri(aUri);
+ if (uriOld.isErr() != uriNew.isErr()) {
+ printf("TEST-FAILED | UriValidation | Validation result mismatch on %S\n",
+ aUri);
+ return false;
+ }
+
+ if (uriOld.isErr()) {
+ if (uriOld.unwrapErr().mError != uriNew.unwrapErr().mError) {
+ printf("TEST-FAILED | UriValidation | Error code mismatch on %S\n", aUri);
+ return false;
+ }
+ return true;
+ }
+
+ LauncherResult<_bstr_t> bstrFragment = GetFragment(aUri);
+ if (bstrFragment.isErr()) {
+ printf("TEST-FAILED | UriValidation | Failed to get a fragment from %S\n",
+ aUri);
+ return false;
+ }
+
+ // We validate a uri with two logics: the current one UrlmonValidateUri and
+ // the older one ShellValidateUri, to make sure the same validation result.
+ // We introduced UrlmonValidateUri because ShellValidateUri drops a fragment
+ // in a uri due to the design of Windows. To bypass the fragment issue, we
+ // extract a fragment and appends it into the validated string, and compare.
+ _bstr_t bstrUriOldCorrected = uriOld.unwrap() + bstrFragment.unwrap();
+ const _bstr_t& bstrUriNew = uriNew.unwrap();
+ if (bstrUriOldCorrected != bstrUriNew) {
+ printf("TEST-FAILED | UriValidation | %S %S %S\n", aUri,
+ static_cast<const wchar_t*>(bstrUriOldCorrected),
+ static_cast<const wchar_t*>(bstrUriNew));
+ return false;
+ }
+
+ return true;
+}
+
+int wmain(int argc, wchar_t* argv[]) {
+ HRESULT hr = CoInitialize(nullptr);
+ if (FAILED(hr)) {
+ return 1;
+ }
+
+ bool isOk = true;
+
+ if (argc == 2) {
+ isOk = RunSingleTest(argv[1]);
+ } else {
+ for (const wchar_t*& testUri : kTestUris) {
+ if (!RunSingleTest(testUri)) {
+ isOk = false;
+ }
+ }
+ }
+
+ CoUninitialize();
+ return isOk ? 0 : 1;
+}