From 3201996fbadd40bf19dd6d0c4068b1ee304a02cb Mon Sep 17 00:00:00 2001 From: "shravanrn@gmail.com" Date: Fri, 20 Dec 2019 18:31:27 +0000 Subject: [PATCH 01/83] Bug 1575985 part 1 - Preload RLBox dynamic library before content sandbox to allow subsequent loads r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D45941 --HG-- extra : moz-landing-system : lando --- dom/ipc/ContentChild.cpp | 6 ++++ gfx/thebes/gfxFontEntry.cpp | 9 ++++- ipc/glue/LibrarySandboxPreload.cpp | 57 ++++++++++++++++++++++++++++++ ipc/glue/LibrarySandboxPreload.h | 17 +++++++++ ipc/glue/moz.build | 2 ++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 ipc/glue/LibrarySandboxPreload.cpp create mode 100644 ipc/glue/LibrarySandboxPreload.h diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index b8e5d3659ab7..1fe81c0ee89f 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -73,6 +73,7 @@ #include "mozilla/ipc/FileDescriptorSetChild.h" #include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/ipc/GeckoChildProcessHost.h" +#include "mozilla/ipc/LibrarySandboxPreload.h" #include "mozilla/ipc/ProcessChild.h" #include "mozilla/ipc/PChildToParentStreamChild.h" #include "mozilla/ipc/PParentToChildStreamChild.h" @@ -1802,6 +1803,11 @@ mozilla::ipc::IPCResult ContentChild::RecvSetProcessSandbox( // We may want to move the sandbox initialization somewhere else // at some point; see bug 880808. #if defined(MOZ_SANDBOX) + +# ifdef MOZ_USING_WASM_SANDBOXING + mozilla::ipc::PreloadSandboxedDynamicLibraries(); +# endif + bool sandboxEnabled = true; # if defined(XP_LINUX) // On Linux, we have to support systems that can't use any sandboxing. diff --git a/gfx/thebes/gfxFontEntry.cpp b/gfx/thebes/gfxFontEntry.cpp index 6005c7458bdd..c2588361decc 100644 --- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -27,6 +27,9 @@ #include "nsStyleConsts.h" #include "mozilla/AppUnits.h" #include "mozilla/FloatingPoint.h" +#ifdef MOZ_WASM_SANDBOXING_GRAPHITE +# include "mozilla/ipc/LibrarySandboxPreload.h" +#endif #include "mozilla/Likely.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Preferences.h" @@ -610,7 +613,11 @@ struct gfxFontEntry::GrSandboxData { GrSandboxData() { #ifdef MOZ_WASM_SANDBOXING_GRAPHITE -# error "Sandboxed graphite not yet implemented" + // Firefox preloads the library externally to ensure we won't be stopped by + // the content sandbox + const bool external_loads_exist = true; + sandbox.create_sandbox(mozilla::ipc::GetSandboxedGraphitePath().get(), + external_loads_exist); #else sandbox.create_sandbox(); #endif diff --git a/ipc/glue/LibrarySandboxPreload.cpp b/ipc/glue/LibrarySandboxPreload.cpp new file mode 100644 index 000000000000..a50f044d3aa5 --- /dev/null +++ b/ipc/glue/LibrarySandboxPreload.cpp @@ -0,0 +1,57 @@ +/* -*- 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 http://mozilla.org/MPL/2.0/. */ + +#include "LibrarySandboxPreload.h" + +#include "BinaryPath.h" +#include "prlink.h" + +namespace mozilla { +namespace ipc { + +nsAutoCString GetSandboxedGraphitePath() { + nsCOMPtr binaryPath; + nsresult rv = mozilla::BinaryPath::GetFile(getter_AddRefs(binaryPath)); + if (NS_FAILED(rv)) { + MOZ_CRASH("Library preload failure: Failed to get binary file\n"); + } + + nsCOMPtr graphiteFile; + rv = binaryPath->GetParent(getter_AddRefs(graphiteFile)); + if (NS_FAILED(rv)) { + MOZ_CRASH("Library preload failure: Failed to get binary folder\n"); + } + + rv = graphiteFile->AppendNative(NS_LITERAL_CSTRING("libgraphitewasm.so")); + if (NS_FAILED(rv)) { + MOZ_CRASH("Library preload failure: Failed to get libgraphite file"); + } + + nsAutoString path; + rv = graphiteFile->GetPath(path); + if (NS_FAILED(rv)) { + MOZ_CRASH("Library preload failure: Failed to get libgraphite path\n"); + } + + nsAutoCString converted_path = NS_ConvertUTF16toUTF8(path); + return converted_path; +} + +void PreloadSandboxedDynamicLibraries() { +#ifdef MOZ_WASM_SANDBOXING_GRAPHITE + nsAutoCString path = GetSandboxedGraphitePath(); + PRLibSpec libSpec; + libSpec.type = PR_LibSpec_Pathname; + libSpec.value.pathname = path.get(); + PRLibrary* ret = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY); + if (!ret) { + MOZ_CRASH("Library preload failure: Failed to load libgraphite\n"); + } +#endif +} + +} // namespace ipc +} // namespace mozilla \ No newline at end of file diff --git a/ipc/glue/LibrarySandboxPreload.h b/ipc/glue/LibrarySandboxPreload.h new file mode 100644 index 000000000000..36ac7baab93a --- /dev/null +++ b/ipc/glue/LibrarySandboxPreload.h @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=4 et : + */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#ifndef ipc_glue_LibrarySandboxPreload_h +#define ipc_glue_LibrarySandboxPreload_h + +namespace mozilla { +namespace ipc { +nsAutoCString GetSandboxedGraphitePath(); +void PreloadSandboxedDynamicLibraries(); +} // namespace ipc +} // namespace mozilla +#endif \ No newline at end of file diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index 68a08a597e1b..df5ef4cd9c8d 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -38,6 +38,7 @@ EXPORTS.mozilla.ipc += [ 'IPCStreamSource.h', 'IPCStreamUtils.h', 'IPDLParamTraits.h', + 'LibrarySandboxPreload.h', 'MessageChannel.h', 'MessageLink.h', 'Neutering.h', @@ -162,6 +163,7 @@ UNIFIED_SOURCES += [ 'IPCStreamParent.cpp', 'IPCStreamSource.cpp', 'IPCStreamUtils.cpp', + 'LibrarySandboxPreload.cpp', 'MessageChannel.cpp', 'MessageLink.cpp', 'MessagePump.cpp', From 0ed2c652dda207a19707709cb8a318e62e9e8b68 Mon Sep 17 00:00:00 2001 From: James Graham Date: Fri, 20 Dec 2019 18:35:37 +0000 Subject: [PATCH 02/83] Bug 1569559 - Don't remove subtests where a condition is outside the updatable set, r=maja_zf Sometimes we see subtests that only appear in certain conditions e.g. if we get an early error on nightly but the tests run as expected in stable. In this case the wpt sync bot will update the metadata with --full and remove the missing subtests. To work around this, check if subtests contain any conditions that aren't part of the update set, and if so never remove them Differential Revision: https://phabricator.services.mozilla.com/D57983 --HG-- extra : moz-landing-system : lando --- .../wptrunner/wptrunner/manifestupdate.py | 2 +- .../tools/wptrunner/wptrunner/metadata.py | 27 ++++++++++++++++++- .../wptrunner/wptrunner/tests/test_update.py | 24 ++++++++++++++++- .../wptmanifest/backends/conditional.py | 4 +++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py index af9af18d9071..2f2a8d543352 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py @@ -513,7 +513,7 @@ class PropertyUpdate(object): top_level_props, dependent_props = self.node.root.run_info_properties update_properties = set(top_level_props) for item in itervalues(dependent_props): - update_properties |= set(dependent_props) + update_properties |= set(item) for condition in current_conditions: if ((not condition.variables.issubset(update_properties) and not run_info_by_condition[condition])): diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py index 24267093b034..58281ad289c6 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/metadata.py @@ -4,6 +4,7 @@ import os from collections import defaultdict, namedtuple from mozlog import structuredlog +from six import itervalues from six.moves import intern from . import manifestupdate @@ -285,7 +286,7 @@ def update_results(id_test_map, disable_intermittent, update_intermittent, remove_intermittent): - test_file_items = set(id_test_map.itervalues()) + test_file_items = set(itervalues(id_test_map)) default_expected_by_type = {} for test_type, test_cls in wpttest.manifest_test_cls.iteritems(): @@ -672,6 +673,29 @@ class TestFileData(object): return rv + def filter_unknown_props(self, update_properties, subtests): + # Remove subtests which have some conditions that aren't in update_properties + # since removing these may be inappropriate + top_level_props, dependent_props = update_properties + all_properties = set(top_level_props) + for item in itervalues(dependent_props): + all_properties |= set(item) + + filtered = [] + for subtest in subtests: + include = True + for key, _ in subtest.iter_properties(): + conditions = subtest.get_conditions(key) + for condition in conditions: + if not condition.variables.issubset(all_properties): + include = False + break + if not include: + break + if include: + filtered.append(subtest) + return filtered + def update(self, default_expected_by_type, update_properties, full_update=False, disable_intermittent=None, update_intermittent=False, remove_intermittent=False): @@ -686,6 +710,7 @@ class TestFileData(object): if full_update: orphans = self.orphan_subtests(expected) + orphans = self.filter_unknown_props(update_properties, orphans) if not self.requires_update and not orphans: return diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py index bb3a58f2281e..89457e3768b4 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_update.py @@ -67,7 +67,7 @@ def update(tests, *logs, **kwargs): updater.update_from_log(log) update_properties = (["debug", "os", "version", "processor"], - {"os": ["version"], "processor": "bits"}) + {"os": ["version"], "processor": ["bits"]}) expected_data = {} metadata.load_expected = lambda _, __, test_path, *args: expected_data.get(test_path) @@ -1260,6 +1260,28 @@ def test_update_full_unknown(): "expected", run_info_2) == "ERROR" +@pytest.mark.xfail(sys.version[0] == "3", + reason="metadata doesn't support py3") +def test_update_full_unknown_missing(): + tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] + [subtest_deleted] + expected: + if release_or_beta: ERROR + FAIL +""")] + + log_0 = suite_log([("test_start", {"test": test_id}), + ("test_status", {"test": test_id, + "subtest": "test1", + "status": "PASS", + "expected": "PASS"}), + ("test_end", {"test": test_id, + "status": "OK"})], + run_info={"debug": False, "release_or_beta": False}) + + updated = update(tests, log_0, full_update=True) + assert len(updated) == 0 + @pytest.mark.xfail(sys.version[0] == "3", reason="metadata doesn't support py3") diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py index aacd7857072f..ab3c83ebd510 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py @@ -382,6 +382,10 @@ class ManifestItem(object): for item in self._flatten().iterkeys(): yield item + def iter_properties(self): + for item in self._data: + yield item, self._data[item] + def remove_value(self, key, value): if key not in self._data: return From c4a7a05545e5af5a1aad25ac083673cfaa697cba Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Fri, 20 Dec 2019 18:01:19 +0000 Subject: [PATCH 03/83] Bug 1604530 - Handle GC with uninitialized Instrumentation Holder r=bhackett Differential Revision: https://phabricator.services.mozilla.com/D57924 --HG-- extra : moz-landing-system : lando --- js/src/vm/Instrumentation.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/js/src/vm/Instrumentation.cpp b/js/src/vm/Instrumentation.cpp index b8ec9a224220..64bde478c67b 100644 --- a/js/src/vm/Instrumentation.cpp +++ b/js/src/vm/Instrumentation.cpp @@ -31,7 +31,8 @@ enum InstrumentationHolderSlots { static RealmInstrumentation* GetInstrumentation(JSObject* obj) { Value v = JS_GetReservedSlot(obj, RealmInstrumentationSlot); - return static_cast(v.toPrivate()); + return static_cast(v.isUndefined() ? nullptr + : v.toPrivate()); } /* static */ @@ -43,7 +44,9 @@ void RealmInstrumentation::holderFinalize(JSFreeOp* fop, JSObject* obj) { /* static */ void RealmInstrumentation::holderTrace(JSTracer* trc, JSObject* obj) { RealmInstrumentation* instrumentation = GetInstrumentation(obj); - instrumentation->trace(trc); + if (instrumentation) { + instrumentation->trace(trc); + } } static const JSClassOps InstrumentationHolderClassOps = { @@ -168,6 +171,7 @@ bool RealmInstrumentation::setActive(JSContext* cx, } RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); if (active != instrumentation->active) { instrumentation->active = active; @@ -188,6 +192,7 @@ bool RealmInstrumentation::isActive(GlobalObject* global) { MOZ_ASSERT(holder); RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); return instrumentation->active; } @@ -197,6 +202,7 @@ const int32_t* RealmInstrumentation::addressOfActive(GlobalObject* global) { MOZ_ASSERT(holder); RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); return &instrumentation->active; } @@ -206,6 +212,7 @@ JSObject* RealmInstrumentation::getCallback(GlobalObject* global) { MOZ_ASSERT(holder); RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); return instrumentation->callback; } @@ -217,6 +224,7 @@ uint32_t RealmInstrumentation::getInstrumentationKinds(GlobalObject* global) { } RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); return instrumentation->kinds; } @@ -227,6 +235,7 @@ bool RealmInstrumentation::getScriptId(JSContext* cx, MOZ_ASSERT(global == cx->global()); RootedObject holder(cx, global->getInstrumentationHolder()); RealmInstrumentation* instrumentation = GetInstrumentation(holder); + MOZ_ASSERT(instrumentation); RootedObject dbgObject(cx, UncheckedUnwrap(instrumentation->dbgObject)); From 97bd574229d29c77338baa7bd35e33a1342fc14a Mon Sep 17 00:00:00 2001 From: Mike Shal Date: Fri, 20 Dec 2019 17:49:26 +0000 Subject: [PATCH 04/83] Bug 1601777 - Check if any build backend is out of date; r=froydnj By default we create both the RecursiveMake and FasterMake backends, but building.py is only checking if the RecursiveMake backend is out of date to decide if the backend needs to be updated. Since the FasterMake backend may have different input files, we also need to check if that's out of date, otherwise renaming certain files can cause './mach build faster' to break. Differential Revision: https://phabricator.services.mozilla.com/D58010 --HG-- extra : moz-landing-system : lando --- python/mozbuild/mozbuild/controller/building.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py index 9348a5763e96..4bfe74273245 100644 --- a/python/mozbuild/mozbuild/controller/building.py +++ b/python/mozbuild/mozbuild/controller/building.py @@ -1074,14 +1074,16 @@ class BuildDriver(MozbuildObject): config = self.reload_config_environment() - active_backend = config.substs.get('BUILD_BACKENDS', [None])[0] + all_backends = config.substs.get('BUILD_BACKENDS', [None]) + active_backend = all_backends[0] status = None if (not config_rc and - self.backend_out_of_date(mozpath.join(self.topobjdir, - 'backend.%sBackend' % - active_backend))): + any([self.backend_out_of_date(mozpath.join(self.topobjdir, + 'backend.%sBackend' % + backend)) + for backend in all_backends])): print('Build configuration changed. Regenerating backend.') args = [config.substs['PYTHON'], mozpath.join(self.topobjdir, 'config.status')] From 42066a1e0f08248ab8d28a8862365df294a2df48 Mon Sep 17 00:00:00 2001 From: Andrew Halberstadt Date: Mon, 16 Dec 2019 17:07:40 +0000 Subject: [PATCH 05/83] Bug 1583353 - [ci] Chunk xpcshell in the taskgraph, r=gbrown Differential Revision: https://phabricator.services.mozilla.com/D57326 --HG-- extra : moz-landing-system : lando --- taskcluster/taskgraph/transforms/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/taskcluster/taskgraph/transforms/tests.py b/taskcluster/taskgraph/transforms/tests.py index 1d1d48cf3dbf..d004228e778c 100644 --- a/taskcluster/taskgraph/transforms/tests.py +++ b/taskcluster/taskgraph/transforms/tests.py @@ -1303,7 +1303,6 @@ CHUNK_SUITES_BLACKLIST = ( 'web-platform-tests', 'web-platform-tests-reftests', 'web-platform-tests-wdspec', - 'xpcshell', ) """These suites will be chunked at test runtime rather than here in the taskgraph.""" From 1b32e82bc4768b035f09a7ed71cab7b164b0a187 Mon Sep 17 00:00:00 2001 From: Junior Hsu Date: Fri, 20 Dec 2019 18:22:40 +0000 Subject: [PATCH 06/83] Bug 1531708 - avoid hiding error in nsSyncStreamListener r=michal Differential Revision: https://phabricator.services.mozilla.com/D56812 --HG-- extra : moz-landing-system : lando --- netwerk/base/nsSyncStreamListener.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/netwerk/base/nsSyncStreamListener.cpp b/netwerk/base/nsSyncStreamListener.cpp index 10d2696f40c4..2edf3a2f0567 100644 --- a/netwerk/base/nsSyncStreamListener.cpp +++ b/netwerk/base/nsSyncStreamListener.cpp @@ -116,8 +116,14 @@ nsSyncStreamListener::Available(uint64_t* result) { mStatus = mPipeIn->Available(result); if (NS_SUCCEEDED(mStatus) && (*result == 0) && !mDone) { - mStatus = WaitForData(); - if (NS_SUCCEEDED(mStatus)) mStatus = mPipeIn->Available(result); + nsresult rv = WaitForData(); + if (NS_FAILED(rv)) { + // Note that `WaitForData` could fail `mStatus`. Do not overwrite if it's + // the case. + mStatus = NS_SUCCEEDED(mStatus) ? rv : mStatus; + } else if (NS_SUCCEEDED(mStatus)) { + mStatus = mPipeIn->Available(result); + } } return mStatus; } From e4d9fe5e1038a92717e26cbcdb029abaa7ba8217 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 20 Dec 2019 17:52:11 +0000 Subject: [PATCH 07/83] Bug 1605418 - use GeneratedFile template in layout/style/test/gtest/; r=firefox-style-system-reviewers,jwatt The template is slightly nicer and slighty more modern. Differential Revision: https://phabricator.services.mozilla.com/D58009 --HG-- extra : moz-landing-system : lando --- layout/style/test/gtest/moz.build | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/layout/style/test/gtest/moz.build b/layout/style/test/gtest/moz.build index 216467397838..425f8c7055f0 100644 --- a/layout/style/test/gtest/moz.build +++ b/layout/style/test/gtest/moz.build @@ -15,11 +15,8 @@ LOCAL_INCLUDES += [ '/layout/style', ] -GENERATED_FILES += [ - 'ExampleStylesheet.h', -] - -GENERATED_FILES['ExampleStylesheet.h'].script = 'generate_example_stylesheet.py' -GENERATED_FILES['ExampleStylesheet.h'].inputs = ['example.css'] +GeneratedFile('ExampleStylesheet.h', + script='generate_example_stylesheet.py', + inputs=['example.css']) FINAL_LIBRARY = 'xul-gtest' From 68e5d2ff117d202976f674621891910ea1af898d Mon Sep 17 00:00:00 2001 From: Se Yeon Kim Date: Tue, 17 Dec 2019 19:41:03 +0000 Subject: [PATCH 08/83] Bug 1594497 - Increase shavar chunk size limit r=dimi Differential Revision: https://phabricator.services.mozilla.com/D52913 --HG-- extra : moz-landing-system : lando --- toolkit/components/url-classifier/ProtocolParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/url-classifier/ProtocolParser.cpp b/toolkit/components/url-classifier/ProtocolParser.cpp index 89cc31d53593..a95ac51c8382 100644 --- a/toolkit/components/url-classifier/ProtocolParser.cpp +++ b/toolkit/components/url-classifier/ProtocolParser.cpp @@ -30,7 +30,7 @@ namespace mozilla { namespace safebrowsing { // Updates will fail if fed chunks larger than this -const uint32_t MAX_CHUNK_SIZE = (1024 * 1024); +const uint32_t MAX_CHUNK_SIZE = (4 * 1024 * 1024); // Updates will fail if the total number of tocuhed chunks is larger than this const uint32_t MAX_CHUNK_RANGE = 1000000; From 3069b0683291681b612c58ae5ad877d24b68d874 Mon Sep 17 00:00:00 2001 From: Se Yeon Kim Date: Tue, 17 Dec 2019 19:41:01 +0000 Subject: [PATCH 09/83] Bug 1594497 - Add Google entity lists r=dimi Depends on D52913 Differential Revision: https://phabricator.services.mozilla.com/D57389 --HG-- extra : moz-landing-system : lando --- modules/libpref/init/all.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5f4e684cfc8c..62890ef1113d 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4341,22 +4341,22 @@ pref("urlclassifier.passwordAllowTable", "goog-passwordwhite-proto"); // Tables for anti-tracking features pref("urlclassifier.trackingAnnotationTable", "moztest-track-simple,ads-track-digest256,social-track-digest256,analytics-track-digest256,content-track-digest256"); -pref("urlclassifier.trackingAnnotationWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256"); +pref("urlclassifier.trackingAnnotationWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256,google-trackwhite-digest256"); pref("urlclassifier.trackingTable", "moztest-track-simple,ads-track-digest256,social-track-digest256,analytics-track-digest256"); -pref("urlclassifier.trackingWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256"); +pref("urlclassifier.trackingWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256,google-trackwhite-digest256"); pref("urlclassifier.features.fingerprinting.blacklistTables", "base-fingerprinting-track-digest256"); -pref("urlclassifier.features.fingerprinting.whitelistTables", "mozstd-trackwhite-digest256"); +pref("urlclassifier.features.fingerprinting.whitelistTables", "mozstd-trackwhite-digest256,google-trackwhite-digest256"); pref("urlclassifier.features.fingerprinting.annotate.blacklistTables", "base-fingerprinting-track-digest256"); -pref("urlclassifier.features.fingerprinting.annotate.whitelistTables", "mozstd-trackwhite-digest256"); +pref("urlclassifier.features.fingerprinting.annotate.whitelistTables", "mozstd-trackwhite-digest256,google-trackwhite-digest256"); pref("urlclassifier.features.cryptomining.blacklistTables", "base-cryptomining-track-digest256"); pref("urlclassifier.features.cryptomining.whitelistTables", "mozstd-trackwhite-digest256"); pref("urlclassifier.features.cryptomining.annotate.blacklistTables", "base-cryptomining-track-digest256"); pref("urlclassifier.features.cryptomining.annotate.whitelistTables", "mozstd-trackwhite-digest256"); pref("urlclassifier.features.socialtracking.blacklistTables", "social-tracking-protection-facebook-digest256,social-tracking-protection-linkedin-digest256,social-tracking-protection-twitter-digest256"); -pref("urlclassifier.features.socialtracking.whitelistTables", "mozstd-trackwhite-digest256"); +pref("urlclassifier.features.socialtracking.whitelistTables", "mozstd-trackwhite-digest25,google-trackwhite-digest256"); pref("urlclassifier.features.socialtracking.annotate.blacklistTables", "social-tracking-protection-facebook-digest256,social-tracking-protection-linkedin-digest256,social-tracking-protection-twitter-digest256"); -pref("urlclassifier.features.socialtracking.annotate.whitelistTables", "mozstd-trackwhite-digest256"); +pref("urlclassifier.features.socialtracking.annotate.whitelistTables", "mozstd-trackwhite-digest256,google-trackwhite-digest256"); // These tables will never trigger a gethash call. pref("urlclassifier.disallow_completions", "goog-downloadwhite-digest256,base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,goog-passwordwhite-proto,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256,social-tracking-protection-digest256,social-tracking-protection-facebook-digest256,social-tracking-protection-linkedin-digest256,social-tracking-protection-twitter-digest256"); @@ -4429,7 +4429,7 @@ pref("browser.safebrowsing.reportPhishURL", "https://%LOCALE%.phish-report.mozil // Mozilla Safe Browsing provider (for tracking protection and plugin blocking) pref("browser.safebrowsing.provider.mozilla.pver", "2.2"); -pref("browser.safebrowsing.provider.mozilla.lists", "base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256,social-tracking-protection-digest256,social-tracking-protection-facebook-digest256,social-tracking-protection-linkedin-digest256,social-tracking-protection-twitter-digest256"); +pref("browser.safebrowsing.provider.mozilla.lists", "base-track-digest256,mozstd-trackwhite-digest256,google-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256,social-tracking-protection-digest256,social-tracking-protection-facebook-digest256,social-tracking-protection-linkedin-digest256,social-tracking-protection-twitter-digest256"); pref("browser.safebrowsing.provider.mozilla.updateURL", "https://shavar.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2"); pref("browser.safebrowsing.provider.mozilla.gethashURL", "https://shavar.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2"); // Set to a date in the past to force immediate download in new profiles. From f7332b479f693fc3fbe13b71ace15d44a3140971 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Fri, 20 Dec 2019 19:05:46 +0000 Subject: [PATCH 10/83] Bug 1605405: Break the MSCOM <-> XPCOM cycle in the alerts service during shutdown. r=jmathies While windows toast notifications are active there is a reference cycle between MSCOM and XPCOM objects that the cycle collector cannot break. Fix this by breaking the reference cycle at any point where we expect the toast notification to be destroyed. Differential Revision: https://phabricator.services.mozilla.com/D58001 --HG-- extra : moz-landing-system : lando --- widget/windows/ToastNotification.cpp | 13 ++- widget/windows/ToastNotificationHandler.cpp | 91 +++++++++++---------- widget/windows/ToastNotificationHandler.h | 2 + 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/widget/windows/ToastNotification.cpp b/widget/windows/ToastNotification.cpp index f4761865accf..de72a156841b 100644 --- a/widget/windows/ToastNotification.cpp +++ b/widget/windows/ToastNotification.cpp @@ -61,7 +61,15 @@ ToastNotification::Observe(nsISupports* aSubject, const char* aTopic, // Got quit-application // The handlers destructors will do the right thing (de-register with // Windows). - mActiveHandlers.Clear(); + for (auto iter = mActiveHandlers.Iter(); !iter.Done(); iter.Next()) { + RefPtr handler = iter.UserData(); + iter.Remove(); + + // Break the cycle between the handler and the MSCOM notification so the + // handler's destructor will be called. + handler->UnregisterHandler(); + } + return NS_OK; } @@ -145,6 +153,7 @@ ToastNotification::ShowAlert(nsIAlertNotification* aAlert, rv = handler->InitAlertAsync(aAlert); if (NS_WARN_IF(NS_FAILED(rv))) { mActiveHandlers.Remove(name); + handler->UnregisterHandler(); return rv; } @@ -159,6 +168,7 @@ ToastNotification::CloseAlert(const nsAString& aAlertName, return NS_OK; } mActiveHandlers.Remove(aAlertName); + handler->UnregisterHandler(); return NS_OK; } @@ -180,6 +190,7 @@ void ToastNotification::RemoveHandler(const nsAString& aAlertName, // the hashtable .Remove() method. Wait until we have returned from there. RefPtr kungFuDeathGrip(aHandler); mActiveHandlers.Remove(aAlertName); + aHandler->UnregisterHandler(); } } diff --git a/widget/windows/ToastNotificationHandler.cpp b/widget/windows/ToastNotificationHandler.cpp index 010e6ffaa48f..fffc3511270d 100644 --- a/widget/windows/ToastNotificationHandler.cpp +++ b/widget/windows/ToastNotificationHandler.cpp @@ -6,10 +6,13 @@ #include "ToastNotificationHandler.h" +#include "WidgetUtils.h" +#include "WinTaskbar.h" +#include "WinUtils.h" #include "imgIContainer.h" #include "imgIRequest.h" -#include "mozilla/gfx/2D.h" #include "mozilla/WindowsVersion.h" +#include "mozilla/gfx/2D.h" #include "nsDirectoryServiceDefs.h" #include "nsIStringBundle.h" #include "nsIURI.h" @@ -19,9 +22,6 @@ #include "nsNetUtil.h" #include "nsPIDOMWindow.h" #include "nsProxyRelease.h" -#include "WidgetUtils.h" -#include "WinTaskbar.h" -#include "WinUtils.h" #include "ToastNotification.h" @@ -29,15 +29,15 @@ namespace mozilla { namespace widget { typedef ABI::Windows::Foundation::ITypedEventHandler< - ABI::Windows::UI::Notifications::ToastNotification*, IInspectable*> + ABI::Windows::UI::Notifications::ToastNotification *, IInspectable *> ToastActivationHandler; typedef ABI::Windows::Foundation::ITypedEventHandler< - ABI::Windows::UI::Notifications::ToastNotification*, - ABI::Windows::UI::Notifications::ToastDismissedEventArgs*> + ABI::Windows::UI::Notifications::ToastNotification *, + ABI::Windows::UI::Notifications::ToastDismissedEventArgs *> ToastDismissedHandler; typedef ABI::Windows::Foundation::ITypedEventHandler< - ABI::Windows::UI::Notifications::ToastNotification*, - ABI::Windows::UI::Notifications::ToastFailedEventArgs*> + ABI::Windows::UI::Notifications::ToastNotification *, + ABI::Windows::UI::Notifications::ToastFailedEventArgs *> ToastFailedHandler; using namespace ABI::Windows::Data::Xml::Dom; @@ -49,11 +49,11 @@ using namespace mozilla; NS_IMPL_ISUPPORTS(ToastNotificationHandler, nsIAlertNotificationImageListener) -static bool SetNodeValueString(const nsString& aString, IXmlNode* node, - IXmlDocument* xml) { +static bool SetNodeValueString(const nsString &aString, IXmlNode *node, + IXmlDocument *xml) { ComPtr inputText; if (NS_WARN_IF(FAILED(xml->CreateTextNode( - HStringReference(static_cast(aString.get())).Get(), + HStringReference(static_cast(aString.get())).Get(), &inputText)))) { return false; } @@ -69,9 +69,9 @@ static bool SetNodeValueString(const nsString& aString, IXmlNode* node, return true; } -static bool SetAttribute(IXmlElement* element, const HSTRING name, - const nsAString& value) { - HSTRING valueStr = HStringReference(static_cast( +static bool SetAttribute(IXmlElement *element, const HSTRING name, + const nsAString &value) { + HSTRING valueStr = HStringReference(static_cast( PromiseFlatString(value).get())) .Get(); if (NS_WARN_IF(FAILED(element->SetAttribute(name, valueStr)))) { @@ -80,9 +80,9 @@ static bool SetAttribute(IXmlElement* element, const HSTRING name, return true; } -static bool AddActionNode(IXmlDocument* toastXml, IXmlNode* actionsNode, - const nsAString& actionTitle, - const nsAString& actionArgs) { +static bool AddActionNode(IXmlDocument *toastXml, IXmlNode *actionsNode, + const nsAString &actionTitle, + const nsAString &actionArgs) { ComPtr action; HRESULT hr = toastXml->CreateElement(HStringReference(L"action").Get(), &action); @@ -146,12 +146,19 @@ ToastNotificationHandler::~ToastNotificationHandler() { NS_ASSERTION(NS_SUCCEEDED(rv), "Cannot remove temporary image file"); } + UnregisterHandler(); +} + +void ToastNotificationHandler::UnregisterHandler() { if (mNotification && mNotifier) { mNotification->remove_Dismissed(mDismissedToken); mNotification->remove_Activated(mActivatedToken); mNotification->remove_Failed(mFailedToken); mNotifier->Hide(mNotification.Get()); } + + mNotification = nullptr; + mNotifier = nullptr; } ComPtr ToastNotificationHandler::InitializeXmlForTemplate( @@ -165,8 +172,8 @@ ComPtr ToastNotificationHandler::InitializeXmlForTemplate( return toastXml; } -nsresult ToastNotificationHandler::InitAlertAsync( - nsIAlertNotification* aAlert) { +nsresult +ToastNotificationHandler::InitAlertAsync(nsIAlertNotification *aAlert) { return aAlert->LoadImage(/* aTimeout = */ 0, this, /* aUserData = */ nullptr, getter_AddRefs(mImageRequest)); } @@ -332,7 +339,7 @@ bool ToastNotificationHandler::ShowAlert() { } bool ToastNotificationHandler::CreateWindowsNotificationFromXml( - IXmlDocument* aXml) { + IXmlDocument *aXml) { ComPtr factory; HRESULT hr = GetActivationFactory( HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification) @@ -350,8 +357,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml( RefPtr self = this; hr = mNotification->add_Activated( - Callback([self](IToastNotification* aNotification, - IInspectable* aInspectable) { + Callback([self](IToastNotification *aNotification, + IInspectable *aInspectable) { return self->OnActivate(aNotification, aInspectable); }).Get(), &mActivatedToken); @@ -360,8 +367,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml( } hr = mNotification->add_Dismissed( - Callback([self](IToastNotification* aNotification, - IToastDismissedEventArgs* aArgs) { + Callback([self](IToastNotification *aNotification, + IToastDismissedEventArgs *aArgs) { return self->OnDismiss(aNotification, aArgs); }).Get(), &mDismissedToken); @@ -370,8 +377,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml( } hr = mNotification->add_Failed( - Callback([self](IToastNotification* aNotification, - IToastFailedEventArgs* aArgs) { + Callback([self](IToastNotification *aNotification, + IToastFailedEventArgs *aArgs) { return self->OnFail(aNotification, aArgs); }).Get(), &mFailedToken); @@ -391,7 +398,7 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml( } HSTRING uidStr = - HStringReference(static_cast(uid.get())).Get(); + HStringReference(static_cast(uid.get())).Get(); hr = toastNotificationManagerStatics->CreateToastNotifierWithId(uidStr, &mNotifier); if (NS_WARN_IF(FAILED(hr))) { @@ -411,20 +418,20 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml( } HRESULT -ToastNotificationHandler::OnActivate(IToastNotification* notification, - IInspectable* inspectable) { +ToastNotificationHandler::OnActivate(IToastNotification *notification, + IInspectable *inspectable) { if (mAlertListener) { nsAutoString argString; if (inspectable) { ComPtr eventArgs; HRESULT hr = inspectable->QueryInterface( - __uuidof(IToastActivatedEventArgs), (void**)&eventArgs); + __uuidof(IToastActivatedEventArgs), (void **)&eventArgs); if (SUCCEEDED(hr)) { HSTRING arguments; hr = eventArgs->get_Arguments(&arguments); if (SUCCEEDED(hr)) { uint32_t len = 0; - const wchar_t* buffer = WindowsGetStringRawBuffer(arguments, &len); + const wchar_t *buffer = WindowsGetStringRawBuffer(arguments, &len); if (buffer) { argString.Assign(buffer, len); } @@ -462,8 +469,8 @@ ToastNotificationHandler::OnActivate(IToastNotification* notification, } HRESULT -ToastNotificationHandler::OnDismiss(IToastNotification* notification, - IToastDismissedEventArgs* aArgs) { +ToastNotificationHandler::OnDismiss(IToastNotification *notification, + IToastDismissedEventArgs *aArgs) { if (mAlertListener) { mAlertListener->Observe(nullptr, "alertfinished", mCookie.get()); } @@ -472,8 +479,8 @@ ToastNotificationHandler::OnDismiss(IToastNotification* notification, } HRESULT -ToastNotificationHandler::OnFail(IToastNotification* notification, - IToastFailedEventArgs* aArgs) { +ToastNotificationHandler::OnFail(IToastNotification *notification, + IToastFailedEventArgs *aArgs) { if (mAlertListener) { mAlertListener->Observe(nullptr, "alertfinished", mCookie.get()); } @@ -489,12 +496,12 @@ nsresult ToastNotificationHandler::TryShowAlert() { return NS_OK; } NS_IMETHODIMP -ToastNotificationHandler::OnImageMissing(nsISupports*) { +ToastNotificationHandler::OnImageMissing(nsISupports *) { return TryShowAlert(); } NS_IMETHODIMP -ToastNotificationHandler::OnImageReady(nsISupports*, imgIRequest* aRequest) { +ToastNotificationHandler::OnImageReady(nsISupports *, imgIRequest *aRequest) { nsresult rv = AsyncSaveImage(aRequest); if (NS_FAILED(rv)) { return TryShowAlert(); @@ -502,7 +509,7 @@ ToastNotificationHandler::OnImageReady(nsISupports*, imgIRequest* aRequest) { return rv; } -nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest* aRequest) { +nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest *aRequest) { nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mImageFile)); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -565,7 +572,7 @@ nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest* aRequest) { nsCOMPtr cbRunnable = NS_NewRunnableFunction( "ToastNotificationHandler::AsyncWriteBitmapCb", [self, rv]() -> void { - auto handler = const_cast(self.get()); + auto handler = const_cast(self.get()); handler->OnWriteBitmapFinished(rv); }); @@ -604,5 +611,5 @@ nsresult ToastNotificationHandler::OnWriteBitmapSuccess() { return NS_OK; } -} // namespace widget -} // namespace mozilla +} // namespace widget +} // namespace mozilla diff --git a/widget/windows/ToastNotificationHandler.h b/widget/windows/ToastNotificationHandler.h index cbdaff519fd4..059bf142fd3c 100644 --- a/widget/windows/ToastNotificationHandler.h +++ b/widget/windows/ToastNotificationHandler.h @@ -45,6 +45,8 @@ class ToastNotificationHandler final void OnWriteBitmapFinished(nsresult rv); + void UnregisterHandler(); + protected: virtual ~ToastNotificationHandler(); From d7afb46b485848aa476bbbba0e6bf588fb082c6f Mon Sep 17 00:00:00 2001 From: Gavin Lazar Suntop Date: Fri, 20 Dec 2019 19:18:34 +0000 Subject: [PATCH 11/83] Bug 1602518 - Use text underline for hover state on Popular Topics links r=thecount Differential Revision: https://phabricator.services.mozilla.com/D58015 --HG-- extra : moz-landing-system : lando --- .../DiscoveryStreamComponents/Navigation/_Navigation.scss | 3 +-- browser/components/newtab/css/activity-stream-linux.css | 2 +- browser/components/newtab/css/activity-stream-mac.css | 2 +- browser/components/newtab/css/activity-stream-windows.css | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss index 7132d8e85158..53a74875b183 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss @@ -32,8 +32,7 @@ a { &:hover { - // text-decoration: underline; didn't quite match comps. - border-bottom: 1px solid var(--newtab-link-primary-color); + text-decoration: underline; &:active { border-bottom: 1px solid $blue-70; diff --git a/browser/components/newtab/css/activity-stream-linux.css b/browser/components/newtab/css/activity-stream-linux.css index 2682b6d443dc..a289a190c042 100644 --- a/browser/components/newtab/css/activity-stream-linux.css +++ b/browser/components/newtab/css/activity-stream-linux.css @@ -2469,7 +2469,7 @@ main { .ds-navigation ul li:last-child::after { content: none; } .ds-navigation ul li a:hover { - border-bottom: 1px solid var(--newtab-link-primary-color); } + text-decoration: underline; } .ds-navigation ul li a:hover:active { border-bottom: 1px solid #003EAA; } .ds-navigation ul li a:active { diff --git a/browser/components/newtab/css/activity-stream-mac.css b/browser/components/newtab/css/activity-stream-mac.css index ae24fbde7e92..37df2286bd37 100644 --- a/browser/components/newtab/css/activity-stream-mac.css +++ b/browser/components/newtab/css/activity-stream-mac.css @@ -2472,7 +2472,7 @@ main { .ds-navigation ul li:last-child::after { content: none; } .ds-navigation ul li a:hover { - border-bottom: 1px solid var(--newtab-link-primary-color); } + text-decoration: underline; } .ds-navigation ul li a:hover:active { border-bottom: 1px solid #003EAA; } .ds-navigation ul li a:active { diff --git a/browser/components/newtab/css/activity-stream-windows.css b/browser/components/newtab/css/activity-stream-windows.css index ca7f3603b484..dd1d1aa980cd 100644 --- a/browser/components/newtab/css/activity-stream-windows.css +++ b/browser/components/newtab/css/activity-stream-windows.css @@ -2469,7 +2469,7 @@ main { .ds-navigation ul li:last-child::after { content: none; } .ds-navigation ul li a:hover { - border-bottom: 1px solid var(--newtab-link-primary-color); } + text-decoration: underline; } .ds-navigation ul li a:hover:active { border-bottom: 1px solid #003EAA; } .ds-navigation ul li a:active { From 27b191a96e50ae85a4d340311cbc3b7ec8591b54 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Fri, 20 Dec 2019 10:58:19 +0000 Subject: [PATCH 12/83] Bug 1605026 - mark click_events_on_input.html as permafail on ubuntu1804 debug r=jmaher Changes: With acknowledgement from the test owner, disable this test for linux64/debug web-platform-tests due to permafail. Differential Revision: https://phabricator.services.mozilla.com/D57874 --HG-- extra : moz-landing-system : lando --- .../meta/uievents/click/click_events_on_input.html.ini | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 testing/web-platform/meta/uievents/click/click_events_on_input.html.ini diff --git a/testing/web-platform/meta/uievents/click/click_events_on_input.html.ini b/testing/web-platform/meta/uievents/click/click_events_on_input.html.ini new file mode 100644 index 000000000000..84ca237c3d91 --- /dev/null +++ b/testing/web-platform/meta/uievents/click/click_events_on_input.html.ini @@ -0,0 +1,5 @@ +[click_events_on_input.html] + disabled: + if (os == 'linux' and os_version == '18.04' and debug): https://bugzilla.mozilla.org/show_bug.cgi?id=1605026 + + From c9ab4ba28d2c39e245af0de4f897a177ec9d06a7 Mon Sep 17 00:00:00 2001 From: Kirk Steuber Date: Fri, 20 Dec 2019 17:41:31 +0000 Subject: [PATCH 13/83] Bug 1603828 - Remove XULElement.pack from webidl and c++ r=webidl,smaug Differential Revision: https://phabricator.services.mozilla.com/D57686 --HG-- extra : moz-landing-system : lando --- dom/webidl/XULElement.webidl | 2 -- dom/xul/nsXULElement.h | 4 ---- 2 files changed, 6 deletions(-) diff --git a/dom/webidl/XULElement.webidl b/dom/webidl/XULElement.webidl index 25cdc50cf5ae..7a6cae4ef52b 100644 --- a/dom/webidl/XULElement.webidl +++ b/dom/webidl/XULElement.webidl @@ -18,8 +18,6 @@ interface XULElement : Element { attribute DOMString ordinal; [SetterThrows] attribute DOMString orient; - [SetterThrows] - attribute DOMString pack; // Properties for hiding elements. attribute boolean hidden; diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 057205e9dd63..939b720c590c 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -399,10 +399,6 @@ class nsXULElement : public nsStyledElement { void SetOrient(const nsAString& aValue, mozilla::ErrorResult& rv) { SetXULAttr(nsGkAtoms::orient, aValue, rv); } - void GetPack(DOMString& aValue) const { GetXULAttr(nsGkAtoms::pack, aValue); } - void SetPack(const nsAString& aValue, mozilla::ErrorResult& rv) { - SetXULAttr(nsGkAtoms::pack, aValue, rv); - } bool Hidden() const { return BoolAttrIsTrue(nsGkAtoms::hidden); } void SetHidden(bool aHidden) { SetXULBoolAttr(nsGkAtoms::hidden, aHidden); } bool Collapsed() const { return BoolAttrIsTrue(nsGkAtoms::collapsed); } From 3036d033c3f4dea8074fd3bbd2ca081383e5ed26 Mon Sep 17 00:00:00 2001 From: Kirk Steuber Date: Thu, 19 Dec 2019 06:39:15 +0000 Subject: [PATCH 14/83] Bug 1603828 - Replace XULElement.pack with getAttribute/setAttribute r=bgrins Depends on D57686 Differential Revision: https://phabricator.services.mozilla.com/D57687 --HG-- extra : moz-landing-system : lando --- browser/components/places/content/places-menupopup.js | 8 ++++---- toolkit/content/tests/chrome/test_arrowpanel.xhtml | 2 +- toolkit/content/widgets/panel.js | 8 ++++---- toolkit/mozapps/extensions/content/blocklist.js | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/browser/components/places/content/places-menupopup.js b/browser/components/places/content/places-menupopup.js index 170c392119ff..1bcd894d05d8 100644 --- a/browser/components/places/content/places-menupopup.js +++ b/browser/components/places/content/places-menupopup.js @@ -663,9 +663,9 @@ container.orient = "horizontal"; arrowbox.orient = "vertical"; if (position.indexOf("_after") > 0) { - arrowbox.pack = "end"; + arrowbox.setAttribute("pack", "end"); } else { - arrowbox.pack = "start"; + arrowbox.setAttribute("pack", "start"); } arrowbox.style.transform = "translate(0, " + -offset + "px)"; @@ -686,9 +686,9 @@ container.orient = ""; arrowbox.orient = ""; if (position.indexOf("_end") > 0) { - arrowbox.pack = "end"; + arrowbox.setAttribute("pack", "end"); } else { - arrowbox.pack = "start"; + arrowbox.setAttribute("pack", "start"); } arrowbox.style.transform = "translate(" + -offset + "px, 0)"; diff --git a/toolkit/content/tests/chrome/test_arrowpanel.xhtml b/toolkit/content/tests/chrome/test_arrowpanel.xhtml index cad537ca2554..c720fcc6c0c0 100644 --- a/toolkit/content/tests/chrome/test_arrowpanel.xhtml +++ b/toolkit/content/tests/chrome/test_arrowpanel.xhtml @@ -298,7 +298,7 @@ function checkPanelPosition(panel) var arrow = panel.shadowRoot.querySelector(".panel-arrow"); is(panel.getAttribute("side"), expectedSide, "panel arrow side"); is(arrow.hidden, false, "panel hidden"); - is(arrow.parentNode.pack, expectedPack, "panel arrow pack"); + is(arrow.parentNode.getAttribute("pack"), expectedPack, "panel arrow pack"); is(panel.alignmentPosition, expectedAlignment, "panel alignmentPosition"); panel.hidePopup(); diff --git a/toolkit/content/widgets/panel.js b/toolkit/content/widgets/panel.js index 9e7577c1c011..8aacb39a9ed2 100644 --- a/toolkit/content/widgets/panel.js +++ b/toolkit/content/widgets/panel.js @@ -126,9 +126,9 @@ container.orient = "horizontal"; arrowbox.orient = "vertical"; if (position.indexOf("_after") > 0) { - arrowbox.pack = "end"; + arrowbox.setAttribute("pack", "end"); } else { - arrowbox.pack = "start"; + arrowbox.setAttribute("pack", "start"); } arrowbox.style.transform = "translate(0, " + -offset + "px)"; @@ -149,9 +149,9 @@ container.orient = ""; arrowbox.orient = ""; if (position.indexOf("_end") > 0) { - arrowbox.pack = "end"; + arrowbox.setAttribute("pack", "end"); } else { - arrowbox.pack = "start"; + arrowbox.setAttribute("pack", "start"); } arrowbox.style.transform = "translate(" + -offset + "px, 0)"; diff --git a/toolkit/mozapps/extensions/content/blocklist.js b/toolkit/mozapps/extensions/content/blocklist.js index 93b8d241bbd2..e5933f1ffad2 100644 --- a/toolkit/mozapps/extensions/content/blocklist.js +++ b/toolkit/mozapps/extensions/content/blocklist.js @@ -67,7 +67,7 @@ function init() { nameVersion.append(name, version); const fragment = document.createXULElement("hbox"); - fragment.pack = "end"; + fragment.setAttribute("pack", "end"); if (listItem.blocked) { fragment.appendChild( From 2dd64e92cd80aaf2ddd3b3284b00590185f46038 Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Fri, 20 Dec 2019 19:38:05 +0000 Subject: [PATCH 15/83] Bug 1590098 - [remote] Implement basic support for Network.getCookies. r=remote-protocol-reviewers,ato,maja_zf This patch adds basic support for retrieving cookies, which means that it returns the cookies for the currently active target. Hereby it has the following limitations: 1. It does not walk the frame tree, and as such only returns the cookies from the top-level frame. Support for that will be added once frames can correctly be handled, which means once support for the JSWindowActor API has been landed. 2. The "urls" parameter is not supported because it is unclear right now what it actually does. More investigation is necessary before any implementation can happen. 3. There is no support for the file:// protocol yet. 4. Dot domains aren't taken care of yet. Differential Revision: https://phabricator.services.mozilla.com/D57614 --HG-- extra : moz-landing-system : lando --- remote/domains/parent/Network.jsm | 75 ++++++ remote/test/browser/network/browser.ini | 6 +- .../browser/network/browser_getCookies.js | 244 ++++++++++++++++++ remote/test/browser/network/sjs-cookies.sjs | 44 ++++ 4 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 remote/test/browser/network/browser_getCookies.js create mode 100644 remote/test/browser/network/sjs-cookies.sjs diff --git a/remote/domains/parent/Network.jsm b/remote/domains/parent/Network.jsm index 43f26243b37f..044df1cc0af0 100644 --- a/remote/domains/parent/Network.jsm +++ b/remote/domains/parent/Network.jsm @@ -6,6 +6,14 @@ var EXPORTED_SYMBOLS = ["Network"]; +const { XPCOMUtils } = ChromeUtils.import( + "resource://gre/modules/XPCOMUtils.jsm" +); + +XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]); + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + const { Domain } = ChromeUtils.import( "chrome://remote/content/domains/Domain.jsm" ); @@ -75,6 +83,73 @@ class Network extends Domain { this.enabled = false; } + /** + * Returns all browser cookies for the current URL. + * + * @param {Object} options + * @param {Array=} urls + * The list of URLs for which applicable cookies will be fetched. + * Defaults to the currently open URL. + * + * @return {Array} + * Array of cookie objects. + */ + // https://cs.chromium.org/chromium/src/content/browser/devtools/protocol/network_handler.cc?type=cs&q=+ComputeCookieURLs&sq=package:chromium&g=0&l=1115 + async getCookies(options = {}) { + // Bug 1605354 - Add support for options.urls + const urls = [this.session.target.url]; + + const cookies = []; + for (let url of urls) { + url = new URL(url); + + const secureProtocol = ["https:", "wss:"].includes(url.protocol); + + const cookiesFound = Services.cookies.getCookiesWithOriginAttributes( + JSON.stringify({}), + url.hostname + ); + + for (const cookie of cookiesFound) { + // Reject secure cookies for non-secure protocols + if (cookie.isSecure && !secureProtocol) { + continue; + } + + // Reject cookies which do not match the given path + if (!url.pathname.startsWith(cookie.path)) { + continue; + } + + const data = { + name: cookie.name, + value: cookie.value, + domain: cookie.host, + path: cookie.path, + expires: cookie.isSession ? -1 : cookie.expiry, + // The size is the combined length of both the cookie name and value + size: cookie.name.length + cookie.value.length, + httpOnly: cookie.isHttpOnly, + secure: cookie.isSecure, + session: cookie.isSession, + }; + + if (cookie.sameSite) { + const sameSiteMap = new Map([ + [Ci.nsICookie.SAMESITE_LAX, "Lax"], + [Ci.nsICookie.SAMESITE_STRICT, "Strict"], + ]); + + data.sameSite = sameSiteMap.get(cookie.sameSite); + } + + cookies.push(data); + } + } + + return { cookies }; + } + /** * Allows overriding user agent with the given string. * diff --git a/remote/test/browser/network/browser.ini b/remote/test/browser/network/browser.ini index 59c1070d39e7..beccebc78db7 100644 --- a/remote/test/browser/network/browser.ini +++ b/remote/test/browser/network/browser.ini @@ -3,8 +3,12 @@ tags = remote subsuite = remote prefs = remote.enabled=true support-files = + !/remote/test/browser/chrome-remote-interface.js + !/remote/test/browser/head.js + head.js doc_requestWillBeSent.html file_requestWillBeSent.js - head.js + sjs-cookies.sjs +[browser_getCookies.js] [browser_requestWillBeSent.js] diff --git a/remote/test/browser/network/browser_getCookies.js b/remote/test/browser/network/browser_getCookies.js new file mode 100644 index 000000000000..09f892a5f22f --- /dev/null +++ b/remote/test/browser/network/browser_getCookies.js @@ -0,0 +1,244 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const SJS_PATH = "/browser/remote/test/browser/network/sjs-cookies.sjs"; + +const DEFAULT_HOST = "http://example.org"; +const ALT_HOST = "http://example.net"; +const SECURE_HOST = "https://example.com"; + +const DEFAULT_URL = `${DEFAULT_HOST}${SJS_PATH}`; + +add_task(async function noCookiesWhenNoneAreSet({ Network }) { + const { cookies } = await Network.getCookies({ urls: [DEFAULT_HOST] }); + is(cookies.length, 0, "No cookies have been found"); +}); + +add_task(async function noCookiesForPristineContext({ Network }) { + await loadURL(DEFAULT_URL); + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 0, "No cookies have been found"); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function allCookiesFromHostWithPort({ Network }) { + const PORT_URL = `${DEFAULT_HOST}:8000${SJS_PATH}?name=id&value=1`; + await loadURL(PORT_URL); + + const cookie = { + name: "id", + value: "1", + }; + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 1, "All cookies have been found"); + assertCookie(cookies[0], cookie); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function allCookiesFromCurrentURL({ Network }) { + await loadURL(`${ALT_HOST}${SJS_PATH}?name=user&value=password`); + await loadURL(`${DEFAULT_URL}?name=foo&value=bar`); + await loadURL(`${DEFAULT_URL}?name=user&value=password`); + + const cookie1 = { name: "foo", value: "bar", domain: "example.org" }; + const cookie2 = { name: "user", value: "password", domain: "example.org" }; + + try { + const { cookies } = await Network.getCookies(); + cookies.sort((a, b) => a.name.localeCompare(b.name)); + is(cookies.length, 2, "All cookies have been found"); + assertCookie(cookies[0], cookie1); + assertCookie(cookies[1], cookie2); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function secure({ Network }) { + await loadURL(`${SECURE_HOST}${SJS_PATH}?name=foo&value=bar&secure`); + + const cookie = { + name: "foo", + value: "bar", + domain: "example.com", + secure: true, + }; + + try { + // Cookie returned for secure protocols + let result = await Network.getCookies(); + is(result.cookies.length, 1, "The secure cookie has been found"); + assertCookie(result.cookies[0], cookie); + + // For unsecure protocols no secure cookies are returned + await loadURL(DEFAULT_URL); + result = await Network.getCookies(); + is(result.cookies.length, 0, "No secure cookies have been found"); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function expiry({ Network }) { + const date = new Date(); + date.setDate(date.getDate() + 3); + + const encodedDate = encodeURI(date.toUTCString()); + await loadURL(`${DEFAULT_URL}?name=foo&value=bar&expiry=${encodedDate}`); + + const cookie = { + name: "foo", + value: "bar", + expires: date, + session: false, + }; + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 1, "A single cookie has been found"); + assertCookie(cookies[0], cookie); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function session({ Network }) { + await loadURL(`${DEFAULT_URL}?name=foo&value=bar`); + + const cookie = { + name: "foo", + value: "bar", + expiry: -1, + session: true, + }; + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 1, "A single cookie has been found"); + assertCookie(cookies[0], cookie); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function path({ Network }) { + const PATH = "/browser/remote/test/browser/"; + const PARENT_PATH = "/browser/remote/test/"; + + await loadURL(`${DEFAULT_URL}?name=foo&value=bar&path=${PATH}`); + + const cookie = { + name: "foo", + value: "bar", + path: PATH, + }; + + try { + console.log("Check exact path"); + await loadURL(`${DEFAULT_HOST}${PATH}`); + let result = await Network.getCookies(); + is(result.cookies.length, 1, "A single cookie has been found"); + assertCookie(result.cookies[0], cookie); + + console.log("Check sub path"); + await loadURL(`${DEFAULT_HOST}${SJS_PATH}`); + result = await Network.getCookies(); + is(result.cookies.length, 1, "A single cookie has been found"); + assertCookie(result.cookies[0], cookie); + + console.log("Check parent path"); + await loadURL(`${DEFAULT_HOST}${PARENT_PATH}`); + result = await Network.getCookies(); + is(result.cookies.length, 0, "No cookies have been found"); + + console.log("Check non matching path"); + await loadURL(`${DEFAULT_HOST}/foo/bar`); + result = await Network.getCookies(); + is(result.cookies.length, 0, "No cookies have been found"); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function httpOnly({ Network }) { + await loadURL(`${DEFAULT_URL}?name=foo&value=bar&httpOnly`); + + const cookie = { + name: "foo", + value: "bar", + httpOnly: true, + }; + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 1, "A single cookie has been found"); + assertCookie(cookies[0], cookie); + } finally { + Services.cookies.removeAll(); + } +}); + +add_task(async function sameSite({ Network }) { + for (const value of ["Lax", "Strict"]) { + console.log(`Test cookie with sameSite=${value}`); + await loadURL(`${DEFAULT_URL}?name=foo&value=bar&sameSite=${value}`); + + const cookie = { + name: "foo", + value: "bar", + sameSite: value, + }; + + try { + const { cookies } = await Network.getCookies(); + is(cookies.length, 1, "A single cookie has been found"); + assertCookie(cookies[0], cookie); + } finally { + Services.cookies.removeAll(); + } + } +}); + +function assertCookie(cookie, expected = {}) { + const { + name = "", + value = "", + domain = "example.org", + path = "/", + expires = -1, + size = name.length + value.length, + httpOnly = false, + secure = false, + session = true, + sameSite, + } = expected; + + const expectedCookie = { + name, + value, + domain, + path, + // If expires is set, convert from milliseconds to seconds + expires: expires > 0 ? Math.floor(expires.getTime() / 1000) : -1, + size, + httpOnly, + secure, + session, + }; + + if (sameSite) { + expectedCookie.sameSite = sameSite; + } + + Assert.deepEqual(cookie, expectedCookie); +} diff --git a/remote/test/browser/network/sjs-cookies.sjs b/remote/test/browser/network/sjs-cookies.sjs new file mode 100644 index 000000000000..345a66880d5c --- /dev/null +++ b/remote/test/browser/network/sjs-cookies.sjs @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// eslint-disable-next-line mozilla/reject-importGlobalProperties +Cu.importGlobalProperties(["URLSearchParams"]); + +function handleRequest(request, response) { + const queryString = new URLSearchParams(request.queryString); + + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + + if (queryString.has("name") && queryString.has("value")) { + const name = queryString.get("name"); + const value = queryString.get("value"); + const path = queryString.get("path") || "/"; + + const expiry = queryString.get("expiry"); + const httpOnly = queryString.has("httpOnly"); + const secure = queryString.has("secure"); + const sameSite = queryString.get("sameSite"); + + let cookie = `${name}=${value}; Path=${path}`; + + if (expiry) { + cookie += `; Expires=${expiry}`; + } + + if (httpOnly) { + cookie += "; HttpOnly"; + } + + if (sameSite != undefined) { + cookie += `; sameSite=${sameSite}`; + } + + if (secure) { + cookie += "; Secure"; + } + + response.setHeader("Set-Cookie", cookie, true); + response.write(`Set cookie: ${cookie}`); + } +} From 4072abcd72f73bc2441817b1f3f45b2fe16ef3c9 Mon Sep 17 00:00:00 2001 From: Bryan Kok Date: Wed, 18 Dec 2019 10:12:15 +0000 Subject: [PATCH 16/83] Bug 1589908 - The Worker name should be reflected in the threads pane r=bhackett Differential Revision: https://phabricator.services.mozilla.com/D52444 --HG-- extra : moz-landing-system : lando --- devtools/client/debugger/src/client/firefox/create.js | 4 +++- devtools/client/debugger/src/client/firefox/types.js | 1 + devtools/server/actors/targets/worker.js | 4 +++- devtools/server/connectors/worker-connector.js | 1 + devtools/server/startup/worker.js | 1 + devtools/shared/fronts/targets/worker.js | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/devtools/client/debugger/src/client/firefox/create.js b/devtools/client/debugger/src/client/firefox/create.js index 06ba93ff2612..fa21e65a553e 100644 --- a/devtools/client/debugger/src/client/firefox/create.js +++ b/devtools/client/debugger/src/client/firefox/create.js @@ -97,7 +97,9 @@ export function createThread(actor: string, target: Target): Thread { actor, url: target.url, type: getTargetType(target), - name: target.name, + name: target.isWorkerTarget + ? target.workerName || target.name + : target.name, serviceWorkerStatus: target.debuggerServiceWorkerStatus, }; } diff --git a/devtools/client/debugger/src/client/firefox/types.js b/devtools/client/debugger/src/client/firefox/types.js index 86c78cff22cc..9131ba88302c 100644 --- a/devtools/client/debugger/src/client/firefox/types.js +++ b/devtools/client/debugger/src/client/firefox/types.js @@ -195,6 +195,7 @@ export type Target = { destroy: () => void, threadFront: ThreadFront, name: string, + workerName?: string, isBrowsingContext: boolean, isContentProcess: boolean, isWorkerTarget: boolean, diff --git a/devtools/server/actors/targets/worker.js b/devtools/server/actors/targets/worker.js index b7a52837780e..ac2dea4f3cac 100644 --- a/devtools/server/actors/targets/worker.js +++ b/devtools/server/actors/targets/worker.js @@ -125,13 +125,15 @@ const WorkerTargetActor = protocol.ActorClassWithSpec(workerTargetSpec, { } return connectToWorker(this.conn, this._dbg, this.actorID, options).then( - ({ threadActor, transport, consoleActor }) => { + ({ workerName, threadActor, transport, consoleActor }) => { + this._workerName = workerName; this._threadActor = threadActor; this._transport = transport; this._consoleActor = consoleActor; return { type: "connected", + workerName: this._workerName, threadActor: this._threadActor, consoleActor: this._consoleActor, }; diff --git a/devtools/server/connectors/worker-connector.js b/devtools/server/connectors/worker-connector.js index ff884f7a4de7..9119533fe787 100644 --- a/devtools/server/connectors/worker-connector.js +++ b/devtools/server/connectors/worker-connector.js @@ -156,6 +156,7 @@ function connectToWorker(connection, dbg, id, options) { connection.setForwarding(id, transport); resolve({ + workerName: message.workerName, threadActor: message.threadActor, consoleActor: message.consoleActor, transport: transport, diff --git a/devtools/server/startup/worker.js b/devtools/server/startup/worker.js index b53736d7a173..770997499576 100644 --- a/devtools/server/startup/worker.js +++ b/devtools/server/startup/worker.js @@ -123,6 +123,7 @@ this.addEventListener("message", function(event) { JSON.stringify({ type: "connected", id: packet.id, + workerName: consoleActor.evaluateJS({ text: "self.name" }).result, threadActor: threadActor.actorID, consoleActor: consoleActor.actorID, }) diff --git a/devtools/shared/fronts/targets/worker.js b/devtools/shared/fronts/targets/worker.js index fa9f5e60c50a..1b3157f3300d 100644 --- a/devtools/shared/fronts/targets/worker.js +++ b/devtools/shared/fronts/targets/worker.js @@ -78,6 +78,7 @@ class WorkerTargetFront extends TargetMixin( const connectResponse = await this.connect({}); // Set the console actor ID on the form to expose it to Target.attachConsole // Set the ThreadActor on the target form so it is accessible by getFront + this.workerName = connectResponse.workerName; this.targetForm.consoleActor = connectResponse.consoleActor; this.targetForm.threadActor = connectResponse.threadActor; this._threadActor = connectResponse.threadActor; From f5fb2ad06de220bf374aadd8051750d4da5215ca Mon Sep 17 00:00:00 2001 From: Dan Mosedale Date: Fri, 20 Dec 2019 18:54:16 +0000 Subject: [PATCH 17/83] Bug 1605235 - Update node/npm to 8.17.0/6.13.4, r=Mardak Differential Revision: https://phabricator.services.mozilla.com/D57886 --HG-- extra : moz-landing-system : lando --- browser/components/newtab/.nvmrc | 2 +- browser/components/newtab/.travis.yml | 2 +- browser/components/newtab/package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/browser/components/newtab/.nvmrc b/browser/components/newtab/.nvmrc index 9fad72fcf21f..29d3fcd5549c 100644 --- a/browser/components/newtab/.nvmrc +++ b/browser/components/newtab/.nvmrc @@ -1 +1 @@ -8.16 +8.17.0 diff --git a/browser/components/newtab/.travis.yml b/browser/components/newtab/.travis.yml index ad28b0809190..4053997f1b8d 100644 --- a/browser/components/newtab/.travis.yml +++ b/browser/components/newtab/.travis.yml @@ -2,7 +2,7 @@ language: node_js node_js: # when changing this, be sure to edit .nvrmc and package.json too - - 8 + - 8.17.* python: - "2.7" diff --git a/browser/components/newtab/package.json b/browser/components/newtab/package.json index b4f2463e0bad..23899037dd43 100644 --- a/browser/components/newtab/package.json +++ b/browser/components/newtab/package.json @@ -77,8 +77,8 @@ "engines": { "firefox": ">=45.0 <=*", "//": "when changing node versions, also edit .travis.yml and .nvmrc", - "node": "8.*", - "npm": "6.9" + "node": ">=8.17.0 <9.0", + "npm": "6.13.4" }, "homepage": "https://github.com/mozilla/activity-stream", "keywords": [ From f9f8b6c9064ef7e4839fd0fb56f6c58898275280 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Thu, 19 Dec 2019 02:35:57 +0000 Subject: [PATCH 18/83] Bug 1597765 - support auto scroll in out of process frames r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D54596 --HG-- rename : toolkit/modules/AutoScrollController.jsm => toolkit/actors/AutoScrollChild.jsm extra : moz-landing-system : lando --- .../AutoScrollChild.jsm} | 113 ++++++++++++------ toolkit/actors/AutoScrollParent.jsm | 33 +++++ toolkit/actors/moz.build | 5 + toolkit/content/browser-content.js | 27 +---- .../browser_bug295977_autoscroll_overflow.js | 53 ++++++-- .../content/widgets/browser-custom-element.js | 80 +++++++------ toolkit/modules/ActorManagerParent.jsm | 15 +++ toolkit/modules/moz.build | 4 - 8 files changed, 215 insertions(+), 115 deletions(-) rename toolkit/{modules/AutoScrollController.jsm => actors/AutoScrollChild.jsm} (77%) create mode 100644 toolkit/actors/AutoScrollParent.jsm diff --git a/toolkit/modules/AutoScrollController.jsm b/toolkit/actors/AutoScrollChild.jsm similarity index 77% rename from toolkit/modules/AutoScrollController.jsm rename to toolkit/actors/AutoScrollChild.jsm index 169950a9f18b..668ac754daff 100644 --- a/toolkit/modules/AutoScrollController.jsm +++ b/toolkit/actors/AutoScrollChild.jsm @@ -5,10 +5,12 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); -var EXPORTED_SYMBOLS = ["AutoScrollController"]; +var EXPORTED_SYMBOLS = ["AutoScrollChild"]; + +class AutoScrollChild extends JSWindowActorChild { + constructor() { + super(); -class AutoScrollController { - constructor(global) { this._scrollable = null; this._scrolldir = ""; this._startX = null; @@ -18,10 +20,9 @@ class AutoScrollController { this._lastFrame = null; this._autoscrollHandledByApz = false; this._scrollId = null; - this._global = global; - this.autoscrollLoop = this.autoscrollLoop.bind(this); - global.addMessageListener("Autoscroll:Stop", this); + this.observer = new AutoScrollObserver(this); + this.autoscrollLoop = this.autoscrollLoop.bind(this); } isAutoscrollBlocker(node) { @@ -145,16 +146,22 @@ class AutoScrollController { this._scrolldir = direction; this._scrollable = aNode.ownerGlobal; } else if (aNode.ownerGlobal.frameElement) { - // FIXME(emilio): This won't work with Fission. + // Note, in case of out of process iframes frameElement is null, and + // a caller is supposed to communicate to iframe's parent on its own to + // support cross process scrolling. this.findNearestScrollableElement(aNode.ownerGlobal.frameElement); } } } - startScroll(event) { + async startScroll(event) { this.findNearestScrollableElement(event.originalTarget); - if (!this._scrollable) { + this.sendAsyncMessage("Autoscroll:MaybeStartInParent", { + browsingContextId: this.browsingContext.id, + screenX: event.screenX, + screenY: event.screenY, + }); return; } @@ -180,20 +187,23 @@ class AutoScrollController { // No view ID - leave this._scrollId as null. Receiving side will check. } let presShellId = domUtils.getPresShellId(); - let [result] = this._global.sendSyncMessage("Autoscroll:Start", { - scrolldir: this._scrolldir, - screenX: event.screenX, - screenY: event.screenY, - scrollId: this._scrollId, - presShellId, - }); - if (!result.autoscrollEnabled) { + let { autoscrollEnabled, usingApz } = await this.sendQuery( + "Autoscroll:Start", + { + scrolldir: this._scrolldir, + screenX: event.screenX, + screenY: event.screenY, + scrollId: this._scrollId, + presShellId, + } + ); + if (!autoscrollEnabled) { this._scrollable = null; return; } - Services.els.addSystemEventListener(this._global, "mousemove", this, true); - this._global.addEventListener("pagehide", this, true); + Services.els.addSystemEventListener(this.document, "mousemove", this, true); + this.document.addEventListener("pagehide", this, true); this._ignoreMouseEvents = true; this._startX = event.screenX; @@ -202,9 +212,9 @@ class AutoScrollController { this._screenY = event.screenY; this._scrollErrorX = 0; this._scrollErrorY = 0; - this._autoscrollHandledByApz = result.usingApz; + this._autoscrollHandledByApz = usingApz; - if (!result.usingApz) { + if (!usingApz) { // If the browser didn't hand the autoscroll off to APZ, // scroll here in the main thread. this.startMainThreadScroll(); @@ -212,12 +222,16 @@ class AutoScrollController { // Even if the browser did hand the autoscroll to APZ, // APZ might reject it in which case it will notify us // and we need to take over. - Services.obs.addObserver(this, "autoscroll-rejected-by-apz"); + Services.obs.addObserver(this.observer, "autoscroll-rejected-by-apz"); + } + + if (Cu.isInAutomation) { + Services.obs.notifyObservers(content, "autoscroll-start"); } } startMainThreadScroll() { - let content = this._global.content; + let content = this.document.defaultView; this._lastFrame = content.performance.now(); content.requestAnimationFrame(this.autoscrollLoop); } @@ -228,14 +242,17 @@ class AutoScrollController { this._scrollable = null; Services.els.removeSystemEventListener( - this._global, + this.document, "mousemove", this, true ); - this._global.removeEventListener("pagehide", this, true); + this.document.removeEventListener("pagehide", this, true); if (this._autoscrollHandledByApz) { - Services.obs.removeObserver(this, "autoscroll-rejected-by-apz"); + Services.obs.removeObserver( + this.observer, + "autoscroll-rejected-by-apz" + ); } } } @@ -306,6 +323,8 @@ class AutoScrollController { this._screenY = event.screenY; } else if (event.type == "mousedown") { if ( + event.isTrusted & !event.defaultPrevented && + event.button == 1 && !this._scrollable && !this.isAutoscrollBlocker(event.originalTarget) ) { @@ -315,14 +334,28 @@ class AutoScrollController { if (this._scrollable) { var doc = this._scrollable.ownerDocument || this._scrollable.document; if (doc == event.target) { - this._global.sendAsyncMessage("Autoscroll:Cancel"); + this.sendAsyncMessage("Autoscroll:Cancel"); + this.stopScroll(); } } } } receiveMessage(msg) { + let data = msg.data; switch (msg.name) { + case "Autoscroll:MaybeStart": + for (let child of this.browsingContext.getChildren()) { + if (data.browsingContextId == child.id) { + this.startScroll({ + screenX: data.screenX, + screenY: data.screenY, + originalTarget: child.embedderElement, + }); + break; + } + } + break; case "Autoscroll:Stop": { this.stopScroll(); break; @@ -330,14 +363,24 @@ class AutoScrollController { } } - observe(subject, topic, data) { - if (topic === "autoscroll-rejected-by-apz") { - // The caller passes in the scroll id via 'data'. - if (data == this._scrollId) { - this._autoscrollHandledByApz = false; - this.startMainThreadScroll(); - Services.obs.removeObserver(this, "autoscroll-rejected-by-apz"); - } + rejectedByApz(data) { + // The caller passes in the scroll id via 'data'. + if (data == this._scrollId) { + this._autoscrollHandledByApz = false; + this.startMainThreadScroll(); + Services.obs.removeObserver(this.observer, "autoscroll-rejected-by-apz"); + } + } +} + +class AutoScrollObserver { + constructor(actor) { + this.actor = actor; + } + + observe(subject, topic, data) { + if (topic === "autoscroll-rejected-by-apz") { + this.actor.rejectedByApz(data); } } } diff --git a/toolkit/actors/AutoScrollParent.jsm b/toolkit/actors/AutoScrollParent.jsm new file mode 100644 index 000000000000..f5e6b7b8c397 --- /dev/null +++ b/toolkit/actors/AutoScrollParent.jsm @@ -0,0 +1,33 @@ +/* vim: set ts=2 sw=2 sts=2 et 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 http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var EXPORTED_SYMBOLS = ["AutoScrollParent"]; + +class AutoScrollParent extends JSWindowActorParent { + receiveMessage(msg) { + let browser = this.manager.browsingContext.top.embedderElement; + if (!browser) { + return null; + } + + let data = msg.data; + switch (msg.name) { + case "Autoscroll:Start": + return Promise.resolve(browser.startScroll(data)); + case "Autoscroll:MaybeStartInParent": + let parent = this.browsingContext.parent; + if (parent) { + let actor = parent.currentWindowGlobal.getActor("AutoScroll"); + actor.sendAsyncMessage("Autoscroll:MaybeStart", data); + } + break; + case "Autoscroll:Cancel": + browser.cancelScroll(); + break; + } + return null; + } +} diff --git a/toolkit/actors/moz.build b/toolkit/actors/moz.build index 6b3f0579ad95..21796cde957f 100644 --- a/toolkit/actors/moz.build +++ b/toolkit/actors/moz.build @@ -7,6 +7,9 @@ with Files('**'): BUG_COMPONENT = ('Toolkit', 'General') +with Files('AutoScroll*.jsm'): + BUG_COMPONENT = ('Core', 'Panning and Zooming') + with Files('Finder*.jsm'): BUG_COMPONENT = ('Toolkit', 'Find Toolbar') @@ -25,6 +28,8 @@ FINAL_TARGET_FILES.actors += [ 'AutoCompleteParent.jsm', 'AutoplayChild.jsm', 'AutoplayParent.jsm', + 'AutoScrollChild.jsm', + 'AutoScrollParent.jsm', 'BrowserElementChild.jsm', 'BrowserElementParent.jsm', 'ControllersChild.jsm', diff --git a/toolkit/content/browser-content.js b/toolkit/content/browser-content.js index 307ffedc6370..7b4af1c1828d 100644 --- a/toolkit/content/browser-content.js +++ b/toolkit/content/browser-content.js @@ -6,34 +6,11 @@ /* eslint-env mozilla/frame-script */ /* eslint no-unused-vars: ["error", {args: "none"}] */ +/* exported Services */ var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + var { ActorManagerChild } = ChromeUtils.import( "resource://gre/modules/ActorManagerChild.jsm" ); ActorManagerChild.attach(this); - -ChromeUtils.defineModuleGetter( - this, - "AutoScrollController", - "resource://gre/modules/AutoScrollController.jsm" -); - -var global = this; - -var AutoScrollListener = { - handleEvent(event) { - if (event.isTrusted & !event.defaultPrevented && event.button == 1) { - if (!this._controller) { - this._controller = new AutoScrollController(global); - } - this._controller.handleEvent(event); - } - }, -}; -Services.els.addSystemEventListener( - global, - "mousedown", - AutoScrollListener, - true -); diff --git a/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js b/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js index b4746bc43141..18a54e72bcef 100644 --- a/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js +++ b/toolkit/content/tests/browser/browser_bug295977_autoscroll_overflow.js @@ -160,6 +160,26 @@ body > div > div {width: 1000px;height: 1000px;}\ expected: expectScrollNone, testwindow: true, }, + { + // Test: scroll is initiated in out of process iframe having no scrollable area + dataUri: + "data:text/html," + + encodeURIComponent(` + + +
+ +
+
+ `), + }, + { + elem: "noscroll-outofprocess-iframe", + // We expect the div to scroll vertically, not the iframe's window. + expected: expectScrollVert, + scrollable: "scroller", + }, ]; for (let test of allTests) { @@ -187,19 +207,28 @@ body > div > div {width: 1000px;height: 1000px;}\ // This ensures bug 605127 is fixed: pagehide in an unrelated document // should not cancel the autoscroll. - await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() { - var iframe = content.document.getElementById("iframe"); + await ContentTask.spawn( + gBrowser.selectedBrowser, + { waitForAutoScrollStart: test.expected != expectScrollNone }, + async ({ waitForAutoScrollStart }) => { + var iframe = content.document.getElementById("iframe"); - if (iframe) { - var e = new iframe.contentWindow.PageTransitionEvent("pagehide", { - bubbles: true, - cancelable: true, - persisted: false, - }); - iframe.contentDocument.dispatchEvent(e); - iframe.contentDocument.documentElement.dispatchEvent(e); + if (iframe) { + var e = new iframe.contentWindow.PageTransitionEvent("pagehide", { + bubbles: true, + cancelable: true, + persisted: false, + }); + iframe.contentDocument.dispatchEvent(e); + iframe.contentDocument.documentElement.dispatchEvent(e); + } + if (waitForAutoScrollStart) { + await new Promise(resolve => + Services.obs.addObserver(resolve, "autoscroll-start") + ); + } } - }); + ); is( document.activeElement, @@ -265,7 +294,7 @@ body > div > div {width: 1000px;height: 1000px;}\ { scrollVert, scrollHori, - elemid: test.elem, + elemid: test.scrollable || test.elem, checkWindow: test.testwindow, }, ], diff --git a/toolkit/content/widgets/browser-custom-element.js b/toolkit/content/widgets/browser-custom-element.js index 8d8533d0b37c..4151095bd1d0 100644 --- a/toolkit/content/widgets/browser-custom-element.js +++ b/toolkit/content/widgets/browser-custom-element.js @@ -1344,8 +1344,6 @@ "PopupBlocking:UpdateBlockedPopups", this ); - this.messageManager.addMessageListener("Autoscroll:Start", this); - this.messageManager.addMessageListener("Autoscroll:Cancel", this); this.messageManager.addMessageListener( "UnselectedTabHover:Toggle", this @@ -1418,41 +1416,6 @@ this.updateBlockedPopups(); break; } - case "Autoscroll:Start": { - if (!this.autoscrollEnabled) { - return { autoscrollEnabled: false, usingApz: false }; - } - this.startScroll(data.scrolldir, data.screenX, data.screenY); - let usingApz = false; - if ( - this.isRemoteBrowser && - data.scrollId != null && - this.mPrefs.getBoolPref("apz.autoscroll.enabled", false) - ) { - let { remoteTab } = this.frameLoader; - if (remoteTab) { - // If APZ is handling the autoscroll, it may decide to cancel - // it of its own accord, so register an observer to allow it - // to notify us of that. - var os = Services.obs; - os.addObserver(this.observer, "apz:cancel-autoscroll", true); - - usingApz = remoteTab.startApzAutoscroll( - data.screenX, - data.screenY, - data.scrollId, - data.presShellId - ); - } - // Save the IDs for later - this._autoScrollScrollId = data.scrollId; - this._autoScrollPresShellId = data.presShellId; - } - return { autoscrollEnabled: true, usingApz }; - } - case "Autoscroll:Cancel": - this._autoScrollPopup.hidePopup(); - break; case "UnselectedTabHover:Toggle": this._shouldSendUnselectedTabHover = data.enable ? ++this._unselectedTabHoverMessageListenerCount > 0 @@ -1659,7 +1622,8 @@ window.removeEventListener("keydown", this, true); window.removeEventListener("keypress", this, true); window.removeEventListener("keyup", this, true); - this.messageManager.sendAsyncMessage("Autoscroll:Stop"); + + this.sendMessageToActor("Autoscroll:Stop", {}, "AutoScroll", true); try { Services.obs.removeObserver(this.observer, "apz:cancel-autoscroll"); @@ -1690,7 +1654,11 @@ return popup; } - startScroll(scrolldir, screenX, screenY) { + startScroll({ scrolldir, screenX, screenY, scrollId, presShellId }) { + if (!this.autoscrollEnabled) { + return { autoscrollEnabled: false, usingApz: false }; + } + const POPUP_SIZE = 32; if (!this._autoScrollPopup) { if (this.hasAttribute("autoscrollpopup")) { @@ -1772,6 +1740,40 @@ window.addEventListener("keydown", this, true); window.addEventListener("keypress", this, true); window.addEventListener("keyup", this, true); + + let usingApz = false; + if ( + this.isRemoteBrowser && + scrollId != null && + this.mPrefs.getBoolPref("apz.autoscroll.enabled", false) + ) { + let { remoteTab } = this.frameLoader; + if (remoteTab) { + // If APZ is handling the autoscroll, it may decide to cancel + // it of its own accord, so register an observer to allow it + // to notify us of that. + Services.obs.addObserver( + this.observer, + "apz:cancel-autoscroll", + true + ); + + usingApz = remoteTab.startApzAutoscroll( + screenX, + screenY, + scrollId, + presShellId + ); + } + // Save the IDs for later + this._autoScrollScrollId = scrollId; + this._autoScrollPresShellId = presShellId; + } + return { autoscrollEnabled: true, usingApz }; + } + + cancelScroll() { + this._autoScrollPopup.hidePopup(); } handleEvent(aEvent) { diff --git a/toolkit/modules/ActorManagerParent.jsm b/toolkit/modules/ActorManagerParent.jsm index 4e42c19d138a..745578d7cbcf 100644 --- a/toolkit/modules/ActorManagerParent.jsm +++ b/toolkit/modules/ActorManagerParent.jsm @@ -90,6 +90,21 @@ let ACTORS = { allFrames: true, }, + AutoScroll: { + parent: { + moduleURI: "resource://gre/actors/AutoScrollParent.jsm", + }, + + child: { + moduleURI: "resource://gre/actors/AutoScrollChild.jsm", + events: { + mousedown: { capture: true, mozSystemGroup: true }, + }, + }, + + allFrames: true, + }, + BrowserElement: { parent: { moduleURI: "resource://gre/actors/BrowserElementParent.jsm", diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build index 19d8edd95f1c..20ac4bab65b3 100644 --- a/toolkit/modules/moz.build +++ b/toolkit/modules/moz.build @@ -48,9 +48,6 @@ with Files('tests/xpcshell/test_UpdateUtils*.js'): with Files('AsyncPrefs.jsm'): BUG_COMPONENT = ('Core', 'Security: Process Sandboxing') -with Files('AutoScrollController.jsm'): - BUG_COMPONENT = ('Core', 'Panning and Zooming') - with Files('CharsetMenu.jsm'): BUG_COMPONENT = ('Firefox', 'Toolbars and Customization') @@ -165,7 +162,6 @@ EXTRA_JS_MODULES += [ 'ActorManagerParent.jsm', 'AppMenuNotifications.jsm', 'AsyncPrefs.jsm', - 'AutoScrollController.jsm', 'BinarySearch.jsm', 'BrowserUtils.jsm', 'CanonicalJSON.jsm', From a0c9590371a7193dfc3c821ed3d340df76072e88 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Fri, 20 Dec 2019 19:27:40 +0000 Subject: [PATCH 19/83] Bug 1603272: List installed site specific browsers in the app menu. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D57015 --HG-- extra : moz-landing-system : lando --- browser/base/content/browser.js | 110 ++++++++++++++++++ .../customizableui/content/panelUI.inc.xhtml | 12 ++ browser/components/ssb/ImageTools.jsm | 57 +++++++++ .../ssb/SiteSpecificBrowserService.jsm | 32 +++++ browser/components/ssb/content/ssb.js | 2 +- .../components/ssb/tests/browser/browser.ini | 1 + .../ssb/tests/browser/browser_ssb_lasttab.js | 8 +- .../tests/browser/browser_ssb_list_menu.js | 67 +++++++++++ .../browser/browser_ssb_manifest_scope.js | 17 +-- .../ssb/tests/browser/browser_ssb_open.js | 7 +- browser/components/ssb/tests/browser/head.js | 55 ++++++--- 11 files changed, 336 insertions(+), 32 deletions(-) create mode 100644 browser/components/ssb/tests/browser/browser_ssb_list_menu.js diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 6c023eed989e..5d818a54e4ac 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -69,6 +69,9 @@ XPCOMUtils.defineLazyModuleGetters(this, { SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm", SiteDataManager: "resource:///modules/SiteDataManager.jsm", SitePermissions: "resource:///modules/SitePermissions.jsm", + SiteSpecificBrowser: "resource:///modules/SiteSpecificBrowserService.jsm", + SiteSpecificBrowserService: + "resource:///modules/SiteSpecificBrowserService.jsm", TabModalPrompt: "chrome://global/content/tabprompts.jsm", TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm", TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm", @@ -1975,6 +1978,8 @@ var gBrowserInit = { FullZoom.init(); PanelUI.init(); + SiteSpecificBrowserUI.init(); + UpdateUrlbarSearchSplitterState(); BookmarkingUI.init(); @@ -2522,6 +2527,111 @@ gBrowserInit.idleTasksFinishedPromise = new Promise(resolve => { gBrowserInit.idleTaskPromiseResolve = resolve; }); +const SiteSpecificBrowserUI = { + menuInitialized: false, + + init() { + if (!SiteSpecificBrowserService.isEnabled) { + return; + } + + XPCOMUtils.defineLazyGetter(this, "panelBody", () => { + return document.querySelector("#appMenu-SSBView .panel-subview-body"); + }); + + let initializeMenu = async () => { + let list = await SiteSpecificBrowserService.list(); + + for (let ssb of list) { + this.addSSBToMenu(ssb); + } + + if (!list.length) { + document.getElementById("appMenu-ssb-button").hidden = true; + } + + this.menuInitialized = true; + }; + + document.getElementById("appMenu-popup").addEventListener( + "popupshowing", + () => { + let blocker = initializeMenu(); + document.getElementById("appMenu-SSBView").addEventListener( + "ViewShowing", + event => { + event.detail.addBlocker(blocker); + }, + { once: true } + ); + }, + { once: true } + ); + + Services.obs.addObserver(this, "site-specific-browser-install", true); + Services.obs.addObserver(this, "site-specific-browser-uninstall", true); + }, + + observe(subject, topic, id) { + if (!this.menuInitialized) { + return; + } + + let ssb = SiteSpecificBrowser.get(id); + switch (topic) { + case "site-specific-browser-install": + this.addSSBToMenu(ssb); + break; + case "site-specific-browser-uninstall": + this.removeSSBFromMenu(ssb); + break; + } + }, + + removeSSBFromMenu(ssb) { + let button = document.getElementById("ssb-button-" + ssb.id); + if (!button) { + return; + } + + if (!button.nextElementSibling && !button.previousElementSibling) { + document.getElementById("appMenu-ssb-button").hidden = true; + } + + let uri = button.getAttribute("image"); + if (uri) { + URL.revokeObjectURL(uri); + } + + button.remove(); + }, + + addSSBToMenu(ssb) { + let menu = document.createXULElement("toolbarbutton"); + menu.id = "ssb-button-" + ssb.id; + menu.className = "subviewbutton subviewbutton-iconic"; + menu.setAttribute("label", ssb.name); + + ssb.getScaledIcon(16 * devicePixelRatio).then( + icon => { + menu.setAttribute("image", URL.createObjectURL(icon)); + }, + error => { + console.error(error); + } + ); + + menu.addEventListener("command", () => { + ssb.launch(); + }); + + this.panelBody.append(menu); + document.getElementById("appMenu-ssb-button").hidden = false; + }, + + QueryInterface: ChromeUtils.generateQI([Ci.nsISupportsWeakReference]), +}; + function HandleAppCommandEvent(evt) { switch (evt.command) { case "Back": diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml index 971b6804aad9..6a652d6d1433 100644 --- a/browser/components/customizableui/content/panelUI.inc.xhtml +++ b/browser/components/customizableui/content/panelUI.inc.xhtml @@ -355,6 +355,12 @@ key="key_openAddons" command="Tools:Addons" /> +