From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- widget/windows/tests/gtest/TestJumpListBuilder.cpp | 261 ++++++++++++++++++--- widget/windows/tests/gtest/TestWinDND.cpp | 2 +- 2 files changed, 229 insertions(+), 34 deletions(-) (limited to 'widget/windows/tests/gtest') diff --git a/widget/windows/tests/gtest/TestJumpListBuilder.cpp b/widget/windows/tests/gtest/TestJumpListBuilder.cpp index 5494c42d37..531e326465 100644 --- a/widget/windows/tests/gtest/TestJumpListBuilder.cpp +++ b/widget/windows/tests/gtest/TestJumpListBuilder.cpp @@ -275,14 +275,14 @@ class TestingJumpListBackend : public JumpListBackend { * @param {nsTArray&} aArray * The outparam for the array of generated * WindowsJumpListShortcutDescriptions. - * @param {nsTArray&} aJSValArray + * @param {JS::Handle} aJSArrayObj * The outparam for the array of JS::Value's representing the generated * WindowsJumpListShortcutDescriptions. */ void GenerateWindowsJumpListShortcutDescriptions( JSContext* aCx, uint32_t howMany, bool longDescription, nsTArray& aArray, - nsTArray& aJSValArray) { + JS::Handle aJSArrayObj) { for (uint32_t i = 0; i < howMany; ++i) { WindowsJumpListShortcutDescription desc; nsAutoString title(u"Test Task #"); @@ -321,7 +321,8 @@ void GenerateWindowsJumpListShortcutDescriptions( aArray.AppendElement(desc); JS::Rooted descJSValue(aCx); ASSERT_TRUE(ToJSValue(aCx, desc, &descJSValue)); - aJSValArray.AppendElement(std::move(descJSValue)); + + MOZ_ALWAYS_TRUE(JS_SetElement(aCx, aJSArrayObj, i, descJSValue)); } } @@ -393,15 +394,15 @@ TEST(JumpListBuilder, CheckForRemovals) EXPECT_CALL(*testBackend, BeginList) .WillOnce([](UINT* pcMinSlots, REFIID riid, void** ppv) { RefPtr collection; - DebugOnly hr = CoCreateInstance( + HRESULT hr = CoCreateInstance( CLSID_EnumerableObjectCollection, nullptr, CLSCTX_INPROC_SERVER, IID_IObjectCollection, getter_AddRefs(collection)); - MOZ_ASSERT(SUCCEEDED(hr)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); RefPtr link; hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, getter_AddRefs(link)); - MOZ_ASSERT(SUCCEEDED(hr)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); nsAutoString firstLinkHref(u"https://example.com"_ns); link->SetArguments(firstLinkHref.get()); @@ -421,7 +422,7 @@ TEST(JumpListBuilder, CheckForRemovals) RefPtr pArray; hr = collection->QueryInterface(IID_IObjectArray, getter_AddRefs(pArray)); - MOZ_ASSERT(SUCCEEDED(hr)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); *ppv = static_cast(pArray); (static_cast(*ppv))->AddRef(); @@ -477,6 +478,115 @@ TEST(JumpListBuilder, CheckForRemovals) ASSERT_TRUE(secondURLAutoString.EqualsLiteral("https://mozilla.org")); } +/** + * Tests calling CheckForRemovals and receiving a jump list entry with a very + * long URL doesn't result in JumpListBuilder truncating the URL before handing + * it back to the caller. Expects the following calls in order: + * + * - SetAppID + * - AbortList + * - BeginList + * - AbortList + */ +TEST(JumpListBuilder, CheckForRemovalsLongURL) +{ + RefPtr> testBackend = + new StrictMock(); + nsAutoString aumid(u"TestApplicationID"); + // We set up this expectation here because SetAppID will be called soon + // after construction of the JumpListBuilder via the background thread. + EXPECT_CALL(*testBackend, SetAppID(_)).Times(1); + + nsCOMPtr builder = + new JumpListBuilder(aumid, testBackend); + ASSERT_TRUE(builder); + + EXPECT_CALL(*testBackend, AbortList()).Times(2); + + constexpr static const nsLiteralString veryLongHref( + u"https://example.verylongurl.test/first/second/third/fourth/fifth/" + "sixth/seventh/eighth/ninth/tenth/eleventh/twelfth/thirteenth/" + "fourteenth/fifteenth-path-item/some/more/junk/after/that/more/more/" + "more/more/more/more/more/more/more/more/more/more/more/more/more/more/" + "more/more/more/more/more/more/more/more/more/more/more"_ns); + // This test ensures that URLs longer than MAX_PATH do not get truncated by + // JumpListBuilder or one of its utilities, so we must ensure that the static + // URL we just defined is actually longer than MAX_PATH. + static_assert(veryLongHref.Length() > MAX_PATH); + + // Let's prepare BeginList to return a one entry collection of IShellLinks. + // The IShellLink will have the URL be very long - over MAX_PATH characters. + EXPECT_CALL(*testBackend, BeginList) + .WillOnce([](UINT* pcMinSlots, REFIID riid, void** ppv) { + RefPtr collection; + HRESULT hr = CoCreateInstance( + CLSID_EnumerableObjectCollection, nullptr, CLSCTX_INPROC_SERVER, + IID_IObjectCollection, getter_AddRefs(collection)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); + + RefPtr link; + hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, + IID_IShellLinkW, getter_AddRefs(link)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); + + link->SetArguments(veryLongHref.get()); + + nsAutoString appPath(u"C:\\Tmp\\firefox.exe"_ns); + link->SetIconLocation(appPath.get(), 0); + + collection->AddObject(link); + + RefPtr pArray; + hr = collection->QueryInterface(IID_IObjectArray, + getter_AddRefs(pArray)); + MOZ_RELEASE_ASSERT(SUCCEEDED(hr)); + + *ppv = static_cast(pArray); + (static_cast(*ppv))->AddRef(); + + // This is the default value to return, according to + // https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-icustomdestinationlist-beginlist + *pcMinSlots = 10; + + return S_OK; + }); + + AutoJSAPI jsapi; + MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope())); + JSContext* cx = jsapi.cx(); + RefPtr promise; + nsresult rv = builder->CheckForRemovals(cx, getter_AddRefs(promise)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(promise); + + RefPtr resolver = new WaitForResolver(); + promise->AppendNativeHandler(resolver); + JS::Rooted result(cx); + resolver->SpinUntilResolvedWithResult(&result); + + ASSERT_TRUE(result.isObject()); + JS::Rooted obj(cx, result.toObjectOrNull()); + + bool isArray; + ASSERT_TRUE(JS::IsArrayObject(cx, obj, &isArray)); + ASSERT_TRUE(isArray); + + // We should expect to see 1 URL string returned in the array. + uint32_t length = 0; + ASSERT_TRUE(JS::GetArrayLength(cx, obj, &length)); + ASSERT_EQ(length, 1U); + + // The URL should match veryLongHref + JS::Rooted returnedURLValue(cx); + ASSERT_TRUE(JS_GetElement(cx, obj, 0, &returnedURLValue)); + JS::Rooted returnedURLValueJSString(cx, + returnedURLValue.toString()); + nsAutoJSString returnedURLValueAutoString; + ASSERT_TRUE(returnedURLValueAutoString.init(cx, returnedURLValueJSString)); + + ASSERT_TRUE(returnedURLValueAutoString.Equals(veryLongHref)); +} + /** * Tests calling PopulateJumpList with empty arguments, which should call the * following methods on the backend, in order: @@ -506,9 +616,13 @@ TEST(JumpListBuilder, PopulateJumpListEmpty) JSContext* cx = jsapi.cx(); RefPtr promise; - nsTArray taskDescJSVals; + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj)); + nsAutoString customTitle(u""); - nsTArray customDescJSVals; + + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); EXPECT_CALL(*testBackend, AbortList()).Times(1); EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); @@ -516,7 +630,7 @@ TEST(JumpListBuilder, PopulateJumpListEmpty) EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); nsresult rv = - builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals, + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, cx, getter_AddRefs(promise)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(promise); @@ -558,13 +672,15 @@ TEST(JumpListBuilder, PopulateJumpListOnlyTasks) JSContext* cx = jsapi.cx(); RefPtr promise; - nsTArray taskDescJSVals; + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj)); nsTArray taskDescs; GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs, - taskDescJSVals); + taskDescsObj); nsAutoString customTitle(u""); - nsTArray customDescJSVals; + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); EXPECT_CALL(*testBackend, AbortList()).Times(1); EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); @@ -575,7 +691,7 @@ TEST(JumpListBuilder, PopulateJumpListOnlyTasks) EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); nsresult rv = - builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals, + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, cx, getter_AddRefs(promise)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(promise); @@ -617,13 +733,17 @@ TEST(JumpListBuilder, PopulateJumpListOnlyCustomItems) JSContext* cx = jsapi.cx(); RefPtr promise; - nsTArray descs; - nsTArray customDescJSVals; - GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, descs, - customDescJSVals); + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx); + taskDescsJSVal.setObject(*taskDescsObj); nsAutoString customTitle(u"My custom title"); - nsTArray taskDescJSVals; + + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); + nsTArray descs; + GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, descs, + customDescsObj); EXPECT_CALL(*testBackend, AbortList()).Times(1); EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); @@ -636,7 +756,7 @@ TEST(JumpListBuilder, PopulateJumpListOnlyCustomItems) EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); nsresult rv = - builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals, + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, cx, getter_AddRefs(promise)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(promise); @@ -679,30 +799,102 @@ TEST(JumpListBuilder, PopulateJumpList) JSContext* cx = jsapi.cx(); RefPtr promise; + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj)); nsTArray taskDescs; - nsTArray taskDescJSVals; GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs, - taskDescJSVals); + taskDescsObj); + + nsAutoString customTitle(u"My custom title"); + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); nsTArray customDescs; - nsTArray customDescJSVals; GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, customDescs, - customDescJSVals); + customDescsObj); + + EXPECT_CALL(*testBackend, AbortList()).Times(1); + EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); + EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1); + + EXPECT_CALL(*testBackend, AppendCategory(LPCWSTREq(customTitle.get()), + ShellLinksEq(&customDescs))) + .Times(1); + EXPECT_CALL(*testBackend, CommitList()).Times(1); + EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); + + nsresult rv = + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, + cx, getter_AddRefs(promise)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(promise); + + RefPtr resolver = new WaitForResolver(); + promise->AppendNativeHandler(resolver); + JS::Rooted result(cx); + resolver->SpinUntilResolved(); +} + +/** + * Tests calling PopulateJumpList with tasks and custom items, but makes it so + * that AppendCategory returns E_ACCESSDENIED, which can occur if Windows is + * configured to not show recently opened items. The PopulateJumpList Promise + * should still resolve. + * + * - SetAppID + * - AbortList + * - BeginList + * - AddUserTasks + * - AppendCategory + * - CommitList + * + * This should result in a jump list with just built-in tasks. + */ +TEST(JumpListBuilder, PopulateJumpListNoOpenedItems) +{ + RefPtr> testBackend = + new StrictMock(); + nsAutoString aumid(u"TestApplicationID"); + // We set up this expectation here because SetAppID will be called soon + // after construction of the JumpListBuilder via the background thread. + EXPECT_CALL(*testBackend, SetAppID(_)).Times(1); + + nsCOMPtr builder = + new JumpListBuilder(aumid, testBackend); + ASSERT_TRUE(builder); + + AutoJSAPI jsapi; + MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope())); + JSContext* cx = jsapi.cx(); + RefPtr promise; + + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj)); + nsTArray taskDescs; + GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, taskDescs, + taskDescsObj); nsAutoString customTitle(u"My custom title"); + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); + nsTArray customDescs; + GenerateWindowsJumpListShortcutDescriptions(cx, 2, false, customDescs, + customDescsObj); + EXPECT_CALL(*testBackend, AbortList()).Times(1); EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1); EXPECT_CALL(*testBackend, AppendCategory(LPCWSTREq(customTitle.get()), ShellLinksEq(&customDescs))) - .Times(1); + .WillOnce([] { return E_ACCESSDENIED; }); + EXPECT_CALL(*testBackend, CommitList()).Times(1); EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); nsresult rv = - builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals, + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, cx, getter_AddRefs(promise)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(promise); @@ -780,15 +972,20 @@ TEST(JumpListBuilder, TruncateDescription) JSContext* cx = jsapi.cx(); RefPtr promise; + JS::Rooted taskDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted taskDescsJSVal(cx, JS::ObjectValue(*taskDescsObj)); nsTArray taskDescs; - nsTArray taskDescJSVals; GenerateWindowsJumpListShortcutDescriptions(cx, 2, true, taskDescs, - taskDescJSVals); + taskDescsObj); + nsAutoString customTitle(u"My custom title"); + + JS::Rooted customDescsObj(cx, JS::NewArrayObject(cx, 0)); + JS::Rooted customDescsJSVal(cx, JS::ObjectValue(*customDescsObj)); nsTArray customDescs; - nsTArray customDescJSVals; GenerateWindowsJumpListShortcutDescriptions(cx, 2, true, customDescs, - customDescJSVals); + customDescsObj); + // We expect the long descriptions to be truncated to 260 characters, so // we'll truncate the descriptions here ourselves. for (auto& taskDesc : taskDescs) { @@ -798,8 +995,6 @@ TEST(JumpListBuilder, TruncateDescription) customDesc.mDescription.SetLength(MAX_PATH - 1); } - nsAutoString customTitle(u"My custom title"); - EXPECT_CALL(*testBackend, AbortList()).Times(1); EXPECT_CALL(*testBackend, BeginList(_, _, _)).Times(1); EXPECT_CALL(*testBackend, AddUserTasks(ShellLinksEq(&taskDescs))).Times(1); @@ -811,7 +1006,7 @@ TEST(JumpListBuilder, TruncateDescription) EXPECT_CALL(*testBackend, DeleteList(_)).Times(0); nsresult rv = - builder->PopulateJumpList(taskDescJSVals, customTitle, customDescJSVals, + builder->PopulateJumpList(taskDescsJSVal, customTitle, customDescsJSVal, cx, getter_AddRefs(promise)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(promise); diff --git a/widget/windows/tests/gtest/TestWinDND.cpp b/widget/windows/tests/gtest/TestWinDND.cpp index fb7849fd79..9a4b8c3db1 100644 --- a/widget/windows/tests/gtest/TestWinDND.cpp +++ b/widget/windows/tests/gtest/TestWinDND.cpp @@ -693,7 +693,7 @@ nsCOMPtr GetTemporaryDirectory() { #define ENSURE(expr) NS_ENSURE_SUCCESS(expr, nullptr); ENSURE(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpdir))); - MOZ_ASSERT(tmpdir); + MOZ_RELEASE_ASSERT(tmpdir); ENSURE(tmpdir->AppendNative("TestWinDND"_ns)); ENSURE(tmpdir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0777)); -- cgit v1.2.3