Commits:
-
434c77a2
by Jeff Boek at 2026-11-09T10:39:10+01:00
Bug 1991276 - Only fill based on the currently focused node r=geckoview-reviewers,owlish
Differential Revision: https://phabricator.services.mozilla.com/D272949
-
89fe8d45
by pollymce at 2026-11-09T10:39:11+01:00
Bug 2074123 - show recording notification for custom tabs as well as regular tabs. r=android-reviewers,mcarare
Differential Revision: https://phabricator.services.mozilla.com/D332436
-
e74a7d7a
by Emilio Cobos Álvarez at 2026-11-09T10:39:11+01:00
Bug 2077035 - Remove untested and dubious visitedWeight target radius. r=masayuki
I don't think it's worth it. It's pretty dubious to favor a visited link
in that way anyway, specially in the modern web where lots of links are
used as buttons and so on.
It's also totally untested.
Differential Revision: https://phabricator.services.mozilla.com/D332153
-
2d3db03e
by Nicolas Silva at 2026-11-09T10:39:12+01:00
Bug 2081249 - Handle empty profile shmems from child processes in nsProfiler::StartGathering. r=profiler-reviewers,canova
Differential Revision: https://phabricator.services.mozilla.com/D333246
-
39c0db5e
by Nicolas Silva at 2026-11-09T10:39:12+01:00
Bug 2081249 - Bound the time CanvasTranslator::CheckAndSignalWriter waits for the writer to leave the AboutToWait state. r=gfx-reviewers,gw
Differential Revision: https://phabricator.services.mozilla.com/D333248
-
7cbf6257
by Emilio Cobos Álvarez at 2026-11-09T10:39:13+01:00
Bug 2083733. r=arai
Differential Revision: https://phabricator.services.mozilla.com/D335409
17 changed files:
Changes:
gfx/layers/ipc/CanvasTranslator.cpp
| ... |
... |
@@ -660,6 +660,8 @@ void CanvasTranslator::BlockCanvas() { |
|
660
|
660
|
}
|
|
661
|
661
|
|
|
662
|
662
|
void CanvasTranslator::CheckAndSignalWriter() {
|
|
|
663
|
+ uint32_t spinCount = mMaxSpinCount;
|
|
|
664
|
+ TimeStamp deadline;
|
|
663
|
665
|
do {
|
|
664
|
666
|
switch (mHeader->writerState) {
|
|
665
|
667
|
case State::Processing:
|
| ... |
... |
@@ -672,6 +674,20 @@ void CanvasTranslator::CheckAndSignalWriter() { |
|
672
|
674
|
if (mIPDLClosed) {
|
|
673
|
675
|
return;
|
|
674
|
676
|
}
|
|
|
677
|
+ if (spinCount > 0) {
|
|
|
678
|
+ --spinCount;
|
|
|
679
|
+ continue;
|
|
|
680
|
+ }
|
|
|
681
|
+ // The writer only stays in this state for a few instructions, so if it
|
|
|
682
|
+ // does not move on in a reasonable time it is misbehaving.
|
|
|
683
|
+ if (deadline.IsNull()) {
|
|
|
684
|
+ deadline = TimeStamp::Now() + TimeDuration::FromSeconds(1);
|
|
|
685
|
+ } else if (TimeStamp::Now() > deadline) {
|
|
|
686
|
+ gfxCriticalNote << "CanvasTranslator writer stuck in AboutToWait";
|
|
|
687
|
+ Deactivate();
|
|
|
688
|
+ return;
|
|
|
689
|
+ }
|
|
|
690
|
+ PR_Sleep(PR_INTERVAL_NO_WAIT);
|
|
675
|
691
|
continue;
|
|
676
|
692
|
case State::Waiting:
|
|
677
|
693
|
if (mHeader->processedCount >= mHeader->writerWaitCount) {
|
layout/base/PositionedEventTargeting.cpp
| ... |
... |
@@ -104,8 +104,7 @@ enum class SearchType { |
|
104
|
104
|
};
|
|
105
|
105
|
|
|
106
|
106
|
struct EventRadiusPrefs {
|
|
107
|
|
- bool mEnabled; // other fields are valid iff this field is true
|
|
108
|
|
- uint32_t mVisitedWeight; // in percent, i.e. default is 100
|
|
|
107
|
+ bool mEnabled; // other fields are valid iff this field is true
|
|
109
|
108
|
uint32_t mRadiusTopmm;
|
|
110
|
109
|
uint32_t mRadiusRightmm;
|
|
111
|
110
|
uint32_t mRadiusBottommm;
|
| ... |
... |
@@ -117,7 +116,6 @@ struct EventRadiusPrefs { |
|
117
|
116
|
explicit EventRadiusPrefs(WidgetGUIEvent* aMouseOrTouchEvent) {
|
|
118
|
117
|
if (aMouseOrTouchEvent->mClass == eTouchEventClass) {
|
|
119
|
118
|
mEnabled = StaticPrefs::ui_touch_radius_enabled();
|
|
120
|
|
- mVisitedWeight = StaticPrefs::ui_touch_radius_visitedWeight();
|
|
121
|
119
|
mRadiusTopmm = StaticPrefs::ui_touch_radius_topmm();
|
|
122
|
120
|
mRadiusRightmm = StaticPrefs::ui_touch_radius_rightmm();
|
|
123
|
121
|
mRadiusBottommm = StaticPrefs::ui_touch_radius_bottommm();
|
| ... |
... |
@@ -138,7 +136,6 @@ struct EventRadiusPrefs { |
|
138
|
136
|
|
|
139
|
137
|
} else if (aMouseOrTouchEvent->mClass == eMouseEventClass) {
|
|
140
|
138
|
mEnabled = StaticPrefs::ui_mouse_radius_enabled();
|
|
141
|
|
- mVisitedWeight = StaticPrefs::ui_mouse_radius_visitedWeight();
|
|
142
|
139
|
mRadiusTopmm = StaticPrefs::ui_mouse_radius_topmm();
|
|
143
|
140
|
mRadiusRightmm = StaticPrefs::ui_mouse_radius_rightmm();
|
|
144
|
141
|
mRadiusBottommm = StaticPrefs::ui_mouse_radius_bottommm();
|
| ... |
... |
@@ -149,7 +146,6 @@ struct EventRadiusPrefs { |
|
149
|
146
|
|
|
150
|
147
|
} else {
|
|
151
|
148
|
mEnabled = false;
|
|
152
|
|
- mVisitedWeight = 0;
|
|
153
|
149
|
mRadiusTopmm = 0;
|
|
154
|
150
|
mRadiusRightmm = 0;
|
|
155
|
151
|
mRadiusBottommm = 0;
|
| ... |
... |
@@ -697,17 +693,6 @@ static nsIFrame* GetClosest(RelativeTo aRoot, |
|
697
|
693
|
// distance is in appunit
|
|
698
|
694
|
double distance =
|
|
699
|
695
|
ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
|
|
700
|
|
- nsIContent* content = f->GetContent();
|
|
701
|
|
- // XXX Well, some users may want to tap unvisited link, however, some other
|
|
702
|
|
- // users may not. For example, click a link, and go back, then, want to go
|
|
703
|
|
- // forward, but click the visited link instead. This scenario may occur if
|
|
704
|
|
- // clicking the link is easier to do "go forward" and I think it's true for
|
|
705
|
|
- // the most users. So, it might be better to do this.
|
|
706
|
|
- if (content && content->IsElement() &&
|
|
707
|
|
- content->AsElement()->State().HasState(
|
|
708
|
|
- ElementState(ElementState::VISITED))) {
|
|
709
|
|
- distance *= aPrefs.mVisitedWeight / 100.0;
|
|
710
|
|
- }
|
|
711
|
696
|
// XXX When we look for a touchable or clickable target, should we give
|
|
712
|
697
|
// lower weight for clickable target?
|
|
713
|
698
|
if (distance < bestDistance) {
|
layout/base/tests/test_event_target_radius.html
| ... |
... |
@@ -122,8 +122,8 @@ function startTest() { |
|
122
|
122
|
["ui.mouse.radius.leftmm", 12],
|
|
123
|
123
|
["ui.mouse.radius.topmm", 4],
|
|
124
|
124
|
["ui.mouse.radius.rightmm", 4],
|
|
125
|
|
- ["ui.mouse.radius.bottommm", 4],
|
|
126
|
|
- ["ui.mouse.radius.visitedweight", 50]]}, runTest);
|
|
|
125
|
+ ["ui.mouse.radius.bottommm", 4]
|
|
|
126
|
+ ]}, runTest);
|
|
127
|
127
|
}
|
|
128
|
128
|
|
|
129
|
129
|
|
| ... |
... |
@@ -484,7 +484,6 @@ function test3() { |
|
484
|
484
|
setShowing("t3_6", false);
|
|
485
|
485
|
|
|
486
|
486
|
// Not yet tested:
|
|
487
|
|
- // -- visited link weight
|
|
488
|
487
|
// -- "Closest" using Euclidean distance
|
|
489
|
488
|
|
|
490
|
489
|
|
| ... |
... |
@@ -493,8 +492,8 @@ function test3() { |
|
493
|
492
|
["ui.touch.radius.leftmm", 12],
|
|
494
|
493
|
["ui.touch.radius.topmm", 4],
|
|
495
|
494
|
["ui.touch.radius.rightmm", 4],
|
|
496
|
|
- ["ui.touch.radius.bottommm", 4],
|
|
497
|
|
- ["ui.touch.radius.visitedweight", 50]]}, testTouchable);
|
|
|
495
|
+ ["ui.touch.radius.bottommm", 4]
|
|
|
496
|
+ ]}, testTouchable);
|
|
498
|
497
|
}
|
|
499
|
498
|
|
|
500
|
499
|
async function testTouchable() {
|
layout/style/Loader.cpp
| ... |
... |
@@ -1548,14 +1548,13 @@ Loader::Completed Loader::ParseSheet( |
|
1548
|
1548
|
|
|
1549
|
1549
|
void Loader::AddPerformanceEntryForCachedSheet(SheetLoadData& aLoadData) {
|
|
1550
|
1550
|
MOZ_ASSERT(aLoadData.mURI);
|
|
1551
|
|
-
|
|
1552
|
|
- if (!aLoadData.mNetworkMetadata) {
|
|
|
1551
|
+ if (!mDocument || !aLoadData.mNetworkMetadata) {
|
|
1553
|
1552
|
return;
|
|
1554
|
1553
|
}
|
|
1555
|
|
- if (!mDocument) {
|
|
|
1554
|
+ if (aLoadData.mParentData &&
|
|
|
1555
|
+ !aLoadData.mParentData->mSheet->IsOriginClean()) {
|
|
1556
|
1556
|
return;
|
|
1557
|
1557
|
}
|
|
1558
|
|
-
|
|
1559
|
1558
|
nsAutoCString name;
|
|
1560
|
1559
|
aLoadData.mURI->GetSpec(name);
|
|
1561
|
1560
|
NS_ConvertUTF8toUTF16 entryName(name);
|
mobile/android/android-components/components/feature/media/src/main/java/mozilla/components/feature/media/middleware/RecordingDevicesMiddleware.kt
| ... |
... |
@@ -70,11 +70,12 @@ class RecordingDevicesMiddleware( |
|
70
|
70
|
store: Store<BrowserState, BrowserAction>,
|
|
71
|
71
|
isReminder: Boolean,
|
|
72
|
72
|
) {
|
|
73
|
|
- val devices = store.state.tabs
|
|
74
|
|
- .map { tab -> tab.content.recordingDevices }
|
|
75
|
|
- .flatten()
|
|
76
|
|
- .filter { device -> device.status == RecordingDevice.Status.RECORDING }
|
|
77
|
|
- .distinctBy { device -> device.type }
|
|
|
73
|
+ val devices =
|
|
|
74
|
+ (store.state.tabs + store.state.customTabs)
|
|
|
75
|
+ .map { tab -> tab.content.recordingDevices }
|
|
|
76
|
+ .flatten()
|
|
|
77
|
+ .filter { device -> device.status == RecordingDevice.Status.RECORDING }
|
|
|
78
|
+ .distinctBy { device -> device.type }
|
|
78
|
79
|
|
|
79
|
80
|
val isUsingCamera = devices.find { it.type == RecordingDevice.Type.CAMERA } != null
|
|
80
|
81
|
val isUsingMicrophone = devices.find { it.type == RecordingDevice.Type.MICROPHONE } != null
|
mobile/android/android-components/components/feature/media/src/test/java/mozilla/components/feature/media/middleware/RecordingDevicesMiddlewareTest.kt
| ... |
... |
@@ -12,7 +12,9 @@ import android.content.IntentFilter |
|
12
|
12
|
import androidx.core.app.NotificationManagerCompat
|
|
13
|
13
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
14
|
14
|
import mozilla.components.browser.state.action.ContentAction
|
|
|
15
|
+import mozilla.components.browser.state.action.CustomTabListAction
|
|
15
|
16
|
import mozilla.components.browser.state.state.BrowserState
|
|
|
17
|
+import mozilla.components.browser.state.state.createCustomTab
|
|
16
|
18
|
import mozilla.components.browser.state.state.createTab
|
|
17
|
19
|
import mozilla.components.browser.state.store.BrowserStore
|
|
18
|
20
|
import mozilla.components.concept.engine.media.RecordingDevice
|
| ... |
... |
@@ -131,4 +133,65 @@ class RecordingDevicesMiddlewareTest { |
|
131
|
133
|
|
|
132
|
134
|
assertEquals(0, notificationManager.size())
|
|
133
|
135
|
}
|
|
|
136
|
+
|
|
|
137
|
+ @Test
|
|
|
138
|
+ fun `middleware shows notification when custom tab has a recording device then hides when recording devices become inactive`() {
|
|
|
139
|
+ val realNotificationManager = testContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
|
140
|
+ val notificationManager = Shadows.shadowOf(realNotificationManager)
|
|
|
141
|
+
|
|
|
142
|
+ val middleware = RecordingDevicesMiddleware(testContext, notificationsDelegate)
|
|
|
143
|
+ val store =
|
|
|
144
|
+ BrowserStore(
|
|
|
145
|
+ initialState =
|
|
|
146
|
+ BrowserState(customTabs = listOf(createCustomTab("https://www.mozilla.org", id = "mozilla"))),
|
|
|
147
|
+ middleware = listOf(middleware),
|
|
|
148
|
+ )
|
|
|
149
|
+
|
|
|
150
|
+ assertEquals(0, notificationManager.size())
|
|
|
151
|
+
|
|
|
152
|
+ store.dispatch(
|
|
|
153
|
+ ContentAction.SetRecordingDevices(
|
|
|
154
|
+ sessionId = "mozilla",
|
|
|
155
|
+ devices = listOf(RecordingDevice(RecordingDevice.Type.MICROPHONE, RecordingDevice.Status.RECORDING)),
|
|
|
156
|
+ )
|
|
|
157
|
+ )
|
|
|
158
|
+
|
|
|
159
|
+ assertEquals(1, notificationManager.size())
|
|
|
160
|
+
|
|
|
161
|
+ store.dispatch(
|
|
|
162
|
+ ContentAction.SetRecordingDevices(
|
|
|
163
|
+ sessionId = "mozilla",
|
|
|
164
|
+ devices = emptyList(),
|
|
|
165
|
+ )
|
|
|
166
|
+ )
|
|
|
167
|
+
|
|
|
168
|
+ assertEquals(0, notificationManager.size())
|
|
|
169
|
+ }
|
|
|
170
|
+
|
|
|
171
|
+ @Test
|
|
|
172
|
+ fun `middleware hides notification when a recording custom tab is removed`() {
|
|
|
173
|
+ val realNotificationManager = testContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
|
174
|
+ val notificationManager = Shadows.shadowOf(realNotificationManager)
|
|
|
175
|
+
|
|
|
176
|
+ val middleware = RecordingDevicesMiddleware(testContext, notificationsDelegate)
|
|
|
177
|
+ val store =
|
|
|
178
|
+ BrowserStore(
|
|
|
179
|
+ initialState =
|
|
|
180
|
+ BrowserState(customTabs = listOf(createCustomTab("https://www.mozilla.org", id = "mozilla"))),
|
|
|
181
|
+ middleware = listOf(middleware),
|
|
|
182
|
+ )
|
|
|
183
|
+
|
|
|
184
|
+ store.dispatch(
|
|
|
185
|
+ ContentAction.SetRecordingDevices(
|
|
|
186
|
+ sessionId = "mozilla",
|
|
|
187
|
+ devices = listOf(RecordingDevice(RecordingDevice.Type.MICROPHONE, RecordingDevice.Status.RECORDING)),
|
|
|
188
|
+ )
|
|
|
189
|
+ )
|
|
|
190
|
+
|
|
|
191
|
+ assertEquals(1, notificationManager.size())
|
|
|
192
|
+
|
|
|
193
|
+ store.dispatch(CustomTabListAction.RemoveCustomTabAction(tabId = "mozilla"))
|
|
|
194
|
+
|
|
|
195
|
+ assertEquals(0, notificationManager.size())
|
|
|
196
|
+ }
|
|
134
|
197
|
} |
mobile/android/geckoview/src/androidTest/assets/www/forms_iframe.html
| ... |
... |
@@ -52,6 +52,10 @@ |
|
52
|
52
|
|
|
53
|
53
|
window.addEventListener("message", async event => {
|
|
54
|
54
|
const { data, source, origin } = event;
|
|
|
55
|
+ if (data.type == "getValue") {
|
|
|
56
|
+ source.postMessage(document.querySelector(data.key).value, origin);
|
|
|
57
|
+ return;
|
|
|
58
|
+ }
|
|
55
|
59
|
source.postMessage(await getData(data.key, data.value), origin);
|
|
56
|
60
|
});
|
|
57
|
61
|
</script>
|
mobile/android/geckoview/src/androidTest/assets/www/forms_xorigin.html
| ... |
... |
@@ -73,5 +73,15 @@ |
|
73
|
73
|
data.push(getData(key, value));
|
|
74
|
74
|
return Promise.all(data);
|
|
75
|
75
|
};
|
|
|
76
|
+
|
|
|
77
|
+ window.getIframeValue = function (key) {
|
|
|
78
|
+ const value = new Promise(resolve =>
|
|
|
79
|
+ window.addEventListener("message", event => resolve(event.data), {
|
|
|
80
|
+ once: true,
|
|
|
81
|
+ })
|
|
|
82
|
+ );
|
|
|
83
|
+ iframe.postMessage({ type: "getValue", key }, "*");
|
|
|
84
|
+ return value;
|
|
|
85
|
+ };
|
|
76
|
86
|
</script>
|
|
77
|
87
|
</html> |
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt
| ... |
... |
@@ -336,21 +336,24 @@ class GeckoViewTest : BaseSessionTest() { |
|
336
|
336
|
val autofills =
|
|
337
|
337
|
mapOf(
|
|
338
|
338
|
"#user1" to "username@xxxxxxxxxxx",
|
|
339
|
|
- "#user2" to "username@xxxxxxxxxxx",
|
|
340
|
339
|
"#pass1" to "test-password",
|
|
341
|
|
- "#pass2" to "test-password",
|
|
342
|
340
|
)
|
|
|
341
|
+ val notFilled = listOf("#user2", "#pass2")
|
|
|
342
|
+
|
|
|
343
|
+ // Only the form containing the focused field is filled.
|
|
|
344
|
+ val promises = autofills.map { entry ->
|
|
|
345
|
+ mainSession.evaluatePromiseJS(
|
|
|
346
|
+ """
|
|
|
347
|
+ getData('${entry.key}', '${entry.value}')
|
|
|
348
|
+ """
|
|
|
349
|
+ )
|
|
|
350
|
+ }
|
|
343
|
351
|
|
|
344
|
|
- // Set up promises to monitor the values changing.
|
|
345
|
|
- val promises =
|
|
346
|
|
- autofills.map { entry ->
|
|
347
|
|
- // Repeat each test with both the top document and the iframe document.
|
|
348
|
|
- mainSession.evaluatePromiseJS(
|
|
349
|
|
- """
|
|
350
|
|
- window.getDataForAllFrames('${entry.key}', '${entry.value}')
|
|
351
|
|
- """,
|
|
352
|
|
- )
|
|
353
|
|
- }
|
|
|
352
|
+ mainSession.evaluateJS("document.querySelector('#user1').focus()")
|
|
|
353
|
+ UiThreadUtils.waitForCondition(
|
|
|
354
|
+ { mainSession.autofillSession.focused != null },
|
|
|
355
|
+ env.defaultTimeoutMillis,
|
|
|
356
|
+ )
|
|
354
|
357
|
|
|
355
|
358
|
activityRule.scenario.onActivity {
|
|
356
|
359
|
val root = MockViewStructure(View.NO_ID)
|
| ... |
... |
@@ -374,19 +377,33 @@ class GeckoViewTest : BaseSessionTest() { |
|
374
|
377
|
it.view.setSession(session)
|
|
375
|
378
|
|
|
376
|
379
|
// Wait on the promises and check for correct values.
|
|
377
|
|
- for (values in promises.map { p -> p.value.asJsonArray() }) {
|
|
378
|
|
- for (i in 0 until values.length()) {
|
|
379
|
|
- val (key, actual, expected, eventInterface) = values.get(i).asJSList<String>()
|
|
380
|
|
-
|
|
381
|
|
- assertThat("Auto-filled value must match ($key)", actual, equalTo(expected))
|
|
382
|
|
- assertThat(
|
|
383
|
|
- "input event should be dispatched with InputEvent interface",
|
|
384
|
|
- eventInterface,
|
|
385
|
|
- equalTo("InputEvent"),
|
|
386
|
|
- )
|
|
387
|
|
- }
|
|
|
380
|
+ for (values in promises.map { p -> p.value.asJSList<String>() }) {
|
|
|
381
|
+ val (key, actual, expected, eventInterface) = values
|
|
|
382
|
+
|
|
|
383
|
+ assertThat("Auto-filled value must match ($key)", actual, equalTo(expected))
|
|
|
384
|
+ assertThat(
|
|
|
385
|
+ "input event should be dispatched with InputEvent interface",
|
|
|
386
|
+ eventInterface,
|
|
|
387
|
+ equalTo("InputEvent"),
|
|
|
388
|
+ )
|
|
388
|
389
|
}
|
|
389
|
390
|
}
|
|
|
391
|
+
|
|
|
392
|
+ for (key in autofills.keys + notFilled) {
|
|
|
393
|
+ assertThat(
|
|
|
394
|
+ "Field in the unfocused iframe must not be filled ($key)",
|
|
|
395
|
+ mainSession.evaluatePromiseJS("window.getIframeValue('$key')").value as String,
|
|
|
396
|
+ equalTo("foo"),
|
|
|
397
|
+ )
|
|
|
398
|
+ }
|
|
|
399
|
+
|
|
|
400
|
+ for (key in notFilled) {
|
|
|
401
|
+ assertThat(
|
|
|
402
|
+ "Field outside the focused form must not be filled ($key)",
|
|
|
403
|
+ mainSession.evaluateJS("document.querySelector('$key').value") as String,
|
|
|
404
|
+ equalTo("foo"),
|
|
|
405
|
+ )
|
|
|
406
|
+ }
|
|
390
|
407
|
}
|
|
391
|
408
|
|
|
392
|
409
|
@Test
|
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java
| ... |
... |
@@ -466,7 +466,9 @@ public class Autofill { |
|
466
|
466
|
public void fillViewStructure(
|
|
467
|
467
|
@NonNull final View view, @NonNull final ViewStructure structure, final int flags) {
|
|
468
|
468
|
ThreadUtils.assertOnUiThread();
|
|
469
|
|
- fillViewStructure(getRoot(), view, structure, flags);
|
|
|
469
|
+ final Node focused = getFocused();
|
|
|
470
|
+ final Node root = focused != null ? focused.getRoot() : null;
|
|
|
471
|
+ fillViewStructure(root != null ? root : getRoot(), view, structure, flags);
|
|
470
|
472
|
}
|
|
471
|
473
|
|
|
472
|
474
|
/**
|
modules/libpref/init/StaticPrefList.yaml
| ... |
... |
@@ -19586,10 +19586,6 @@ |
|
19586
|
19586
|
# dispatched to nearby elements that are sensitive to the event. See
|
|
19587
|
19587
|
# PositionedEventTargeting.cpp. The 'mm' prefs define a rectangle around the
|
|
19588
|
19588
|
# nominal event target point within which we will search for suitable elements.
|
|
19589
|
|
-# 'visitedWeight' is a percentage weight; a value > 100 makes a visited link be
|
|
19590
|
|
-# treated as further away from the event target than it really is, while a
|
|
19591
|
|
-# value < 100 makes a visited link be treated as closer to the event target
|
|
19592
|
|
-# than it really is.
|
|
19593
|
19589
|
|
|
19594
|
19590
|
- name: ui.touch.radius.enabled
|
|
19595
|
19591
|
type: bool
|
| ... |
... |
@@ -19639,11 +19635,6 @@ |
|
19639
|
19635
|
value: true
|
|
19640
|
19636
|
mirror: always
|
|
19641
|
19637
|
|
|
19642
|
|
-- name: ui.touch.radius.visitedWeight
|
|
19643
|
|
- type: uint32_t
|
|
19644
|
|
- value: 120
|
|
19645
|
|
- mirror: always
|
|
19646
|
|
-
|
|
19647
|
19638
|
- name: ui.mouse.radius.enabled
|
|
19648
|
19639
|
type: bool
|
|
19649
|
19640
|
value: @IS_ANDROID@
|
| ... |
... |
@@ -19685,11 +19676,6 @@ |
|
19685
|
19676
|
#endif
|
|
19686
|
19677
|
mirror: always
|
|
19687
|
19678
|
|
|
19688
|
|
-- name: ui.mouse.radius.visitedWeight
|
|
19689
|
|
- type: uint32_t
|
|
19690
|
|
- value: 120
|
|
19691
|
|
- mirror: always
|
|
19692
|
|
-
|
|
19693
|
19679
|
- name: ui.mouse.radius.reposition
|
|
19694
|
19680
|
type: bool
|
|
19695
|
19681
|
value: @IS_ANDROID@
|
testing/web-platform/tests/resource-timing/no-entries-for-cached-import-of-cross-origin-css.html
|
|
1
|
+<!DOCTYPE HTML>
|
|
|
2
|
+<meta charset=utf-8>
|
|
|
3
|
+<title>Resource timing entries for cached @import children of stylesheets</title>
|
|
|
4
|
+<link rel="help" href="">"https://bugzilla.mozilla.org/show_bug.cgi?id=2083733">
|
|
|
5
|
+<script src="">"/resources/testharness.js"></script>
|
|
|
6
|
+<script src="">"/resources/testharnessreport.js"></script>
|
|
|
7
|
+<script src="">"/common/get-host-info.sub.js"></script>
|
|
|
8
|
+<script src="">"/common/utils.js"></script>
|
|
|
9
|
+<body>
|
|
|
10
|
+<script>
|
|
|
11
|
+const {ORIGIN, HTTP_REMOTE_ORIGIN} = get_host_info();
|
|
|
12
|
+const RESOURCES = "/resource-timing/resources/";
|
|
|
13
|
+
|
|
|
14
|
+async function loadInFrame(t, href) {
|
|
|
15
|
+ const iframe = document.createElement("iframe");
|
|
|
16
|
+ iframe.srcdoc = `<link rel="stylesheet" href=""p">${href}">`;
|
|
|
17
|
+ await new Promise(resolve => {
|
|
|
18
|
+ iframe.onload = resolve;
|
|
|
19
|
+ document.body.appendChild(iframe);
|
|
|
20
|
+ });
|
|
|
21
|
+ t.add_cleanup(() => iframe.remove());
|
|
|
22
|
+ return iframe.contentWindow;
|
|
|
23
|
+}
|
|
|
24
|
+
|
|
|
25
|
+// The first load caches the child stylesheet, but not the parent, which is
|
|
|
26
|
+// no-store, so the second load re-parses the parent and gets the child from
|
|
|
27
|
+// the cache.
|
|
|
28
|
+async function loadTwice(t, parentOrigin, childOrigin) {
|
|
|
29
|
+ const id = token();
|
|
|
30
|
+ const child = `${childOrigin}${RESOURCES}cacheable-import-child.css?${id}`;
|
|
|
31
|
+ const parent = v =>
|
|
|
32
|
+ `${parentOrigin}${RESOURCES}no-store-importer.sub.css?import=${encodeURIComponent(child)}&v=${v}`;
|
|
|
33
|
+ await loadInFrame(t, parent(1));
|
|
|
34
|
+ const win = await loadInFrame(t, parent(2));
|
|
|
35
|
+ await new Promise(resolve => t.step_timeout(resolve, 0));
|
|
|
36
|
+ assert_equals(win.performance.getEntriesByName(parent(2)).length, 1,
|
|
|
37
|
+ "Parent stylesheet should be in the timeline");
|
|
|
38
|
+ return win.performance.getEntriesByName(child).length;
|
|
|
39
|
+}
|
|
|
40
|
+
|
|
|
41
|
+promise_test(async t => {
|
|
|
42
|
+ assert_equals(await loadTwice(t, HTTP_REMOTE_ORIGIN, HTTP_REMOTE_ORIGIN), 0);
|
|
|
43
|
+}, "Cached @import children of cross-origin stylesheets are not in the timeline");
|
|
|
44
|
+
|
|
|
45
|
+promise_test(async t => {
|
|
|
46
|
+ assert_equals(await loadTwice(t, ORIGIN, ORIGIN), 1);
|
|
|
47
|
+}, "Cached same-origin @import children of same-origin stylesheets are in the timeline");
|
|
|
48
|
+
|
|
|
49
|
+promise_test(async t => {
|
|
|
50
|
+ assert_equals(await loadTwice(t, ORIGIN, HTTP_REMOTE_ORIGIN), 1);
|
|
|
51
|
+}, "Cached cross-origin @import children of same-origin stylesheets are in the timeline");
|
|
|
52
|
+</script>
|
|
|
53
|
+</body> |
testing/web-platform/tests/resource-timing/resources/cacheable-import-child.css
|
|
1
|
+.child { color: blue } |
testing/web-platform/tests/resource-timing/resources/cacheable-import-child.css.headers
|
|
1
|
+Content-Type: text/css
|
|
|
2
|
+Cache-Control: max-age=600 |
testing/web-platform/tests/resource-timing/resources/no-store-importer.sub.css
|
|
1
|
+@import "{{GET[import]}}"; |
testing/web-platform/tests/resource-timing/resources/no-store-importer.sub.css.headers
|
|
1
|
+Content-Type: text/css
|
|
|
2
|
+Cache-Control: no-store |
tools/profiler/gecko/nsProfiler.cpp
| ... |
... |
@@ -1320,8 +1320,11 @@ RefPtr<nsProfiler::GatheringPromise> nsProfiler::StartGathering( |
|
1320
|
1320
|
aEvent.append(Json::Value::UInt64(childPid));
|
|
1321
|
1321
|
aEvent.append(Json::Value::UInt64{profileShmem.Size<char>()});
|
|
1322
|
1322
|
});
|
|
|
1323
|
+ const size_t profileLength =
|
|
|
1324
|
+ profileShmem.Size<char>() > 0 ? profileShmem.Size<char>() - 1
|
|
|
1325
|
+ : 0;
|
|
1323
|
1326
|
const nsDependentCSubstring profileString(
|
|
1324
|
|
- profileShmem.get<char>(), profileShmem.Size<char>() - 1);
|
|
|
1327
|
+ profileShmem.get<char>(), profileLength);
|
|
1325
|
1328
|
if (profileString.IsEmpty() || profileString[0] != '*') {
|
|
1326
|
1329
|
self->GatheredOOPProfile(
|
|
1327
|
1330
|
childPid, profileString,
|
|