Commits:
-
28d2f8a6
by Marcin Koziński at 2026-08-16T00:43:28+02:00
Bug 1978587 - Forward onEnterAnimationComplete to interested fragments r=android-reviewers,twhite
Differential Revision: https://phabricator.services.mozilla.com/D306954
-
cc401020
by Harveer Singh at 2026-08-16T00:43:29+02:00
Bug 2025732: Increase Cache API opaque response padding. a=RyanVM DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D313509
Differential Revision: https://phabricator.services.mozilla.com/D315608
-
1f1e6dc7
by Rob Wu at 2026-08-16T00:43:29+02:00
Bug 2045676 - Gracefully handle broken files in verifyBundleSignedState a=RyanVM DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D305180
Differential Revision: https://phabricator.services.mozilla.com/D315593
-
2d64ea04
by Lee Salzman at 2026-08-16T00:43:30+02:00
Bug 2045711. a=diannaS
Original Revision: https://phabricator.services.mozilla.com/D311733
Differential Revision: https://phabricator.services.mozilla.com/D312888
-
80ebdf97
by Jim Blandy at 2026-08-16T00:43:30+02:00
Bug 2045796: Saturate when rounding up pixman trapezoid edges. a=diannaS DONTBUILD
When rounding the edge coordinates of a non-antialised edge upwards,
use saturating addition, just in case the coordinates are close to the
limit of `pixman_fixed_t`'s range.
Original Revision: https://phabricator.services.mozilla.com/D314811
Differential Revision: https://phabricator.services.mozilla.com/D317287
-
8848a3c2
by Karl Tomlinson at 2026-08-17T08:29:53+02:00
Bug 2050380 Make shared memory transfer conditional on IsSharedMemoryAllowed() a=diannaS DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D312653
Differential Revision: https://phabricator.services.mozilla.com/D313366
-
34762463
by Andrea Marchesini at 2026-08-17T08:42:39+02:00
Bug 2048353 - Improve worker shutdown support in CookieStoreNotificationWatcher a=diannaS DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D311765
Differential Revision: https://phabricator.services.mozilla.com/D314995
-
047e6deb
by Henri Sivonen at 2026-08-17T08:50:18+02:00
Bug 2053153 - Only check for high surrogates when intending to avoid split pair. a=diannaS DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D314632
Differential Revision: https://phabricator.services.mozilla.com/D316466
-
993e59cd
by Olli Pettay at 2026-08-17T10:01:44+02:00
Bug 2054643, make button's EndSubmitClick handling consistent with input type=button, a=diannaS DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D315429
Differential Revision: https://phabricator.services.mozilla.com/D315956
-
c0635dbe
by Dimi at 2026-08-17T10:19:53+02:00
Bug 2054687 - Check iframe's parent matches the browsing context, a=diannaS DONTBUILD
Original Revision: https://phabricator.services.mozilla.com/D312950
Differential Revision: https://phabricator.services.mozilla.com/D313656
-
723477b9
by Lee Salzman at 2026-08-17T10:49:08+02:00
Bug 2060000. r=gfx-reviewers,nical, a=dsmith
Differential Revision: https://phabricator.services.mozilla.com/D315942
-
7017edb5
by Emilio Cobos Álvarez at 2026-08-17T10:51:23+02:00
Bug 2060048 - Force revalidation of Vary: cookie subresources. a=diannaS
I think this would fix the image, css, and script caches.
Original Revision: https://phabricator.services.mozilla.com/D315988
Differential Revision: https://phabricator.services.mozilla.com/D317319
22 changed files:
Changes:
dom/base/nsContentUtils.cpp
| ... |
... |
@@ -12196,6 +12196,23 @@ nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest, |
|
12196
|
12196
|
if (!info.mMustRevalidate) {
|
|
12197
|
12197
|
Unused << httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
|
|
12198
|
12198
|
}
|
|
|
12199
|
+
|
|
|
12200
|
+ if (!info.mMustRevalidate) {
|
|
|
12201
|
+ nsAutoCString vary;
|
|
|
12202
|
+ (void)httpChannel->GetResponseHeader("vary"_ns, vary);
|
|
|
12203
|
+ info.mMustRevalidate = [&] {
|
|
|
12204
|
+ for (const nsACString& token :
|
|
|
12205
|
+ nsCCharSeparatedTokenizer(vary, ',').ToRange()) {
|
|
|
12206
|
+ if (token.EqualsLiteral("*")) {
|
|
|
12207
|
+ return true;
|
|
|
12208
|
+ }
|
|
|
12209
|
+ if (token.EqualsIgnoreCase("cookie")) {
|
|
|
12210
|
+ return true;
|
|
|
12211
|
+ }
|
|
|
12212
|
+ }
|
|
|
12213
|
+ return false;
|
|
|
12214
|
+ }();
|
|
|
12215
|
+ }
|
|
12199
|
12216
|
}
|
|
12200
|
12217
|
|
|
12201
|
12218
|
// data: URIs are safe to cache across documents under any circumstance, so we
|
dom/cache/FileUtils.cpp
| ... |
... |
@@ -47,7 +47,7 @@ namespace { |
|
47
|
47
|
|
|
48
|
48
|
// Const variable for generate padding size.
|
|
49
|
49
|
// XXX This will be tweaked to something more meaningful in Bug 1383656.
|
|
50
|
|
-const int64_t kRoundUpNumber = 20480;
|
|
|
50
|
+const int64_t kRoundUpNumber = 131072;
|
|
51
|
51
|
|
|
52
|
52
|
// At the moment, the encrypted stream block size is assumed to be unchangeable
|
|
53
|
53
|
// between encrypting and decrypting blobs. This assumptions holds as long as we
|
dom/canvas/WebGLContextGL.cpp
| ... |
... |
@@ -1361,8 +1361,8 @@ void WebGLContext::UniformData( |
|
1361
|
1361
|
// -
|
|
1362
|
1362
|
|
|
1363
|
1363
|
const auto lengthInType = data.size();
|
|
1364
|
|
- const auto elemCount = lengthInType / channels;
|
|
1365
|
|
- if (elemCount > 1 && !validationInfo.isArray) {
|
|
|
1364
|
+ const size_t availElemCount = lengthInType / channels;
|
|
|
1365
|
+ if (availElemCount > 1 && !validationInfo.isArray) {
|
|
1366
|
1366
|
GenerateError(
|
|
1367
|
1367
|
LOCAL_GL_INVALID_OPERATION,
|
|
1368
|
1368
|
"(uniform %s) `values` length (%u) must exactly match size of %s.",
|
| ... |
... |
@@ -1370,6 +1370,10 @@ void WebGLContext::UniformData( |
|
1370
|
1370
|
EnumString(activeInfo.elemType).c_str());
|
|
1371
|
1371
|
return;
|
|
1372
|
1372
|
}
|
|
|
1373
|
+ const size_t elemCount =
|
|
|
1374
|
+ validationInfo.isArray
|
|
|
1375
|
+ ? std::min(availElemCount, size_t(activeInfo.elemCount))
|
|
|
1376
|
+ : availElemCount;
|
|
1373
|
1377
|
|
|
1374
|
1378
|
// -
|
|
1375
|
1379
|
|
dom/cookiestore/CookieStoreNotificationWatcherWrapper.cpp
| ... |
... |
@@ -99,13 +99,13 @@ void CookieStoreNotificationWatcherWrapper::ResolvePromiseWhenNotified( |
|
99
|
99
|
mEventTarget(GetCurrentSerialEventTarget()) {}
|
|
100
|
100
|
|
|
101
|
101
|
NS_IMETHOD Run() override {
|
|
102
|
|
- mPromise->MaybeResolveWithUndefined();
|
|
103
|
|
- mPromise = nullptr;
|
|
|
102
|
+ if (mPromise) {
|
|
|
103
|
+ mPromise->MaybeResolveWithUndefined();
|
|
|
104
|
+ mPromise = nullptr;
|
|
|
105
|
+ }
|
|
104
|
106
|
return NS_OK;
|
|
105
|
107
|
}
|
|
106
|
108
|
|
|
107
|
|
- bool HasPromise() const { return !!mPromise; }
|
|
108
|
|
-
|
|
109
|
109
|
private:
|
|
110
|
110
|
~PromiseResolver() {
|
|
111
|
111
|
NS_ProxyRelease(
|
| ... |
... |
@@ -140,10 +140,8 @@ void CookieStoreNotificationWatcherWrapper::ResolvePromiseWhenNotified( |
|
140
|
140
|
auto callback = [resolver = RefPtr(resolver),
|
|
141
|
141
|
eventTarget = RefPtr(GetCurrentSerialEventTarget()),
|
|
142
|
142
|
workerRef = RefPtr(workerRef)] {
|
|
143
|
|
- if (resolver->HasPromise()) {
|
|
144
|
|
- RefPtr<Runnable> runnable(resolver);
|
|
145
|
|
- eventTarget->Dispatch(runnable.forget());
|
|
146
|
|
- }
|
|
|
143
|
+ RefPtr<Runnable> runnable(resolver);
|
|
|
144
|
+ eventTarget->Dispatch(runnable.forget());
|
|
147
|
145
|
};
|
|
148
|
146
|
|
|
149
|
147
|
if (!NS_IsMainThread()) {
|
dom/fetch/InternalResponse.cpp
| ... |
... |
@@ -25,7 +25,7 @@ namespace { |
|
25
|
25
|
|
|
26
|
26
|
// Const variable for generate padding size
|
|
27
|
27
|
// XXX This will be tweaked to something more meaningful in Bug 1383656.
|
|
28
|
|
-const uint32_t kMaxRandomNumber = 102400;
|
|
|
28
|
+const uint32_t kMaxRandomNumber = 1048576;
|
|
29
|
29
|
|
|
30
|
30
|
} // namespace
|
|
31
|
31
|
|
dom/html/HTMLButtonElement.cpp
| ... |
... |
@@ -256,8 +256,8 @@ void EndSubmitClick(EventChainVisitor& aVisitor) { |
|
256
|
256
|
}
|
|
257
|
257
|
|
|
258
|
258
|
void HTMLButtonElement::ActivationBehavior(EventChainPostVisitor& aVisitor) {
|
|
|
259
|
+ auto endSubmit = MakeScopeExit([&] { EndSubmitClick(aVisitor); });
|
|
259
|
260
|
if (!aVisitor.mPresContext) {
|
|
260
|
|
- // Should check whether EndSubmitClick is needed here.
|
|
261
|
261
|
return;
|
|
262
|
262
|
}
|
|
263
|
263
|
|
dom/html/HTMLFormElement.cpp
| ... |
... |
@@ -817,6 +817,10 @@ nsresult HTMLFormElement::SubmitSubmission( |
|
817
|
817
|
return NS_OK;
|
|
818
|
818
|
}
|
|
819
|
819
|
|
|
|
820
|
+ if (doc->GetSandboxFlags() & SANDBOXED_FORMS) {
|
|
|
821
|
+ return NS_OK;
|
|
|
822
|
+ }
|
|
|
823
|
+
|
|
820
|
824
|
// _javascript_ URIs are not really submissions; they just call a function.
|
|
821
|
825
|
// Also, they may synchronously call submit(), and we want them to be able to
|
|
822
|
826
|
// do so while still disallowing other double submissions. (Bug 139798)
|
dom/media/webaudio/AudioWorkletNode.cpp
| ... |
... |
@@ -767,7 +767,10 @@ already_AddRefed<AudioWorkletNode> AudioWorkletNode::Constructor( |
|
767
|
767
|
// can share memory.
|
|
768
|
768
|
JS::CloneDataPolicy cloneDataPolicy;
|
|
769
|
769
|
cloneDataPolicy.allowIntraClusterClonableSharedObjects();
|
|
770
|
|
- cloneDataPolicy.allowSharedMemoryObjects();
|
|
|
770
|
+ nsIGlobalObject* currentGlobal = xpc::CurrentNativeGlobal(cx);
|
|
|
771
|
+ if (currentGlobal->IsSharedMemoryAllowed()) {
|
|
|
772
|
+ cloneDataPolicy.allowSharedMemoryObjects();
|
|
|
773
|
+ }
|
|
771
|
774
|
|
|
772
|
775
|
// StructuredCloneHolder does not have a move constructor. Instead allocate
|
|
773
|
776
|
// memory so that the pointer can be passed to the rendering thread.
|
gfx/cairo/README
| ... |
... |
@@ -63,3 +63,5 @@ pixman-export.patch: make sure pixman symbols are not exported in libxul |
|
63
|
63
|
pixman-interp.patch: use lower quality interpolation by default on mobile
|
|
64
|
64
|
|
|
65
|
65
|
pixman-rename.patch: include pixman-rename.h for renaming of external symbols
|
|
|
66
|
+
|
|
|
67
|
+pixman-edge-saturate.patch: Saturate when rounding up trapezoid edges |
gfx/cairo/cairo/src/cairo-truetype-subset.c
| ... |
... |
@@ -1451,13 +1451,22 @@ find_name (tt_name_t *name, unsigned long size, int name_id, int platform, int e |
|
1451
|
1451
|
{
|
|
1452
|
1452
|
tt_name_record_t *record;
|
|
1453
|
1453
|
unsigned int i, len;
|
|
|
1454
|
+ unsigned long max_records;
|
|
1454
|
1455
|
char *str;
|
|
1455
|
1456
|
char *p;
|
|
1456
|
1457
|
cairo_bool_t has_tag;
|
|
1457
|
1458
|
cairo_status_t status;
|
|
1458
|
1459
|
|
|
1459
|
1460
|
str = NULL;
|
|
1460
|
|
- for (i = 0; i < MIN(be16_to_cpu (name->num_records), size / sizeof(name->records[0])); i++) {
|
|
|
1461
|
+ /* records[] starts after the 6-byte tt_name_t header (format,
|
|
|
1462
|
+ * num_records, strings_offset); only records lying entirely within the
|
|
|
1463
|
+ * size-byte table may be read. */
|
|
|
1464
|
+ if (size < offsetof (tt_name_t, records)) {
|
|
|
1465
|
+ *str_out = NULL;
|
|
|
1466
|
+ return CAIRO_STATUS_SUCCESS;
|
|
|
1467
|
+ }
|
|
|
1468
|
+ max_records = (size - offsetof (tt_name_t, records)) / sizeof(name->records[0]);
|
|
|
1469
|
+ for (i = 0; i < MIN(be16_to_cpu (name->num_records), max_records); i++) {
|
|
1461
|
1470
|
record = &(name->records[i]);
|
|
1462
|
1471
|
if (be16_to_cpu (record->name) == name_id &&
|
|
1463
|
1472
|
be16_to_cpu (record->platform) == platform &&
|
gfx/cairo/libpixman/src/pixman-edge-imp.h
| ... |
... |
@@ -53,10 +53,13 @@ RASTERIZE_EDGES (pixman_image_t *image, |
|
53
|
53
|
* when the sample point lies exactly on the line, we round towards
|
|
54
|
54
|
* north-west.
|
|
55
|
55
|
*
|
|
|
56
|
+ * Use 64 bits to get a saturating add, in case lx or rx are near
|
|
|
57
|
+ * the limits of pixman_fixed_t.
|
|
|
58
|
+ *
|
|
56
|
59
|
* (The AA case does a similar adjustment in RENDER_SAMPLES_X)
|
|
57
|
60
|
*/
|
|
58
|
|
- lx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
|
59
|
|
- rx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
|
|
61
|
+ lx = (pixman_fixed_t) MIN ((int64_t) lx + (X_FRAC_FIRST(1) - pixman_fixed_e), INT32_MAX);
|
|
|
62
|
+ rx = (pixman_fixed_t) MIN ((int64_t) rx + (X_FRAC_FIRST(1) - pixman_fixed_e), INT32_MAX);
|
|
60
|
63
|
#endif
|
|
61
|
64
|
/* clip X */
|
|
62
|
65
|
if (lx < 0)
|
gfx/cairo/patches/0043-Bug-2045711-records-size-check.patch
|
|
1
|
+diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c
|
|
|
2
|
+--- a/gfx/cairo/cairo/src/cairo-truetype-subset.c
|
|
|
3
|
++++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c
|
|
|
4
|
+@@ -1446,23 +1446,32 @@ cleanup:
|
|
|
5
|
+ */
|
|
|
6
|
+ #define MAX_FONT_NAME_LENGTH 127
|
|
|
7
|
+
|
|
|
8
|
+ static cairo_status_t
|
|
|
9
|
+ find_name (tt_name_t *name, unsigned long size, int name_id, int platform, int encoding, int language, char **str_out)
|
|
|
10
|
+ {
|
|
|
11
|
+ tt_name_record_t *record;
|
|
|
12
|
+ unsigned int i, len;
|
|
|
13
|
++ unsigned long max_records;
|
|
|
14
|
+ char *str;
|
|
|
15
|
+ char *p;
|
|
|
16
|
+ cairo_bool_t has_tag;
|
|
|
17
|
+ cairo_status_t status;
|
|
|
18
|
+
|
|
|
19
|
+ str = NULL;
|
|
|
20
|
+- for (i = 0; i < MIN(be16_to_cpu (name->num_records), size / sizeof(name->records[0])); i++) {
|
|
|
21
|
++ /* records[] starts after the 6-byte tt_name_t header (format,
|
|
|
22
|
++ * num_records, strings_offset); only records lying entirely within the
|
|
|
23
|
++ * size-byte table may be read. */
|
|
|
24
|
++ if (size < offsetof (tt_name_t, records)) {
|
|
|
25
|
++ *str_out = NULL;
|
|
|
26
|
++ return CAIRO_STATUS_SUCCESS;
|
|
|
27
|
++ }
|
|
|
28
|
++ max_records = (size - offsetof (tt_name_t, records)) / sizeof(name->records[0]);
|
|
|
29
|
++ for (i = 0; i < MIN(be16_to_cpu (name->num_records), max_records); i++) {
|
|
|
30
|
+ record = &(name->records[i]);
|
|
|
31
|
+ if (be16_to_cpu (record->name) == name_id &&
|
|
|
32
|
+ be16_to_cpu (record->platform) == platform &&
|
|
|
33
|
+ be16_to_cpu (record->encoding) == encoding &&
|
|
|
34
|
+ (language == -1 || be16_to_cpu (record->language) == language)) {
|
|
|
35
|
+
|
|
|
36
|
+ len = be16_to_cpu (record->length);
|
|
|
37
|
+ if (platform == 3 && len > MAX_FONT_NAME_LENGTH*2) /* UTF-16 name */ |
gfx/cairo/pixman-edge-saturate.patch
|
|
1
|
+From: Jim Blandy <jimb@xxxxxxxxxxx>
|
|
|
2
|
+Subject: Saturate when rounding up trapezoid edges
|
|
|
3
|
+
|
|
|
4
|
+diff --git a/gfx/cairo/libpixman/src/pixman-edge-imp.h b/gfx/cairo/libpixman/src/pixman-edge-imp.h
|
|
|
5
|
+index a4698eddb281..39e8d71d2568 100644
|
|
|
6
|
+--- a/gfx/cairo/libpixman/src/pixman-edge-imp.h
|
|
|
7
|
++++ b/gfx/cairo/libpixman/src/pixman-edge-imp.h
|
|
|
8
|
+@@ -53,10 +53,13 @@ RASTERIZE_EDGES (pixman_image_t *image,
|
|
|
9
|
+ * when the sample point lies exactly on the line, we round towards
|
|
|
10
|
+ * north-west.
|
|
|
11
|
+ *
|
|
|
12
|
++ * Use 64 bits to get a saturating add, in case lx or rx are near
|
|
|
13
|
++ * the limits of pixman_fixed_t.
|
|
|
14
|
++ *
|
|
|
15
|
+ * (The AA case does a similar adjustment in RENDER_SAMPLES_X)
|
|
|
16
|
+ */
|
|
|
17
|
+- lx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
|
|
18
|
+- rx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
|
|
19
|
++ lx = (pixman_fixed_t) MIN ((int64_t) lx + (X_FRAC_FIRST(1) - pixman_fixed_e), INT32_MAX);
|
|
|
20
|
++ rx = (pixman_fixed_t) MIN ((int64_t) rx + (X_FRAC_FIRST(1) - pixman_fixed_e), INT32_MAX);
|
|
|
21
|
+ #endif
|
|
|
22
|
+ /* clip X */
|
|
|
23
|
+ if (lx < 0) |
mobile/android/android-components/components/feature/sitepermissions/src/main/java/mozilla/components/feature/sitepermissions/SitePermissionsDialogFragment.kt
| ... |
... |
@@ -25,6 +25,7 @@ import androidx.core.graphics.drawable.toDrawable |
|
25
|
25
|
import mozilla.components.support.base.android.NoObscuredTouchesDialogFragment
|
|
26
|
26
|
import mozilla.components.support.base.log.logger.Logger
|
|
27
|
27
|
import mozilla.components.support.ktx.util.PromptAbuserDetector
|
|
|
28
|
+import mozilla.components.support.utils.OnEnterAnimationCompleteListener
|
|
28
|
29
|
|
|
29
|
30
|
internal const val KEY_SESSION_ID = "KEY_SESSION_ID"
|
|
30
|
31
|
internal const val KEY_TITLE = "KEY_TITLE"
|
| ... |
... |
@@ -42,7 +43,9 @@ private const val KEY_IS_NOTIFICATION_REQUEST = "KEY_IS_NOTIFICATION_REQUEST" |
|
42
|
43
|
private const val DEFAULT_VALUE = Int.MAX_VALUE
|
|
43
|
44
|
private const val KEY_PERMISSION_ID = "KEY_PERMISSION_ID"
|
|
44
|
45
|
|
|
45
|
|
-internal open class SitePermissionsDialogFragment : NoObscuredTouchesDialogFragment() {
|
|
|
46
|
+internal open class SitePermissionsDialogFragment :
|
|
|
47
|
+ NoObscuredTouchesDialogFragment(),
|
|
|
48
|
+ OnEnterAnimationCompleteListener {
|
|
46
|
49
|
|
|
47
|
50
|
private val logger = Logger("SitePermissionsDialogFragment")
|
|
48
|
51
|
|
| ... |
... |
@@ -124,6 +127,11 @@ internal open class SitePermissionsDialogFragment : NoObscuredTouchesDialogFragm |
|
124
|
127
|
feature?.onDismiss(permissionRequestId, sessionId)
|
|
125
|
128
|
}
|
|
126
|
129
|
|
|
|
130
|
+ override fun onEnterAnimationComplete() {
|
|
|
131
|
+ // Extend the positive button click delay.
|
|
|
132
|
+ promptAbuserDetector.updateJSDialogAbusedState()
|
|
|
133
|
+ }
|
|
|
134
|
+
|
|
127
|
135
|
private fun Dialog.setContainerView(rootView: View) {
|
|
128
|
136
|
if (dialogShouldWidthMatchParent) {
|
|
129
|
137
|
setContentView(rootView)
|
mobile/android/android-components/components/support/utils/src/main/java/mozilla/components/support/utils/OnEnterAnimationCompleteListener.kt
|
|
1
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
2
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
3
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
4
|
+
|
|
|
5
|
+package mozilla.components.support.utils
|
|
|
6
|
+
|
|
|
7
|
+/**
|
|
|
8
|
+ * Allows forwarding [android.app.Activity.onEnterAnimationComplete] to other classes
|
|
|
9
|
+ * (e.g. fragments) that want to participate in handling it.
|
|
|
10
|
+ */
|
|
|
11
|
+interface OnEnterAnimationCompleteListener {
|
|
|
12
|
+ /**
|
|
|
13
|
+ * Called when the Activity's entering animation has completed.
|
|
|
14
|
+ */
|
|
|
15
|
+ fun onEnterAnimationComplete()
|
|
|
16
|
+} |
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt
| ... |
... |
@@ -13,6 +13,7 @@ import androidx.annotation.VisibleForTesting |
|
13
|
13
|
import androidx.core.net.toUri
|
|
14
|
14
|
import mozilla.components.browser.state.selector.findCustomTab
|
|
15
|
15
|
import mozilla.components.browser.state.state.SessionState
|
|
|
16
|
+import mozilla.components.support.utils.OnEnterAnimationCompleteListener
|
|
16
|
17
|
import mozilla.components.support.utils.SafeIntent
|
|
17
|
18
|
import org.mozilla.fenix.HomeActivity
|
|
18
|
19
|
import org.mozilla.fenix.ext.components
|
| ... |
... |
@@ -95,5 +96,14 @@ open class ExternalAppBrowserActivity : HomeActivity() { |
|
95
|
96
|
override fun onEnterAnimationComplete() {
|
|
96
|
97
|
super.onEnterAnimationComplete()
|
|
97
|
98
|
isFinishedAnimating = true
|
|
|
99
|
+
|
|
|
100
|
+ val fragments = supportFragmentManager.fragments.toMutableList()
|
|
|
101
|
+ while (fragments.isNotEmpty()) {
|
|
|
102
|
+ val fragment = fragments.removeAt(0)
|
|
|
103
|
+ if (fragment is OnEnterAnimationCompleteListener) {
|
|
|
104
|
+ fragment.onEnterAnimationComplete()
|
|
|
105
|
+ }
|
|
|
106
|
+ fragments.addAll(fragment.childFragmentManager.fragments)
|
|
|
107
|
+ }
|
|
98
|
108
|
}
|
|
99
|
109
|
} |
parser/expat/13_high_surrogate_mask.patch
|
|
1
|
+diff --git a/expat/expat/lib/xmltok.c b/expat/expat/lib/xmltok.c
|
|
|
2
|
+--- a/expat/expat/lib/xmltok.c
|
|
|
3
|
++++ b/expat/expat/lib/xmltok.c
|
|
|
4
|
+@@ -707,7 +707,9 @@ unicode_byte_type(char hi, char lo) {
|
|
|
5
|
+ fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
|
|
|
6
|
+ /* Avoid copying first half only of surrogate */ \
|
|
|
7
|
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
|
|
|
8
|
+- && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
|
|
|
9
|
++/* BEGIN MOZILLA CHANGE (Only high surrogate mask) */ \
|
|
|
10
|
++ && (GET_HI(fromLim - 2) & 0xFC) == 0xD8) { \
|
|
|
11
|
++/* END MOZILLA CHANGE */ \
|
|
|
12
|
+ fromLim -= 2; \
|
|
|
13
|
+ res = XML_CONVERT_INPUT_INCOMPLETE; \
|
|
|
14
|
+ } \ |
parser/expat/expat/lib/xmltok.c
| ... |
... |
@@ -705,7 +705,9 @@ unicode_byte_type(char hi, char lo) { |
|
705
|
705
|
fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
|
|
706
|
706
|
/* Avoid copying first half only of surrogate */ \
|
|
707
|
707
|
if (fromLim - *fromP > ((toLim - *toP) << 1) \
|
|
708
|
|
- && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
|
|
|
708
|
+/* BEGIN MOZILLA CHANGE (Only high surrogate mask) */ \
|
|
|
709
|
+ && (GET_HI(fromLim - 2) & 0xFC) == 0xD8) { \
|
|
|
710
|
+/* END MOZILLA CHANGE */ \
|
|
709
|
711
|
fromLim -= 2; \
|
|
710
|
712
|
res = XML_CONVERT_INPUT_INCOMPLETE; \
|
|
711
|
713
|
} \
|
parser/expat/moz.yaml
| ... |
... |
@@ -62,3 +62,4 @@ vendoring: |
|
62
|
62
|
- 10_version_limit.patch
|
|
63
|
63
|
- 11_no_debug_report.patch
|
|
64
|
64
|
- 12_unused.patch
|
|
|
65
|
+ - 13_high_surrogate_mask.patch |
toolkit/components/formautofill/FormAutofillParent.sys.mjs
| ... |
... |
@@ -474,6 +474,10 @@ export class FormAutofillParent extends JSWindowActorParent { |
|
474
|
474
|
}
|
|
475
|
475
|
|
|
476
|
476
|
const iframeBC = BrowsingContext.get(field.browsingContextId);
|
|
|
477
|
+ if (!iframeBC || iframeBC.parent != browsingContext) {
|
|
|
478
|
+ continue;
|
|
|
479
|
+ }
|
|
|
480
|
+
|
|
477
|
481
|
const [fields] = await this.identifyAllSubTreeFields(
|
|
478
|
482
|
iframeBC,
|
|
479
|
483
|
focusedBCId,
|
toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
| ... |
... |
@@ -931,16 +931,24 @@ function shouldVerifySignedState(aAddonType, aLocation) { |
|
931
|
931
|
* or undefined if the file wasn't signed.
|
|
932
|
932
|
*/
|
|
933
|
933
|
export var verifyBundleSignedState = async function (aBundle, aAddon) {
|
|
934
|
|
- let pkg = Package.get(aBundle);
|
|
935
|
934
|
try {
|
|
936
|
|
- let { signedState, signedTypes } = await pkg.verifySignedState(
|
|
937
|
|
- aAddon.id,
|
|
938
|
|
- aAddon.type,
|
|
939
|
|
- aAddon.location
|
|
940
|
|
- );
|
|
941
|
|
- return { signedState, signedTypes };
|
|
942
|
|
- } finally {
|
|
943
|
|
- pkg.close();
|
|
|
935
|
+ let pkg = Package.get(aBundle);
|
|
|
936
|
+ try {
|
|
|
937
|
+ let { signedState, signedTypes } = await pkg.verifySignedState(
|
|
|
938
|
+ aAddon.id,
|
|
|
939
|
+ aAddon.type,
|
|
|
940
|
+ aAddon.location
|
|
|
941
|
+ );
|
|
|
942
|
+ return { signedState, signedTypes };
|
|
|
943
|
+ } finally {
|
|
|
944
|
+ pkg.close();
|
|
|
945
|
+ }
|
|
|
946
|
+ } catch (e) {
|
|
|
947
|
+ logger.warn(`verifyBundleSignedState failed for ${aAddon.id}`, e);
|
|
|
948
|
+ if (!shouldVerifySignedState(aAddon.type, aAddon.location)) {
|
|
|
949
|
+ return { signedState: AddonManager.SIGNEDSTATE_NOT_REQUIRED };
|
|
|
950
|
+ }
|
|
|
951
|
+ return { signedState: AddonManager.SIGNEDSTATE_BROKEN };
|
|
944
|
952
|
}
|
|
945
|
953
|
};
|
|
946
|
954
|
|
toolkit/mozapps/extensions/test/xpcshell/test_signed_verify.js
| ... |
... |
@@ -23,6 +23,13 @@ function verifySignatures() { |
|
23
|
23
|
});
|
|
24
|
24
|
}
|
|
25
|
25
|
|
|
|
26
|
+async function writeCorruptedXPIFile(extensionId) {
|
|
|
27
|
+ let file = AddonTestUtils.getFileForAddon(profileDir, extensionId);
|
|
|
28
|
+ // Clear any handles to the file before replacing it; Windows is very picky.
|
|
|
29
|
+ Services.obs.notifyObservers(file, "flush-cache-entry");
|
|
|
30
|
+ await IOUtils.writeUTF8(file.path, "not a XPI file anymore");
|
|
|
31
|
+}
|
|
|
32
|
+
|
|
26
|
33
|
createAppInfo("xpcshell@xxxxxxxxxxxxxxxxx", "XPCShell", "4", "48");
|
|
27
|
34
|
|
|
28
|
35
|
add_setup(async () => {
|
| ... |
... |
@@ -581,3 +588,159 @@ add_task(async function test_xpi_signed_in_or_before_feb_2018() { |
|
581
|
588
|
|
|
582
|
589
|
ExtensionTestUtils.failOnSchemaWarnings(true);
|
|
583
|
590
|
});
|
|
|
591
|
+
|
|
|
592
|
+add_task(
|
|
|
593
|
+ {
|
|
|
594
|
+ ...useAMOStageCert(),
|
|
|
595
|
+ // This test verifies a behavior that is only hit on builds where the
|
|
|
596
|
+ // enterprise policies are enabled (and skipped in build where enterprise
|
|
|
597
|
+ // policies are disabled, like in mobile builds).
|
|
|
598
|
+ skip_if: () => !Services.policies,
|
|
|
599
|
+ },
|
|
|
600
|
+ async function test_adminInstallOnly_on_verify_with_invalid_manifest() {
|
|
|
601
|
+ const { sinon } = ChromeUtils.importESModule(
|
|
|
602
|
+ "resource://testing-common/Sinon.sys.mjs"
|
|
|
603
|
+ );
|
|
|
604
|
+ const sandbox = sinon.createSandbox();
|
|
|
605
|
+
|
|
|
606
|
+ const { addon: addon1 } = await promiseInstallFile(
|
|
|
607
|
+ do_get_file(`${DATA}/signed1.xpi`)
|
|
|
608
|
+ );
|
|
|
609
|
+ const { addon: addon2 } = await promiseInstallFile(
|
|
|
610
|
+ do_get_file(`${DATA}/long.xpi`)
|
|
|
611
|
+ );
|
|
|
612
|
+
|
|
|
613
|
+ const { XPIExports } = ChromeUtils.importESModule(
|
|
|
614
|
+ "resource://gre/modules/addons/XPIExports.sys.mjs"
|
|
|
615
|
+ );
|
|
|
616
|
+ sinon
|
|
|
617
|
+ .stub(XPIExports.XPIInstall, "loadManifestFromFile")
|
|
|
618
|
+ .callsFake((_sourceBundle, _location) => {
|
|
|
619
|
+ throw new Error("FAKE invalid manifest error");
|
|
|
620
|
+ });
|
|
|
621
|
+
|
|
|
622
|
+ const { messages } = await AddonTestUtils.promiseConsoleOutput(async () => {
|
|
|
623
|
+ await verifySignatures();
|
|
|
624
|
+ });
|
|
|
625
|
+ sandbox.restore();
|
|
|
626
|
+
|
|
|
627
|
+ // Expect a logged warning for each of the two extensions.
|
|
|
628
|
+ AddonTestUtils.checkMessages(messages, {
|
|
|
629
|
+ expected: [
|
|
|
630
|
+ {
|
|
|
631
|
+ message:
|
|
|
632
|
+ /XPI_verifySignature Warning on 'test@xxxxxxxxxxxxx': Error: FAKE invalid manifest error/,
|
|
|
633
|
+ },
|
|
|
634
|
+ {
|
|
|
635
|
+ message:
|
|
|
636
|
+ /XPI_verifySignature Warning on '123456789.*@somewhere.com': Error: FAKE invalid manifest error/,
|
|
|
637
|
+ },
|
|
|
638
|
+ ],
|
|
|
639
|
+ });
|
|
|
640
|
+
|
|
|
641
|
+ await addon1.uninstall();
|
|
|
642
|
+ await addon2.uninstall();
|
|
|
643
|
+ }
|
|
|
644
|
+);
|
|
|
645
|
+
|
|
|
646
|
+add_task(useAMOStageCert(), async function test_broken_file() {
|
|
|
647
|
+ await promiseInstallFile(do_get_file(`${DATA}/signed1.xpi`));
|
|
|
648
|
+
|
|
|
649
|
+ let addon = await promiseAddonByID(ID);
|
|
|
650
|
+ Assert.notEqual(addon, null);
|
|
|
651
|
+ Assert.equal(addon.appDisabled, false);
|
|
|
652
|
+ Assert.equal(addon.isActive, true);
|
|
|
653
|
+ Assert.equal(addon.signedState, AddonManager.SIGNEDSTATE_SIGNED);
|
|
|
654
|
+
|
|
|
655
|
+ await writeCorruptedXPIFile(ID);
|
|
|
656
|
+
|
|
|
657
|
+ let changedProperties = [];
|
|
|
658
|
+ let listener = {
|
|
|
659
|
+ onPropertyChanged(addon, properties) {
|
|
|
660
|
+ changedProperties.push(...properties);
|
|
|
661
|
+ },
|
|
|
662
|
+ };
|
|
|
663
|
+
|
|
|
664
|
+ AddonManager.addAddonListener(listener);
|
|
|
665
|
+
|
|
|
666
|
+ const disablePromise = promiseAddonEvent("onDisabling");
|
|
|
667
|
+ let changes;
|
|
|
668
|
+ const { messages } = await AddonTestUtils.promiseConsoleOutput(async () => {
|
|
|
669
|
+ changes = await verifySignatures();
|
|
|
670
|
+ });
|
|
|
671
|
+ await disablePromise;
|
|
|
672
|
+
|
|
|
673
|
+ Assert.equal(changes.enabled.length, 0);
|
|
|
674
|
+ Assert.equal(changes.disabled.length, 1);
|
|
|
675
|
+ Assert.equal(changes.disabled[0], ID);
|
|
|
676
|
+
|
|
|
677
|
+ Assert.deepEqual(
|
|
|
678
|
+ changedProperties,
|
|
|
679
|
+ ["signedState", "signedTypes", "appDisabled"],
|
|
|
680
|
+ "Got onPropertyChanged events for signedState and appDisabled"
|
|
|
681
|
+ );
|
|
|
682
|
+
|
|
|
683
|
+ Assert.ok(addon.appDisabled);
|
|
|
684
|
+ Assert.ok(!addon.isActive);
|
|
|
685
|
+ Assert.equal(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN);
|
|
|
686
|
+
|
|
|
687
|
+ await addon.uninstall();
|
|
|
688
|
+ AddonManager.removeAddonListener(listener);
|
|
|
689
|
+
|
|
|
690
|
+ AddonTestUtils.checkMessages(messages, {
|
|
|
691
|
+ expected: [
|
|
|
692
|
+ { message: /verifyBundleSignedState failed for test@xxxxxxxxxxxxx/ },
|
|
|
693
|
+ ],
|
|
|
694
|
+ });
|
|
|
695
|
+});
|
|
|
696
|
+
|
|
|
697
|
+// Verify that verifySignatures() does not change signedState for addons that
|
|
|
698
|
+// do not require signatures, even if the underlying file got corrupted.
|
|
|
699
|
+add_task(
|
|
|
700
|
+ {
|
|
|
701
|
+ ...useAMOStageCert(),
|
|
|
702
|
+ // # Non-extension add-ons are not supported on Android.
|
|
|
703
|
+ skip_if: () => AppConstants.platform == "android",
|
|
|
704
|
+ },
|
|
|
705
|
+ async function test_broken_file_not_requiring_signatures() {
|
|
|
706
|
+ // Note: If dictionaries ever require signatures (bug 1753276), change this
|
|
|
707
|
+ // test to another test case where shouldVerifySignedState returns false.
|
|
|
708
|
+ let addon = await promiseInstallWebExtension({
|
|
|
709
|
+ useAddonManager: true,
|
|
|
710
|
+ manifest: {
|
|
|
711
|
+ browser_specific_settings: { gecko: { id: "broken@dict" } },
|
|
|
712
|
+ dictionaries: { "en-US": "en-US.dic" },
|
|
|
713
|
+ },
|
|
|
714
|
+ files: { "en-US.dic": "", "en-US.aff": "" },
|
|
|
715
|
+ });
|
|
|
716
|
+ Assert.equal(addon.signedState, AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
|
|
717
|
+
|
|
|
718
|
+ await writeCorruptedXPIFile(addon.id);
|
|
|
719
|
+
|
|
|
720
|
+ let listener = {
|
|
|
721
|
+ onPropertyChanged(_addon) {
|
|
|
722
|
+ Assert.ok(false, `Got unexpected onPropertyChanged for ${_addon.id}`);
|
|
|
723
|
+ },
|
|
|
724
|
+ };
|
|
|
725
|
+
|
|
|
726
|
+ AddonManager.addAddonListener(listener);
|
|
|
727
|
+
|
|
|
728
|
+ let changes;
|
|
|
729
|
+ const { messages } = await AddonTestUtils.promiseConsoleOutput(async () => {
|
|
|
730
|
+ changes = await verifySignatures();
|
|
|
731
|
+ });
|
|
|
732
|
+ Assert.equal(changes.enabled.length, 0);
|
|
|
733
|
+ Assert.equal(changes.disabled.length, 0);
|
|
|
734
|
+
|
|
|
735
|
+ Assert.equal(addon.appDisabled, false);
|
|
|
736
|
+ Assert.equal(addon.isActive, true);
|
|
|
737
|
+ Assert.equal(addon.signedState, AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
|
|
738
|
+
|
|
|
739
|
+ await addon.uninstall();
|
|
|
740
|
+ AddonManager.removeAddonListener(listener);
|
|
|
741
|
+
|
|
|
742
|
+ AddonTestUtils.checkMessages(messages, {
|
|
|
743
|
+ expected: [{ message: /verifyBundleSignedState failed for broken@dict/ }],
|
|
|
744
|
+ });
|
|
|
745
|
+ }
|
|
|
746
|
+); |
|