From 93fa5a236701854932b9de67ed785d3feb2693ef Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Thu, 14 Feb 2019 13:37:58 +0000 Subject: [PATCH 01/84] Bug 1398095 - [wdspec] Use "script timeout" instead of "timeout error" for promise tests. r=ato Differential Revision: https://phabricator.services.mozilla.com/D19751 --HG-- extra : moz-landing-system : lando --- .../tests/webdriver/tests/execute_script/promise.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/testing/web-platform/tests/webdriver/tests/execute_script/promise.py b/testing/web-platform/tests/webdriver/tests/execute_script/promise.py index 1eab7822c5c2..b35746292515 100644 --- a/testing/web-platform/tests/webdriver/tests/execute_script/promise.py +++ b/testing/web-platform/tests/webdriver/tests/execute_script/promise.py @@ -1,6 +1,4 @@ -import pytest - -from tests.support.asserts import assert_dialog_handled, assert_error, assert_success +from tests.support.asserts import assert_error, assert_success def execute_script(session, script, args=None): @@ -98,7 +96,7 @@ def test_promise_resolve_timeout(session): ) ); """) - assert_error(response, "timeout error") + assert_error(response, "script timeout") def test_promise_reject_timeout(session): @@ -111,4 +109,4 @@ def test_promise_reject_timeout(session): ) ); """) - assert_error(response, "timeout error") \ No newline at end of file + assert_error(response, "script timeout") From 3d93798308356f20c3702168e6a43886a46a2844 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Thu, 14 Feb 2019 13:40:51 +0000 Subject: [PATCH 02/84] Bug 1527884 - WebRender version 0.60.0. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D19780 --HG-- extra : moz-landing-system : lando --- Cargo.lock | 8 ++++---- gfx/webrender_bindings/Cargo.toml | 2 +- gfx/wr/webrender/Cargo.toml | 4 ++-- gfx/wr/webrender_api/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index befc4c926385..bc6014a8a592 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3077,7 +3077,7 @@ dependencies = [ [[package]] name = "webrender" -version = "0.59.0" +version = "0.60.0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3105,14 +3105,14 @@ dependencies = [ "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.58.0", + "webrender_api 0.60.0", "webrender_build 0.0.1", "wr_malloc_size_of 0.0.1", ] [[package]] name = "webrender_api" -version = "0.58.0" +version = "0.60.0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3148,7 +3148,7 @@ dependencies = [ "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.59.0", + "webrender 0.60.0", ] [[package]] diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index 1258ea2807b9..25264cda83b8 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -18,7 +18,7 @@ fxhash = "0.2.1" [dependencies.webrender] path = "../wr/webrender" -version = "0.59.0" +version = "0.60.0" default-features = false features = ["capture", "serialize_program"] diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml index 651f76aabd4d..26223f9fc443 100644 --- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.59.0" +version = "0.60.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" @@ -46,7 +46,7 @@ sha2 = "0.8" smallvec = "0.6" thread_profiler = "0.1.1" time = "0.1" -webrender_api = { version = "0.58.0", path = "../webrender_api" } +webrender_api = { version = "0.60.0", path = "../webrender_api" } webrender_build = { version = "0.0.1", path = "../webrender_build" } wr_malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of" } ws = { optional = true, version = "0.7.3" } diff --git a/gfx/wr/webrender_api/Cargo.toml b/gfx/wr/webrender_api/Cargo.toml index 967c8b14f477..e919800ba147 100644 --- a/gfx/wr/webrender_api/Cargo.toml +++ b/gfx/wr/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.58.0" +version = "0.60.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" From ec77852b6760cc8e4dace2257e881abd4f5f2881 Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Thu, 14 Feb 2019 13:38:41 +0000 Subject: [PATCH 03/84] Bug 1398095 - [marionette] Always clean-up registered timers and listeners in evaluate.sandbox(). r=ato Depends on D19751 Differential Revision: https://phabricator.services.mozilla.com/D19753 --HG-- extra : moz-landing-system : lando --- testing/marionette/evaluate.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testing/marionette/evaluate.js b/testing/marionette/evaluate.js index d5c2b818e72c..02fed7671c5b 100644 --- a/testing/marionette/evaluate.js +++ b/testing/marionette/evaluate.js @@ -137,9 +137,12 @@ evaluate.sandbox = function(sb, script, args = [], }); return promise.then(res => { + return res; + }, error => { + throw error; + }).finally(() => { clearTimeout(scriptTimeoutID); sb.window.removeEventListener("unload", unloadHandler); - return res; }); }; From 39806892a54dd9a5adda8ad3ee21ee2f6996e66a Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Thu, 14 Feb 2019 13:39:19 +0000 Subject: [PATCH 04/84] Bug 1398095 - [marionette] Use promises internally for Execute (Async) Script. r=ato Depends on D19753 Differential Revision: https://phabricator.services.mozilla.com/D19755 --HG-- extra : moz-landing-system : lando --- testing/marionette/evaluate.js | 62 +++++++++++-------- .../tests/execute_script/promise.py.ini | 19 ------ .../webdriver/tests/execute_script/promise.py | 28 ++++----- 3 files changed, 50 insertions(+), 59 deletions(-) diff --git a/testing/marionette/evaluate.js b/testing/marionette/evaluate.js index 02fed7671c5b..69d700ce1fa9 100644 --- a/testing/marionette/evaluate.js +++ b/testing/marionette/evaluate.js @@ -91,18 +91,21 @@ evaluate.sandbox = function(sb, script, args = [], line = 0, timeout = DEFAULT_TIMEOUT, } = {}) { - let scriptTimeoutID, unloadHandler; + let unloadHandler; + + // timeout handler + let scriptTimeoutID, timeoutPromise; + if (timeout !== null) { + timeoutPromise = new Promise((resolve, reject) => { + scriptTimeoutID = setTimeout(() => { + reject(new ScriptTimeoutError(`Timed out after ${timeout} ms`)); + }, timeout); + }); + } let promise = new Promise((resolve, reject) => { let src = ""; sb[COMPLETE] = resolve; - unloadHandler = sandbox.cloneInto( - () => reject(new JavaScriptError("Document was unloaded")), - sb); - - if (async) { - sb[CALLBACK] = sb[COMPLETE]; - } sb[ARGUMENTS] = sandbox.cloneInto(args, sb); // callback function made private @@ -117,29 +120,36 @@ evaluate.sandbox = function(sb, script, args = [], ${script} }).apply(null, ${ARGUMENTS})`; - // timeout and unload handlers - if (timeout !== null) { - scriptTimeoutID = setTimeout(() => reject(new ScriptTimeoutError( - `Timed out after ${timeout} ms`)), timeout); - } + unloadHandler = sandbox.cloneInto( + () => reject(new JavaScriptError("Document was unloaded")), sb); sb.window.onunload = unloadHandler; - let res; - try { - res = Cu.evalInSandbox(src, sb, "1.8", file, line); - } catch (e) { - reject(new JavaScriptError(e)); - } + let promises = [ + Cu.evalInSandbox(src, sb, "1.8", file, line), + timeoutPromise, + ]; - if (!async) { - resolve(res); - } + // Wait for the immediate result of calling evalInSandbox, or a timeout. + // Only resolve the promise if the scriptPromise was resolved and is not + // async, because the latter has to call resolve() itself. + Promise.race(promises).then(value => { + if (!async) { + resolve(value); + } + }, err => { + reject(err); + }); }); - return promise.then(res => { - return res; - }, error => { - throw error; + // This block is mainly for async scripts, which escape the inner promise + // when calling resolve() on their own. The timeout promise will be re-used + // to break out after the initially setup timeout. + return Promise.race([promise, timeoutPromise]).catch(err => { + // Only raise valid errors for both the sync and async scripts. + if (err instanceof ScriptTimeoutError) { + throw err; + } + throw new JavaScriptError(err); }).finally(() => { clearTimeout(scriptTimeoutID); sb.window.removeEventListener("unload", unloadHandler); diff --git a/testing/web-platform/meta/webdriver/tests/execute_script/promise.py.ini b/testing/web-platform/meta/webdriver/tests/execute_script/promise.py.ini index f1544e24b8ba..abce0b314ed7 100644 --- a/testing/web-platform/meta/webdriver/tests/execute_script/promise.py.ini +++ b/testing/web-platform/meta/webdriver/tests/execute_script/promise.py.ini @@ -1,22 +1,3 @@ [promise.py] - [test_promise_timeout] - expected: FAIL - - [test_promise_reject_timeout] - expected: FAIL - - [test_promise_resolve_timeout] - expected: FAIL - [test_await_promise_resolve] expected: FAIL - - [test_promise_all_reject] - expected: FAIL - - [test_promise_reject_delayed] - expected: FAIL - - [test_promise_reject] - expected: FAIL - diff --git a/testing/web-platform/tests/webdriver/tests/execute_script/promise.py b/testing/web-platform/tests/webdriver/tests/execute_script/promise.py index b35746292515..8bb637853ccd 100644 --- a/testing/web-platform/tests/webdriver/tests/execute_script/promise.py +++ b/testing/web-platform/tests/webdriver/tests/execute_script/promise.py @@ -43,12 +43,25 @@ def test_promise_all_resolve(session): def test_await_promise_resolve(session): response = execute_script(session, """ - const res = await Promise.resolve('foobar'); + let res = await Promise.resolve('foobar'); return res; """) assert_success(response, "foobar") +def test_promise_resolve_timeout(session): + session.timeouts.script = .1 + response = execute_script(session, """ + return new Promise( + (resolve) => setTimeout( + () => resolve(), + 1000 + ) + ); + """) + assert_error(response, "script timeout") + + def test_promise_reject(session): response = execute_script(session, """ return Promise.reject(new Error('my error')); @@ -86,19 +99,6 @@ def test_await_promise_reject(session): assert_error(response, "javascript error") -def test_promise_resolve_timeout(session): - session.timeouts.script = .1 - response = execute_script(session, """ - return new Promise( - (resolve) => setTimeout( - () => resolve(), - 1000 - ) - ); - """) - assert_error(response, "script timeout") - - def test_promise_reject_timeout(session): session.timeouts.script = .1 response = execute_script(session, """ From 72f690a447c3b4d8509f87e0eeab050a3f50c3d8 Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Thu, 14 Feb 2019 13:39:55 +0000 Subject: [PATCH 05/84] Bug 1398095 - [wdspec] Add promise tests for Execute Async Script command. r=ato Depends on D19755 Differential Revision: https://phabricator.services.mozilla.com/D19757 --HG-- extra : moz-landing-system : lando --- .../tests/execute_async_script/promise.py.ini | 3 + .../tests/execute_async_script/promise.py | 127 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 testing/web-platform/meta/webdriver/tests/execute_async_script/promise.py.ini create mode 100644 testing/web-platform/tests/webdriver/tests/execute_async_script/promise.py diff --git a/testing/web-platform/meta/webdriver/tests/execute_async_script/promise.py.ini b/testing/web-platform/meta/webdriver/tests/execute_async_script/promise.py.ini new file mode 100644 index 000000000000..abce0b314ed7 --- /dev/null +++ b/testing/web-platform/meta/webdriver/tests/execute_async_script/promise.py.ini @@ -0,0 +1,3 @@ +[promise.py] + [test_await_promise_resolve] + expected: FAIL diff --git a/testing/web-platform/tests/webdriver/tests/execute_async_script/promise.py b/testing/web-platform/tests/webdriver/tests/execute_async_script/promise.py new file mode 100644 index 000000000000..8b6d7d9157b2 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/execute_async_script/promise.py @@ -0,0 +1,127 @@ +from tests.support.asserts import assert_error, assert_success + + +def execute_async_script(session, script, args=None): + if args is None: + args = [] + body = {"script": script, "args": args} + + return session.transport.send( + "POST", "/session/{session_id}/execute/async".format(**vars(session)), + body) + + +def test_promise_resolve(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + resolve(Promise.resolve('foobar')); + """) + assert_success(response, "foobar") + + +def test_promise_resolve_delayed(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = new Promise( + (resolve) => setTimeout( + () => resolve('foobar'), + 50 + ) + ); + resolve(promise); + """) + assert_success(response, "foobar") + + +def test_promise_all_resolve(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = Promise.all([ + Promise.resolve(1), + Promise.resolve(2) + ]); + resolve(promise); + """) + assert_success(response, [1, 2]) + + +def test_await_promise_resolve(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + let res = await Promise.resolve('foobar'); + resolve(res); + """) + assert_success(response, "foobar") + + +def test_promise_resolve_timeout(session): + session.timeouts.script = .1 + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = new Promise( + (resolve) => setTimeout( + () => resolve(), + 1000 + ) + ); + resolve(promise); + """) + assert_error(response, "script timeout") + + +def test_promise_reject(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + resolve(Promise.reject(new Error('my error'))); + """) + assert_error(response, "javascript error") + + +def test_promise_reject_delayed(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = new Promise( + (resolve, reject) => setTimeout( + () => reject(new Error('my error')), + 50 + ) + ); + resolve(promise); + """) + assert_error(response, "javascript error") + + +def test_promise_all_reject(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = Promise.all([ + Promise.resolve(1), + Promise.reject(new Error('error')) + ]); + resolve(promise); + """) + assert_error(response, "javascript error") + + +def test_await_promise_reject(session): + response = execute_async_script(session, """ + let resolve = arguments[0]; + await Promise.reject(new Error('my error')); + resolve('foo'); + """) + assert_error(response, "javascript error") + + +def test_promise_reject_timeout(session): + session.timeouts.script = .1 + response = execute_async_script(session, """ + let resolve = arguments[0]; + let promise = new Promise( + (resolve, reject) => setTimeout( + () => reject(new Error('my error')), + 1000 + ) + ); + resolve(promise); + """) + assert_error(response, "script timeout") From 5631d74c0a08b1a855ce07809072b3b2ba145bbf Mon Sep 17 00:00:00 2001 From: Nicolas Chevobbe Date: Mon, 11 Feb 2019 17:22:12 +0000 Subject: [PATCH 06/84] Bug 1525682 - Add `errorMessageName` in ConsoleMessage; r=bgrins. This will be used in telemetry events. Also, we add `errorMessageName` in evaluation result packets. Stubs are generated so they include the new property. Differential Revision: https://phabricator.services.mozilla.com/D18925 --HG-- extra : moz-landing-system : lando --- .../test/fixtures/stubs/consoleApi.js | 55 +++++++++++++++++++ .../test/fixtures/stubs/cssMessage.js | 2 + .../test/fixtures/stubs/evaluationResult.js | 4 ++ .../test/fixtures/stubs/pageError.js | 5 ++ devtools/client/webconsole/types.js | 1 + devtools/client/webconsole/utils/messages.js | 3 + devtools/server/actors/webconsole.js | 4 +- 7 files changed, 73 insertions(+), 1 deletion(-) diff --git a/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js b/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js index 0912fe8b906b..912f8cb1520c 100644 --- a/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js +++ b/devtools/client/webconsole/test/fixtures/stubs/consoleApi.js @@ -34,6 +34,7 @@ stubPreparedMessages.set(`console.log('foobar', 'test')`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -64,6 +65,7 @@ stubPreparedMessages.set(`console.log(undefined)`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -92,6 +94,7 @@ stubPreparedMessages.set(`console.warn('danger, will robinson!')`, new ConsoleMe "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -122,6 +125,7 @@ stubPreparedMessages.set(`console.log(NaN)`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -152,6 +156,7 @@ stubPreparedMessages.set(`console.log(null)`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -180,6 +185,7 @@ stubPreparedMessages.set(`console.log('鼬')`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -208,6 +214,7 @@ stubPreparedMessages.set(`console.clear()`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -234,6 +241,7 @@ stubPreparedMessages.set(`console.count('bar')`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -292,6 +300,7 @@ stubPreparedMessages.set(`console.assert(false, {message: 'foobar'})`, new Conso "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -320,6 +329,7 @@ stubPreparedMessages.set(`console.log('hello \nfrom \rthe \"string world!')`, ne "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -348,6 +358,7 @@ stubPreparedMessages.set(`console.log('úṇĩçödê țĕșť')`, new ConsoleMe "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -388,6 +399,7 @@ stubPreparedMessages.set(`console.dirxml(window)`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -434,6 +446,7 @@ stubPreparedMessages.set(`console.log('myarray', ['red', 'green', 'blue'])`, new "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -472,6 +485,7 @@ stubPreparedMessages.set(`console.log('myregex', /a.b.c/)`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -517,6 +531,7 @@ stubPreparedMessages.set(`console.table(['red', 'green', 'blue']);`, new Console "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -581,6 +596,7 @@ stubPreparedMessages.set(`console.log('myobject', {red: 'redValue', green: 'gree "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -609,6 +625,7 @@ stubPreparedMessages.set(`console.debug('debug message');`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -637,6 +654,7 @@ stubPreparedMessages.set(`console.info('info message');`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -672,6 +690,7 @@ stubPreparedMessages.set(`console.error('error message');`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -723,6 +742,7 @@ stubPreparedMessages.set(`console.log('mymap')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -768,6 +788,7 @@ stubPreparedMessages.set(`console.log('myset')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -813,6 +834,7 @@ stubPreparedMessages.set(`console.trace()`, new ConsoleMessage({ "column": 11 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -902,6 +924,7 @@ stubPreparedMessages.set(`console.trace('bar', {'foo': 'bar'}, [1,2,3])`, new Co "column": 11 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -928,6 +951,7 @@ stubPreparedMessages.set(`console.time('bar')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -954,6 +978,7 @@ stubPreparedMessages.set(`timerAlreadyExists`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -982,6 +1007,7 @@ stubPreparedMessages.set(`console.timeLog('bar') - 1`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1035,6 +1061,7 @@ stubPreparedMessages.set(`console.timeLog('bar') - 2`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1061,6 +1088,7 @@ stubPreparedMessages.set(`console.timeEnd('bar')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1087,6 +1115,7 @@ stubPreparedMessages.set(`timeEnd.timerDoesntExist`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1113,6 +1142,7 @@ stubPreparedMessages.set(`timeLog.timerDoesntExist`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1141,6 +1171,7 @@ stubPreparedMessages.set(`console.table('bar')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1186,6 +1217,7 @@ stubPreparedMessages.set(`console.table(['a', 'b', 'c'])`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1214,6 +1246,7 @@ stubPreparedMessages.set(`console.group('bar')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1240,6 +1273,7 @@ stubPreparedMessages.set(`console.groupEnd('bar')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1268,6 +1302,7 @@ stubPreparedMessages.set(`console.groupCollapsed('foo')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1294,6 +1329,7 @@ stubPreparedMessages.set(`console.groupEnd('foo')`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1322,6 +1358,7 @@ stubPreparedMessages.set(`console.group()`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1348,6 +1385,7 @@ stubPreparedMessages.set(`console.groupEnd()`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1377,6 +1415,7 @@ stubPreparedMessages.set(`console.log(%cfoobar)`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [ "color:blue; font-size:1.3em; background:url('http://example.com/test'); position:absolute; top:10px; ", @@ -1410,6 +1449,7 @@ stubPreparedMessages.set(`console.log("%cHello%c|%cWorld")`, new ConsoleMessage( "column": 11 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [ "color:red", @@ -1443,6 +1483,7 @@ stubPreparedMessages.set(`console.group(%cfoo%cbar)`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [ "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px", @@ -1472,6 +1513,7 @@ stubPreparedMessages.set(`console.groupEnd(%cfoo%cbar)`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1501,6 +1543,7 @@ stubPreparedMessages.set(`console.groupCollapsed(%cfoo%cbaz)`, new ConsoleMessag "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [ "color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px", @@ -1530,6 +1573,7 @@ stubPreparedMessages.set(`console.groupEnd(%cfoo%cbaz)`, new ConsoleMessage({ "column": 9 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1599,6 +1643,7 @@ stubPreparedMessages.set(`console.dir({C, M, Y, K})`, new ConsoleMessage({ "column": 35 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1625,6 +1670,7 @@ stubPreparedMessages.set(`console.count | default: 1`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1651,6 +1697,7 @@ stubPreparedMessages.set(`console.count | default: 2`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1677,6 +1724,7 @@ stubPreparedMessages.set(`console.count | test counter: 1`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1703,6 +1751,7 @@ stubPreparedMessages.set(`console.count | test counter: 2`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1729,6 +1778,7 @@ stubPreparedMessages.set(`console.count | default: 3`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1757,6 +1807,7 @@ stubPreparedMessages.set(`console.count | clear`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1783,6 +1834,7 @@ stubPreparedMessages.set(`console.count | default: 4`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1809,6 +1861,7 @@ stubPreparedMessages.set(`console.count | test counter: 3`, new ConsoleMessage({ "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1835,6 +1888,7 @@ stubPreparedMessages.set(`console.countReset | test counter: 0`, new ConsoleMess "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, @@ -1861,6 +1915,7 @@ stubPreparedMessages.set(`console.countReset | counterDoesntExist`, new ConsoleM "column": 13 }, "groupId": null, + "errorMessageName": null, "exceptionDocURL": null, "userProvidedStyles": [], "notes": null, diff --git a/devtools/client/webconsole/test/fixtures/stubs/cssMessage.js b/devtools/client/webconsole/test/fixtures/stubs/cssMessage.js index 6b5f756d5837..84f1caffc1e6 100644 --- a/devtools/client/webconsole/test/fixtures/stubs/cssMessage.js +++ b/devtools/client/webconsole/test/fixtures/stubs/cssMessage.js @@ -31,6 +31,7 @@ stubPreparedMessages.set(`Unknown property ‘such-unknown-property’. Declara "column": 25 }, "groupId": null, + "errorMessageName": "", "userProvidedStyles": null, "notes": null, "indent": 0, @@ -56,6 +57,7 @@ stubPreparedMessages.set(`Error in parsing value for ‘padding-top’. Declara "column": 16 }, "groupId": null, + "errorMessageName": "", "userProvidedStyles": null, "notes": null, "indent": 0, diff --git a/devtools/client/webconsole/test/fixtures/stubs/evaluationResult.js b/devtools/client/webconsole/test/fixtures/stubs/evaluationResult.js index 22c9b5627c14..ef038a37a450 100644 --- a/devtools/client/webconsole/test/fixtures/stubs/evaluationResult.js +++ b/devtools/client/webconsole/test/fixtures/stubs/evaluationResult.js @@ -67,6 +67,7 @@ stubPreparedMessages.set(`asdf()`, new ConsoleMessage({ "column": 1 }, "groupId": null, + "errorMessageName": "JSMSG_NOT_DEFINED", "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default", "userProvidedStyles": null, "notes": null, @@ -96,6 +97,7 @@ stubPreparedMessages.set(`1 + @`, new ConsoleMessage({ "column": 4 }, "groupId": null, + "errorMessageName": "JSMSG_ILLEGAL_CHARACTER", "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default", "userProvidedStyles": null, "notes": null, @@ -320,6 +322,7 @@ stubPackets.set(`asdf()`, { }, "exceptionMessage": "ReferenceError: asdf is not defined", "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default", + "errorMessageName": "JSMSG_NOT_DEFINED", "frame": { "source": "debugger eval code", "line": 1, @@ -356,6 +359,7 @@ stubPackets.set(`1 + @`, { }, "exceptionMessage": "SyntaxError: illegal character", "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default", + "errorMessageName": "JSMSG_ILLEGAL_CHARACTER", "frame": { "source": "debugger eval code", "line": 1, diff --git a/devtools/client/webconsole/test/fixtures/stubs/pageError.js b/devtools/client/webconsole/test/fixtures/stubs/pageError.js index e7a01c926353..0e64d8868c5a 100644 --- a/devtools/client/webconsole/test/fixtures/stubs/pageError.js +++ b/devtools/client/webconsole/test/fixtures/stubs/pageError.js @@ -62,6 +62,7 @@ stubPreparedMessages.set(`ReferenceError: asdf is not defined`, new ConsoleMessa "column": 5 }, "groupId": null, + "errorMessageName": "JSMSG_NOT_DEFINED", "exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default", "userProvidedStyles": null, "notes": null, @@ -101,6 +102,7 @@ stubPreparedMessages.set(`SyntaxError: redeclaration of let a`, new ConsoleMessa "column": 9 }, "groupId": null, + "errorMessageName": "JSMSG_REDECLARED_VAR", "userProvidedStyles": null, "notes": [ { @@ -159,6 +161,7 @@ stubPreparedMessages.set(`TypeError longString message`, new ConsoleMessage({ "column": 7 }, "groupId": null, + "errorMessageName": "", "userProvidedStyles": null, "notes": null, "indent": 0, @@ -180,6 +183,7 @@ stubPreparedMessages.set(`throw ""`, new ConsoleMessage({ "stacktrace": null, "frame": null, "groupId": null, + "errorMessageName": "JSMSG_UNCAUGHT_EXCEPTION", "userProvidedStyles": null, "notes": null, "indent": 0, @@ -201,6 +205,7 @@ stubPreparedMessages.set(`throw "tomato"`, new ConsoleMessage({ "stacktrace": null, "frame": null, "groupId": null, + "errorMessageName": "JSMSG_UNCAUGHT_EXCEPTION", "userProvidedStyles": null, "notes": null, "indent": 0, diff --git a/devtools/client/webconsole/types.js b/devtools/client/webconsole/types.js index 667a5db4ec27..d5f51dafaf49 100644 --- a/devtools/client/webconsole/types.js +++ b/devtools/client/webconsole/types.js @@ -41,6 +41,7 @@ exports.ConsoleMessage = function(props) { stacktrace: null, frame: null, groupId: null, + errorMessageName: null, exceptionDocURL: null, executionPoint: undefined, userProvidedStyles: null, diff --git a/devtools/client/webconsole/utils/messages.js b/devtools/client/webconsole/utils/messages.js index a92075d7bfa8..ff0fce698235 100644 --- a/devtools/client/webconsole/utils/messages.js +++ b/devtools/client/webconsole/utils/messages.js @@ -244,6 +244,7 @@ function transformPageErrorPacket(packet) { messageText: pageError.errorMessage, stacktrace: pageError.stacktrace ? pageError.stacktrace : null, frame, + errorMessageName: pageError.errorMessageName, exceptionDocURL: pageError.exceptionDocURL, timeStamp: pageError.timeStamp, notes: pageError.notes, @@ -275,6 +276,7 @@ function transformNetworkEventPacket(packet) { function transformEvaluationResultPacket(packet) { let { exceptionMessage, + errorMessageName, exceptionDocURL, exception, frame, @@ -310,6 +312,7 @@ function transformEvaluationResultPacket(packet) { level, messageText: exceptionMessage, parameters: [parameter], + errorMessageName, exceptionDocURL, frame, timeStamp, diff --git a/devtools/server/actors/webconsole.js b/devtools/server/actors/webconsole.js index cb00bb962eac..16fe7a127cb5 100644 --- a/devtools/server/actors/webconsole.js +++ b/devtools/server/actors/webconsole.js @@ -1010,7 +1010,7 @@ WebConsoleActor.prototype = const helperResult = evalInfo.helperResult; let result, errorDocURL, errorMessage, errorNotes = null, errorGrip = null, - frame = null, awaitResult; + frame = null, awaitResult, errorMessageName; if (evalResult) { if ("return" in evalResult) { result = evalResult.return; @@ -1058,6 +1058,7 @@ WebConsoleActor.prototype = // object and retrieve its errorMessageName. try { errorDocURL = ErrorDocs.GetURL(error); + errorMessageName = error.errorMessageName; } catch (ex) { // ignored } @@ -1131,6 +1132,7 @@ WebConsoleActor.prototype = exception: errorGrip, exceptionMessage: this._createStringGrip(errorMessage), exceptionDocURL: errorDocURL, + errorMessageName, frame, helperResult: helperResult, notes: errorNotes, From 956a15ad0ecf7e46684427838c8ced86e45f610d Mon Sep 17 00:00:00 2001 From: Nicolas Chevobbe Date: Thu, 14 Feb 2019 13:48:12 +0000 Subject: [PATCH 07/84] Bug 1525682 - Add back the telemetry probe monitoring the error messages issued by SpiderMonkey. r=miker This patch adds the DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED telemetry probe back. It existed in the old frontend and was removed when the old frontend was removed. A test is added to ensure this is working correctly (and that we won't delete it by mistake again in the future). Differential Revision: https://phabricator.services.mozilla.com/D18930 --HG-- extra : moz-landing-system : lando --- .../webconsole/middleware/event-telemetry.js | 13 +++++ .../webconsole/test/mochitest/browser.ini | 1 + .../browser_webconsole_telemetry_js_errors.js | 48 +++++++++++++++++++ .../client/webconsole/test/mochitest/head.js | 1 + 4 files changed, 63 insertions(+) create mode 100644 devtools/client/webconsole/test/mochitest/browser_webconsole_telemetry_js_errors.js diff --git a/devtools/client/webconsole/middleware/event-telemetry.js b/devtools/client/webconsole/middleware/event-telemetry.js index 191890392a74..adaf57908b57 100644 --- a/devtools/client/webconsole/middleware/event-telemetry.js +++ b/devtools/client/webconsole/middleware/event-telemetry.js @@ -8,6 +8,7 @@ const { FILTER_TEXT_SET, FILTER_TOGGLE, DEFAULT_FILTERS_RESET, + MESSAGES_ADD, } = require("devtools/client/webconsole/constants"); /** @@ -37,6 +38,8 @@ function eventTelemetryMiddleware(telemetry, sessionId, store) { telemetry, sessionId, }); + } else if (action.type === MESSAGES_ADD) { + messagesAdd({ action, telemetry }); } return res; @@ -77,4 +80,14 @@ function filterChange({action, state, oldState, telemetry, sessionId}) { }); } +function messagesAdd({ action, telemetry }) { + const {messages} = action; + for (const message of messages) { + if (message.level === "error" && message.source === "javascript") { + telemetry.getKeyedHistogramById("DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED") + .add(message.errorMessageName || "Unknown", true); + } + } +} + module.exports = eventTelemetryMiddleware; diff --git a/devtools/client/webconsole/test/mochitest/browser.ini b/devtools/client/webconsole/test/mochitest/browser.ini index ca7aed6aaaf6..712d603fa133 100644 --- a/devtools/client/webconsole/test/mochitest/browser.ini +++ b/devtools/client/webconsole/test/mochitest/browser.ini @@ -415,6 +415,7 @@ skip-if = verify [browser_webconsole_stacktrace_location_scratchpad_link.js] [browser_webconsole_strict_mode_errors.js] [browser_webconsole_string.js] +[browser_webconsole_telemetry_js_errors.js] [browser_webconsole_telemetry_filters_changed.js] [browser_webconsole_telemetry_jump_to_definition.js] [browser_webconsole_telemetry_object_expanded.js] diff --git a/devtools/client/webconsole/test/mochitest/browser_webconsole_telemetry_js_errors.js b/devtools/client/webconsole/test/mochitest/browser_webconsole_telemetry_js_errors.js new file mode 100644 index 000000000000..c739bb9e113b --- /dev/null +++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_telemetry_js_errors.js @@ -0,0 +1,48 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests the DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED telemetry event. + +"use strict"; + +const TEST_URI = `data:text/html,`; + +add_task(async function() { + startTelemetry(); + + const hud = await openNewTabAndConsole(TEST_URI); + + info("Check that the error message is logged in telemetry with the expected key"); + await waitFor(() => findMessage(hud, "is not a function")); + checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 1); + + await refreshTab(); + + info("Reloading the page (and having the same error) increments the sum"); + await waitFor(() => findMessage(hud, "is not a function")); + checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 2); + + info("Evaluating an expression resulting in the same error increments the sum"); + let onMessage = waitForMessage(hud, "window is not a function"); + hud.jsterm.execute("window()"); + await onMessage; + checkErrorDisplayedTelemetry("JSMSG_NOT_FUNCTION", 3); + + info("Evaluating an expression resulting in another error is logged in telemetry"); + onMessage = waitForMessage(hud, "repeat count must be non-negative"); + hud.jsterm.execute(`"a".repeat(-1)`); + await onMessage; + checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 1); + + onMessage = waitForMessage(hud, "repeat count must be non-negative"); + hud.jsterm.execute(`"b".repeat(-1)`); + await onMessage; + checkErrorDisplayedTelemetry("JSMSG_NEGATIVE_REPETITION_COUNT", 2); +}); + +function checkErrorDisplayedTelemetry(key, count) { + checkTelemetry( + "DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED", key, {0: 0, 1: count, 2: 0}, "array"); +} diff --git a/devtools/client/webconsole/test/mochitest/head.js b/devtools/client/webconsole/test/mochitest/head.js index cf4bc317ba83..1b3d1a3853bd 100644 --- a/devtools/client/webconsole/test/mochitest/head.js +++ b/devtools/client/webconsole/test/mochitest/head.js @@ -3,6 +3,7 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /* eslint no-unused-vars: [2, {"vars": "local"}] */ +/* import-globals-from ../../../shared/test/telemetry-test-helpers.js */ "use strict"; From ccd66c5c51a952c411be4c00e5b8ea0125f96cd0 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 12 Feb 2019 19:45:52 +0000 Subject: [PATCH 08/84] Bug 1518774, r=dragana Differential Revision: https://phabricator.services.mozilla.com/D19536 --HG-- extra : rebase_source : 033d033e7ddbb81214218e4dca356d27c10714d0 extra : source : 46906029338037cc38162736163558eb2284c2bb --- xpcom/io/nsStringStream.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/xpcom/io/nsStringStream.cpp b/xpcom/io/nsStringStream.cpp index 511f2b9034b1..4f687e257bbc 100644 --- a/xpcom/io/nsStringStream.cpp +++ b/xpcom/io/nsStringStream.cpp @@ -22,6 +22,7 @@ #include "nsIClassInfoImpl.h" #include "mozilla/Attributes.h" #include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/ReentrantMonitor.h" #include "nsIIPCSerializableInputStream.h" using namespace mozilla::ipc; @@ -48,7 +49,7 @@ class nsStringInputStream final : public nsIStringInputStream, NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM NS_DECL_NSICLONEABLEINPUTSTREAM - nsStringInputStream() : mOffset(0) { Clear(); } + nsStringInputStream() : mOffset(0), mMon("nsStringInputStream") { Clear(); } nsresult Init(nsCString&& aString); @@ -69,9 +70,13 @@ class nsStringInputStream final : public nsIStringInputStream, nsDependentCSubstring mData; uint32_t mOffset; + + mozilla::ReentrantMonitor mMon; }; nsresult nsStringInputStream::Init(nsCString&& aString) { + ReentrantMonitorAutoEnter lock(mMon); + if (!mData.Assign(std::move(aString), fallible)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -109,6 +114,8 @@ nsStringInputStream::GetType(uint16_t* aType) { NS_IMETHODIMP nsStringInputStream::GetData(nsACString& data) { + ReentrantMonitorAutoEnter lock(mMon); + // The stream doesn't have any data when it is closed. We could fake it // and return an empty string here, but it seems better to keep this return // value consistent with the behavior of the other 'getter' methods. @@ -122,6 +129,8 @@ nsStringInputStream::GetData(nsACString& data) { NS_IMETHODIMP nsStringInputStream::SetData(const nsACString& aData) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!mData.Assign(aData, fallible))) { return NS_ERROR_OUT_OF_MEMORY; } @@ -142,6 +151,8 @@ nsStringInputStream::ToString(char** aResult) { NS_IMETHODIMP nsStringInputStream::SetData(const char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -156,6 +167,8 @@ nsStringInputStream::SetData(const char* aData, int32_t aDataLen) { NS_IMETHODIMP nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -166,6 +179,8 @@ nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) { NS_IMETHODIMP nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -181,6 +196,8 @@ nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) { NS_IMETHODIMP_(size_t) nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { + ReentrantMonitorAutoEnter lock(mMon); + size_t n = aMallocSizeOf(this); n += mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf); return n; @@ -192,12 +209,16 @@ nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { NS_IMETHODIMP nsStringInputStream::Close() { + ReentrantMonitorAutoEnter lock(mMon); + Clear(); return NS_OK; } NS_IMETHODIMP nsStringInputStream::Available(uint64_t* aLength) { + ReentrantMonitorAutoEnter lock(mMon); + NS_ASSERTION(aLength, "null ptr"); if (Closed()) { @@ -217,6 +238,8 @@ nsStringInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aReadCount) { NS_IMETHODIMP nsStringInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, uint32_t* aResult) { + ReentrantMonitorAutoEnter lock(mMon); + NS_ASSERTION(aResult, "null ptr"); NS_ASSERTION(Length() >= mOffset, "bad stream state"); @@ -258,6 +281,8 @@ nsStringInputStream::IsNonBlocking(bool* aNonBlocking) { NS_IMETHODIMP nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -289,6 +314,8 @@ nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) { NS_IMETHODIMP nsStringInputStream::SetEOF() { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -303,6 +330,8 @@ nsStringInputStream::SetEOF() { NS_IMETHODIMP nsStringInputStream::Tell(int64_t* aOutWhere) { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -352,6 +381,8 @@ void nsStringInputStream::SerializeInternal(InputStreamParams& aParams, bool aDelayedStart, uint32_t aMaxSize, uint32_t* aSizeUsed, M* aManager) { + ReentrantMonitorAutoEnter lock(mMon); + MOZ_ASSERT(aSizeUsed); *aSizeUsed = 0; @@ -397,6 +428,8 @@ nsStringInputStream::GetCloneable(bool* aCloneableOut) { NS_IMETHODIMP nsStringInputStream::Clone(nsIInputStream** aCloneOut) { + ReentrantMonitorAutoEnter lock(mMon); + RefPtr ref = new nsStringInputStream(); nsresult rv = ref->SetData(mData); if (NS_WARN_IF(NS_FAILED(rv))) { From cb1aa0d750b847a1484cd2eb2176d09bbbf2f39c Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 13 Feb 2019 17:59:40 +0000 Subject: [PATCH 09/84] Bug 1518774 - Disable test_invalid_mime_type_blob.html on android. r=smaug This test is extremely heavy and, often, on android, it timeouts. Differential Revision: https://phabricator.services.mozilla.com/D19690 --HG-- extra : rebase_source : dc1649720f20af493341a1c5d7b5b23776997707 --- dom/canvas/test/mochitest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/canvas/test/mochitest.ini b/dom/canvas/test/mochitest.ini index 494454bc6ba7..571f73229e5d 100644 --- a/dom/canvas/test/mochitest.ini +++ b/dom/canvas/test/mochitest.ini @@ -299,3 +299,4 @@ subsuite = gpu tags = offscreencanvas skip-if = 1 [test_invalid_mime_type_blob.html] +skip-if = toolkit == 'android' From eca9e717dd5cadfc71d7d016c0f6c9aaa68a91bd Mon Sep 17 00:00:00 2001 From: Andreas Farre Date: Wed, 13 Feb 2019 16:08:03 +0000 Subject: [PATCH 10/84] Bug 1525866 - Add IPDLParamTraits>. r=froydnj Add support for serializing/deserializing tuples. Differential Revision: https://phabricator.services.mozilla.com/D18939 --HG-- extra : moz-landing-system : lando --- ipc/glue/IPDLParamTraits.h | 50 ++++++++++++++++++++++ netwerk/protocol/http/PHttpChannelParams.h | 21 --------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/ipc/glue/IPDLParamTraits.h b/ipc/glue/IPDLParamTraits.h index 4da9a9028315..42f7cd76c650 100644 --- a/ipc/glue/IPDLParamTraits.h +++ b/ipc/glue/IPDLParamTraits.h @@ -70,6 +70,27 @@ static MOZ_NEVER_INLINE bool ReadIPDLParam(const IPC::Message* aMsg, aMsg, aIter, aActor, aResult); } +constexpr void WriteIPDLParamList(IPC::Message*, IProtocol*) {} + +template +static void WriteIPDLParamList(IPC::Message* aMsg, IProtocol* aActor, + const P& aParam, const Ps&... aParams) { + WriteIPDLParam(aMsg, aActor, aParam); + WriteIPDLParamList(aMsg, aActor, aParams...); +} + +constexpr bool ReadIPDLParamList(const IPC::Message*, PickleIterator*, + IProtocol*) { + return true; +} + +template +static bool ReadIPDLParamList(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, P* aResult, Ps*... aResults) { + return ReadIPDLParam(aMsg, aIter, aActor, aResult) && + ReadIPDLParamList(aMsg, aIter, aActor, aResults...); +} + // nsTArray support for IPDLParamTraits template struct IPDLParamTraits> { @@ -193,6 +214,35 @@ struct IPDLParamTraits> { } }; +template +struct IPDLParamTraits> { + static void Write(IPC::Message* aMsg, IProtocol* aActor, + const Tuple& aParam) { + WriteInternal(aMsg, aActor, aParam, std::index_sequence_for{}); + } + + static bool Read(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, Tuple* aResult) { + return ReadInternal(aMsg, aIter, aActor, *aResult, + std::index_sequence_for{}); + } + + private: + template + static void WriteInternal(IPC::Message* aMsg, IProtocol* aActor, + const Tuple& aParam, + std::index_sequence) { + WriteIPDLParamList(aMsg, aActor, Get(aParam)...); + } + + template + static bool ReadInternal(const IPC::Message* aMsg, PickleIterator* aIter, + IProtocol* aActor, Tuple& aResult, + std::index_sequence) { + return ReadIPDLParamList(aMsg, aIter, aActor, &Get(aResult)...); + } +}; + } // namespace ipc } // namespace mozilla diff --git a/netwerk/protocol/http/PHttpChannelParams.h b/netwerk/protocol/http/PHttpChannelParams.h index bc1c935681cd..e4e494f712df 100644 --- a/netwerk/protocol/http/PHttpChannelParams.h +++ b/netwerk/protocol/http/PHttpChannelParams.h @@ -42,27 +42,6 @@ typedef nsTArray> ArrayOfStringPairs; namespace IPC { -template <> -struct ParamTraits> { - typedef mozilla::Tuple paramType; - - static void Write(Message* aMsg, const paramType& aParam) { - WriteParam(aMsg, mozilla::Get<0>(aParam)); - WriteParam(aMsg, mozilla::Get<1>(aParam)); - } - - static bool Read(const Message* aMsg, PickleIterator* aIter, - paramType* aResult) { - nsCString first; - nsCString second; - if (!ReadParam(aMsg, aIter, &first) || !ReadParam(aMsg, aIter, &second)) - return false; - - *aResult = mozilla::MakeTuple(first, second); - return true; - } -}; - template <> struct ParamTraits { typedef mozilla::net::RequestHeaderTuple paramType; From 40e0ac9225af8834c4d3dc4f31bf121dd9d31dcf Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Thu, 14 Feb 2019 12:44:07 +0000 Subject: [PATCH 11/84] Bug 1525125 block newtab and homepage overrides in private windows r=rpl,Gijs Differential Revision: https://phabricator.services.mozilla.com/D18730 --HG-- extra : moz-landing-system : lando --- browser/base/content/browser.js | 2 +- browser/base/content/utilityOverlay.js | 17 +- .../extensions/ExtensionControlledPopup.jsm | 9 +- .../extensions/parent/ext-windows.js | 9 +- ...wser_ext_chrome_settings_overrides_home.js | 124 ++++++++++++ .../browser_ext_url_overrides_newtab.js | 183 ++++++++++++++++++ browser/components/nsBrowserContentHandler.js | 10 +- .../components/sessionstore/SessionStore.jsm | 2 +- browser/modules/HomePage.jsm | 26 ++- 9 files changed, 369 insertions(+), 13 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 9994cb518a03..d9237bd5036c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2174,7 +2174,7 @@ function BrowserHome(aEvent) { aEvent.button == 2) // right-click: do nothing return; - var homePage = HomePage.get(); + var homePage = HomePage.get(window); var where = whereToOpenLink(aEvent, false, true); var urls; var notifyObservers; diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index e1fd134a7985..896fe5c6fc25 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", Object.defineProperty(this, "BROWSER_NEW_TAB_URL", { enumerable: true, get() { - if (PrivateBrowsingUtils.isWindowPrivate(window) && - !PrivateBrowsingUtils.permanentPrivateBrowsing && - !aboutNewTabService.overridden) { - return "about:privatebrowsing"; + if (PrivateBrowsingUtils.isWindowPrivate(window)) { + if (!PrivateBrowsingUtils.permanentPrivateBrowsing && + !aboutNewTabService.overridden) { + return "about:privatebrowsing"; + } + // If the extension does not have private browsing permission, + // use about:privatebrowsing. + if (aboutNewTabService.newTabURL.startsWith("moz-extension")) { + let url = new URL(aboutNewTabService.newTabURL); + if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) { + return "about:privatebrowsing"; + } + } } return aboutNewTabService.newTabURL; }, diff --git a/browser/components/extensions/ExtensionControlledPopup.jsm b/browser/components/extensions/ExtensionControlledPopup.jsm index 821cdca9fa63..f264a4582942 100644 --- a/browser/components/extensions/ExtensionControlledPopup.jsm +++ b/browser/components/extensions/ExtensionControlledPopup.jsm @@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); +ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); let { makeWidgetId, @@ -195,6 +197,12 @@ class ExtensionControlledPopup { extensionId = item && item.id; } + let win = targetWindow || this.topWindow; + let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win); + if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) { + return; + } + // The item should have an extension and the user shouldn't have confirmed // the change here, but just to be sure check that it is still controlled // and the user hasn't already confirmed the change. @@ -203,7 +211,6 @@ class ExtensionControlledPopup { return; } - let win = targetWindow || this.topWindow; // If the window closes while waiting for focus, this might reject/throw, // and we should stop trying to show the popup. try { diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index f44f7508d24a..7812b69d8146 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI { args.appendElement(mkstr(createData.url)); } } else { - let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ? - "about:privatebrowsing" : HomePage.get().split("|", 1)[0]; + let url; + if (createData.incognito) { + url = PrivateBrowsingUtils.permanentPrivateBrowsing ? + HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing"; + } else { + url = HomePage.get().split("|", 1)[0]; + } args.appendElement(mkstr(url)); if (url.startsWith("about:") && diff --git a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js index ef702f0b832d..c623327a7355 100644 --- a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js +++ b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js @@ -422,3 +422,127 @@ add_task(async function test_doorhanger_new_window() { ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall"); }); + +add_task(async function test_overriding_home_page_incognito_not_allowed() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_settings_overrides: {"homepage": "home.html"}, + name: "extension", + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("home.html")); + }, + files: {"home.html": "

1

"}, + useAddonManager: "temporary", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url}); + let win = OpenBrowserWindow(); + await windowOpenedPromise; + let doc = win.document; + let description = doc.getElementById("extension-homepage-notification-description"); + let panel = doc.getElementById("extension-notification-panel"); + await promisePopupShown(panel); + + let popupnotification = description.closest("popupnotification"); + is(description.textContent, + "An extension, extension, changed what you see when you open your homepage and new windows.Learn more", + "The extension name is in the popup"); + is(popupnotification.hidden, false, "The expected popup notification is visible"); + + ok(win.gURLBar.value.endsWith("home.html"), "extension is in control"); + await BrowserTestUtils.closeWindow(win); + + // Verify a private window does not open the extension page. + windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + win.BrowserHome(); + await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); + + is(win.gURLBar.value, "", "home page not used in private window"); + await BrowserTestUtils.closeWindow(win); + + // Verify manually setting the pref to the extension page does not work. + Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url); + windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + win.BrowserHome(); + await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); + + is(win.gURLBar.value, "", "home page not used in private window"); + Services.prefs.clearUserPref(HOMEPAGE_URL_PREF); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + name: "extension", + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("home.html")); + }, + files: {"home.html": "

1

"}, + useAddonManager: "temporary", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + // Verify manually setting the pref to the extension page does not work. + Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url); + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + win.BrowserHome(); + await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); + + is(win.gURLBar.value, "", "home page not used in private window"); + Services.prefs.clearUserPref(HOMEPAGE_URL_PREF); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_home_page_incognito_spanning() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_settings_overrides: {"homepage": "home.html"}, + name: "private extension", + applications: { + gecko: {id: "@spanning-home"}, + }, + }, + files: {"home.html": "

1

"}, + useAddonManager: "permanent", + incognitoOverride: "spanning", + }); + + await extension.startup(); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + let doc = win.document; + let panel = doc.getElementById("extension-notification-panel"); + win.BrowserHome(); + await promisePopupShown(panel); + + ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window"); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js index a8ae9a53aa89..105e3b78478d 100644 --- a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js +++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js @@ -5,6 +5,9 @@ ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); +XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", + "@mozilla.org/browser/aboutnewtab-service;1", + "nsIAboutNewTabService"); const NEWTAB_URI_1 = "webext-newtab-1.html"; @@ -522,3 +525,183 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() { BrowserTestUtils.removeTab(tab); await extension.unload(); }); + +add_task(async function test_overriding_newtab_incognito_not_allowed() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let panel = getNewTabDoorhanger().closest("panel"); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_url_overrides: {"newtab": "newtab.html"}, + name: "extension", + applications: { + gecko: {id: "@not-allowed-newtab"}, + }, + }, + files: { + "newtab.html": ` + + + + + + + + + `, + + "newtab.js": function() { + window.onload = () => { + browser.test.sendMessage("from-newtab-page", window.location.href); + }; + }, + }, + useAddonManager: "permanent", + }); + + await extension.startup(); + + let popupShown = promisePopupShown(panel); + BrowserOpenTab(); + await popupShown; + + let url = await extension.awaitMessage("from-newtab-page"); + ok(url.endsWith("newtab.html"), + "Newtab url is overridden by the extension."); + + // This will show a confirmation doorhanger, make sure we don't leave it open. + let popupHidden = promisePopupHidden(panel); + panel.hidePopup(); + await popupHidden; + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + // Verify a private window does not open the extension page. We would + // get an extra notification that we don't listen for if it gets loaded. + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + + let newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "newtab not used in private window"); + + // Verify setting the pref directly doesn't bypass permissions. + aboutNewTabService.newTabURL = url; + newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "directly set newtab not used in private window"); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + name: "extension", + applications: { + gecko: {id: "@not-allowed-newtab"}, + }, + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("newtab.html")); + }, + files: { + "newtab.html": ` + + + + + + + + `, + }, + useAddonManager: "permanent", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + // Verify setting the pref directly doesn't bypass permissions. + aboutNewTabService.newTabURL = url; + + // Verify a private window does not open the extension page. We would + // get an extra notification that we don't listen for if it gets loaded. + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + + let newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "directly set newtab not used in private window"); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_newtab_incognito_spanning() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_url_overrides: {"newtab": "newtab.html"}, + name: "extension", + applications: { + gecko: {id: "@spanning-newtab"}, + }, + }, + files: { + "newtab.html": ` + + + + + + + + + `, + + "newtab.js": function() { + window.onload = () => { + browser.test.sendMessage("from-newtab-page", window.location.href); + }; + }, + }, + useAddonManager: "permanent", + incognitoOverride: "spanning", + }); + + await extension.startup(); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + let panel = win.document.getElementById("extension-new-tab-notification").closest("panel"); + let popupShown = promisePopupShown(panel); + win.BrowserOpenTab(); + await popupShown; + + let url = await extension.awaitMessage("from-newtab-page"); + ok(url.endsWith("newtab.html"), + "Newtab url is overridden by the extension."); + + // This will show a confirmation doorhanger, make sure we don't leave it open. + let popupHidden = promisePopupHidden(panel); + panel.hidePopup(); + await popupHidden; + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index ecb08a61cd2f..874159a13362 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -207,7 +207,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData let args; if (!urlOrUrlList) { // Just pass in the defaultArgs directly. We'll use system principal on the other end. - args = [gBrowserContentHandler.defaultArgs]; + args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)]; } else { let pService = Cc["@mozilla.org/toolkit/profile-service;1"]. getService(Ci.nsIToolkitProfileService); @@ -522,7 +522,7 @@ nsBrowserContentHandler.prototype = { /* nsIBrowserHandler */ - get defaultArgs() { + getDefaultArgs(forcePrivate = false) { var prefb = Services.prefs; if (!gFirstWindow) { @@ -607,7 +607,7 @@ nsBrowserContentHandler.prototype = { try { var choice = prefb.getIntPref("browser.startup.page"); if (choice == 1 || choice == 3) - startPage = HomePage.get(); + startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get(); } catch (e) { Cu.reportError(e); } @@ -625,6 +625,10 @@ nsBrowserContentHandler.prototype = { return overridePage || startPage || "about:blank"; }, + get defaultArgs() { + return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing); + }, + mFeatures: null, getFeatures: function bch_features(cmdLine) { diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index a3d092977e0a..ae671e9f9ca1 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3299,7 +3299,7 @@ var SessionStoreInternal = { let tabbrowser = aWindow.gBrowser; let startupPref = this._prefBranch.getIntPref("startup.page"); if (startupPref == 1) - homePages = homePages.concat(HomePage.get().split("|")); + homePages = homePages.concat(HomePage.get(aWindow).split("|")); for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; diff --git a/browser/modules/HomePage.jsm b/browser/modules/HomePage.jsm index 486209167e87..2f7a3aa491fb 100644 --- a/browser/modules/HomePage.jsm +++ b/browser/modules/HomePage.jsm @@ -10,6 +10,8 @@ var EXPORTED_SYMBOLS = ["HomePage"]; const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); const kPrefName = "browser.startup.homepage"; @@ -43,7 +45,11 @@ function getHomepagePref(useDefault) { } let HomePage = { - get() { + get(aWindow) { + if (PrivateBrowsingUtils.permanentPrivateBrowsing || + (aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) { + return this.getPrivate(); + } return getHomepagePref(); }, @@ -51,6 +57,24 @@ let HomePage = { return getHomepagePref(true); }, + getPrivate() { + let homePages = getHomepagePref(); + if (!homePages.includes("moz-extension")) { + return homePages; + } + // Verify private access and build a new list. + let privateHomePages = homePages.split("|").filter(page => { + let url = new URL(page); + if (url.protocol !== "moz-extension:") { + return true; + } + let policy = WebExtensionPolicy.getByHostname(url.hostname); + return policy && policy.privateBrowsingAllowed; + }); + // Extensions may not be ready on startup, fallback to defaults. + return privateHomePages.join("|") || this.getDefault(); + }, + get overridden() { return Services.prefs.prefHasUserValue(kPrefName); }, From 5b5b01194db9efcb5eae841bb0e2bb41e0617fc7 Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Thu, 14 Feb 2019 01:32:31 +0000 Subject: [PATCH 12/84] Bug 1524001 update manifest to validate manifest.icons, r=kmag Differential Revision: https://phabricator.services.mozilla.com/D18105 --HG-- rename : toolkit/components/extensions/test/xpcshell/test_ext_manifest.js => browser/components/extensions/test/xpcshell/test_ext_manifest.js extra : moz-landing-system : lando --- .../test/xpcshell/test_ext_manifest.js | 48 +++++++++++++++ .../extensions/test/xpcshell/xpcshell.ini | 1 + .../extensions/schemas/manifest.json | 2 +- .../test/xpcshell/test_ext_manifest.js | 60 +++++++++---------- .../test/xpcshell/test_ext_management.js | 4 +- 5 files changed, 80 insertions(+), 35 deletions(-) create mode 100644 browser/components/extensions/test/xpcshell/test_ext_manifest.js diff --git a/browser/components/extensions/test/xpcshell/test_ext_manifest.js b/browser/components/extensions/test/xpcshell/test_ext_manifest.js new file mode 100644 index 000000000000..a2a3c79bdadf --- /dev/null +++ b/browser/components/extensions/test/xpcshell/test_ext_manifest.js @@ -0,0 +1,48 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +async function testIconPaths(icon, manifest, expectedError) { + let normalized = await ExtensionTestUtils.normalizeManifest(manifest); + + if (expectedError) { + ok(expectedError.test(normalized.error), + `Should have an error for ${JSON.stringify(manifest)}`); + } else { + ok(!normalized.error, `Should not have an error ${JSON.stringify(manifest)}, ${normalized.error}`); + } +} + +add_task(async function test_manifest() { + let badpaths = ["", " ", "\t", "http://foo.com/icon.png"]; + for (let path of badpaths) { + for (let action of ["browser_action", "page_action", "sidebar_action"]) { + let manifest = {}; + manifest[action] = {default_icon: path}; + let error = new RegExp(`Error processing ${action}.default_icon`); + await testIconPaths(path, manifest, error); + + manifest[action] = {default_icon: {"16": path}}; + await testIconPaths(path, manifest, error); + } + } + + let paths = ["icon.png", "/icon.png", "./icon.png", "path to an icon.png", " icon.png"]; + for (let path of paths) { + for (let action of ["browser_action", "page_action", "sidebar_action"]) { + let manifest = {}; + manifest[action] = {default_icon: path}; + if (action == "sidebar_action") { + // Sidebar requires panel. + manifest[action].default_panel = "foo.html"; + } + await testIconPaths(path, manifest); + + manifest[action] = {default_icon: {"16": path}}; + if (action == "sidebar_action") { + manifest[action].default_panel = "foo.html"; + } + await testIconPaths(path, manifest); + } + } +}); diff --git a/browser/components/extensions/test/xpcshell/xpcshell.ini b/browser/components/extensions/test/xpcshell/xpcshell.ini index 190b90749e4a..230f60d22590 100644 --- a/browser/components/extensions/test/xpcshell/xpcshell.ini +++ b/browser/components/extensions/test/xpcshell/xpcshell.ini @@ -17,6 +17,7 @@ dupe-manifest = # For tests which should only run with both remote extensions and remote content. [test_ext_geckoProfiler_schema.js] +[test_ext_manifest.js] [test_ext_manifest_commands.js] [test_ext_manifest_omnibox.js] [test_ext_manifest_permissions.js] diff --git a/toolkit/components/extensions/schemas/manifest.json b/toolkit/components/extensions/schemas/manifest.json index 2b778a8c5ca3..db1f6a2552e9 100644 --- a/toolkit/components/extensions/schemas/manifest.json +++ b/toolkit/components/extensions/schemas/manifest.json @@ -95,7 +95,7 @@ "type": "object", "optional": true, "patternProperties": { - "^[1-9]\\d*$": { "type": "string" } + "^[1-9]\\d*$": { "$ref": "ExtensionFileUrl" } } }, diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js b/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js index b21dbda6d585..bde6bff3357d 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_manifest.js @@ -2,48 +2,42 @@ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; +async function testIconPaths(icon, manifest, expectedError) { + let normalized = await ExtensionTestUtils.normalizeManifest(manifest); + + if (expectedError) { + ok(expectedError.test(normalized.error), + `Should have an error for ${JSON.stringify(icon)}`); + } else { + ok(!normalized.error, `Should not have an error ${JSON.stringify(icon)}`); + } +} + add_task(async function test_manifest() { let badpaths = ["", " ", "\t", "http://foo.com/icon.png"]; for (let path of badpaths) { - let normalized = await ExtensionTestUtils.normalizeManifest({ - "browser_action": { - "default_icon": path, + await testIconPaths(path, { + "icons": path, + }, /Error processing icons/); + + await testIconPaths(path, { + "icons": { + "16": path, }, - }); - - ok(/Error processing browser_action.default_icon/.test(normalized.error), - `Should have an error for ${JSON.stringify(path)}`); - - normalized = await ExtensionTestUtils.normalizeManifest({ - "browser_action": { - "default_icon": { - "16": path, - }, - }, - }); - - ok(/Error processing browser_action.default_icon/.test(normalized.error), - `Should have an error for ${JSON.stringify(path)}`); + }, /Error processing icons/); } let paths = ["icon.png", "/icon.png", "./icon.png", "path to an icon.png", " icon.png"]; for (let path of paths) { - let normalized = await ExtensionTestUtils.normalizeManifest({ - "browser_action": { - "default_icon": { - "16": path, - }, + // manifest.icons is an object + await testIconPaths(path, { + "icons": path, + }, /Error processing icons/); + + await testIconPaths(path, { + "icons": { + "16": path, }, }); - - ok(!normalized.error, `Should not have an error ${JSON.stringify(path)}`); - - normalized = await ExtensionTestUtils.normalizeManifest({ - "browser_action": { - "default_icon": path, - }, - }); - - ok(!normalized.error, `Should not have an error ${JSON.stringify(path)}`); } }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js b/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js index a91d230e9202..adc55ec1c5d9 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_ext_management.js @@ -11,6 +11,7 @@ function backgroundGetSelf() { browser.management.getSelf().then(extInfo => { let url = browser.extension.getURL("*"); extInfo.hostPermissions = extInfo.hostPermissions.filter(i => i != url); + extInfo.url = browser.extension.getURL(""); browser.test.sendMessage("management-getSelf", extInfo); }, error => { browser.test.notifyFail(`getSelf rejected with error: ${error}`); @@ -65,8 +66,9 @@ add_task(async function test_management_get_self_complete() { equal(extInfo.updateUrl, manifest.applications.gecko.update_url, "getSelf returned the expected updateUrl"); ok(extInfo.optionsUrl.endsWith(manifest.options_ui.page), "getSelf returned the expected optionsUrl"); for (let [index, size] of Object.keys(manifest.icons).sort().entries()) { + let iconUrl = `${extInfo.url}${manifest.icons[size]}`; equal(extInfo.icons[index].size, +size, "getSelf returned the expected icon size"); - equal(extInfo.icons[index].url, manifest.icons[size], "getSelf returned the expected icon url"); + equal(extInfo.icons[index].url, iconUrl, "getSelf returned the expected icon url"); } deepEqual(extInfo.permissions.sort(), permissions.sort(), "getSelf returned the expected permissions"); deepEqual(extInfo.hostPermissions.sort(), hostPermissions.sort(), "getSelf returned the expected hostPermissions"); From 3ccaa3b9ba28671d3a2e45c84f8bf4c4e4f270d8 Mon Sep 17 00:00:00 2001 From: Bogdan Tara Date: Thu, 14 Feb 2019 16:43:24 +0200 Subject: [PATCH 13/84] Backed out changeset e23608ddeac0 (bug 1527884) for wrench bustages CLOSED TREE --- Cargo.lock | 8 ++++---- gfx/webrender_bindings/Cargo.toml | 2 +- gfx/wr/webrender/Cargo.toml | 4 ++-- gfx/wr/webrender_api/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc6014a8a592..befc4c926385 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3077,7 +3077,7 @@ dependencies = [ [[package]] name = "webrender" -version = "0.60.0" +version = "0.59.0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3105,14 +3105,14 @@ dependencies = [ "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.60.0", + "webrender_api 0.58.0", "webrender_build 0.0.1", "wr_malloc_size_of 0.0.1", ] [[package]] name = "webrender_api" -version = "0.60.0" +version = "0.58.0" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3148,7 +3148,7 @@ dependencies = [ "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.60.0", + "webrender 0.59.0", ] [[package]] diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index 25264cda83b8..1258ea2807b9 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -18,7 +18,7 @@ fxhash = "0.2.1" [dependencies.webrender] path = "../wr/webrender" -version = "0.60.0" +version = "0.59.0" default-features = false features = ["capture", "serialize_program"] diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml index 26223f9fc443..651f76aabd4d 100644 --- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.60.0" +version = "0.59.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" @@ -46,7 +46,7 @@ sha2 = "0.8" smallvec = "0.6" thread_profiler = "0.1.1" time = "0.1" -webrender_api = { version = "0.60.0", path = "../webrender_api" } +webrender_api = { version = "0.58.0", path = "../webrender_api" } webrender_build = { version = "0.0.1", path = "../webrender_build" } wr_malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of" } ws = { optional = true, version = "0.7.3" } diff --git a/gfx/wr/webrender_api/Cargo.toml b/gfx/wr/webrender_api/Cargo.toml index e919800ba147..967c8b14f477 100644 --- a/gfx/wr/webrender_api/Cargo.toml +++ b/gfx/wr/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.60.0" +version = "0.58.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" From 3a0829bb8d25a7760a5afec0ae45827acdec2462 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Mon, 11 Feb 2019 20:07:51 +0000 Subject: [PATCH 14/84] Bug 1513651 - Collect telemetry on sample description box entries when parsing mp4s. r=jya This patch adds telemetry to help us determine if mp4s with certain structures can occur in the wild. Specifically: - How often do mp4s have multiple entries in the sample description box? - Do we ever see mp4s with multiple codecs in the sample description box? - Do we ever see mp4s with multiple sets of crypto info in the sample description box? This information is collected each time we parse mp4 metadata. Remove some diagnostic asserts now that we're gracefully gathering info. Reshuffle of DecoderData function order to align with the order in the header. Differential Revision: https://phabricator.services.mozilla.com/D14426 --HG-- extra : moz-landing-system : lando --- dom/media/mp4/DecoderData.cpp | 142 +++++++++++-------- toolkit/components/telemetry/Histograms.json | 25 ++++ 2 files changed, 111 insertions(+), 56 deletions(-) diff --git a/dom/media/mp4/DecoderData.cpp b/dom/media/mp4/DecoderData.cpp index dc40a0f57988..5bf7fd3e9aba 100644 --- a/dom/media/mp4/DecoderData.cpp +++ b/dom/media/mp4/DecoderData.cpp @@ -8,6 +8,7 @@ #include "DecoderData.h" #include "mozilla/ArrayUtils.h" #include "mozilla/EndianUtils.h" +#include "mozilla/Telemetry.h" #include "VideoUtils.h" // OpusDecoder header is really needed only by MP4 in rust @@ -40,13 +41,6 @@ mozilla::Result CryptoFile::DoUpdate( return mozilla::Ok(); } -bool MP4AudioInfo::IsValid() const { - return mChannels > 0 && mRate > 0 && - // Accept any mime type here, but if it's aac, validate the profile. - (!mMimeType.EqualsLiteral("audio/mp4a-latm") || mProfile > 0 || - mExtendedProfile > 0); -} - static MediaResult UpdateTrackProtectedInfo(mozilla::TrackInfo& aConfig, const Mp4parseSinfInfo& aSinf) { if (aSinf.is_encrypted != 0) { @@ -72,40 +66,91 @@ static MediaResult UpdateTrackProtectedInfo(mozilla::TrackInfo& aConfig, return NS_OK; } -MediaResult MP4AudioInfo::Update(const Mp4parseTrackInfo* track, - const Mp4parseTrackAudioInfo* audio) { - MOZ_DIAGNOSTIC_ASSERT(audio->sample_info_count > 0, - "Must have at least one audio sample info"); - if (audio->sample_info_count == 0) { - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL("Got 0 audio sample info while updating audio track")); - } +// Verify various information shared by Mp4ParseTrackAudioInfo and +// Mp4ParseTrackVideoInfo and record telemetry on that info. Returns an +// appropriate MediaResult indicating if the info is valid or not. +// This verifies: +// - That we have a sample_info_count > 0 (valid tracks should have at least one +// sample description entry) +// - That only a single codec is used across all sample infos, as we don't +// handle multiple. +// - That only a single sample info contains crypto info, as we don't handle +// multiple. +// +// Telemetry is also recorded on the above. As of writing, the +// telemetry is recorded to give us early warning if MP4s exist that we're not +// handling. Note, if adding new checks and telemetry to this function, +// telemetry should be recorded before returning to ensure it is gathered. +template +static MediaResult VerifyAudioOrVideoInfoAndRecordTelemetry( + Mp4ParseTrackAudioOrVideoInfo* audioOrVideoInfo) { + Telemetry::Accumulate( + Telemetry::MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES, + audioOrVideoInfo->sample_info_count); bool hasCrypto = false; - Mp4parseCodec codecType = audio->sample_info[0].codec_type; - for (uint32_t i = 0; i < audio->sample_info_count; i++) { - if (audio->sample_info[0].codec_type != codecType) { - // Different codecs in a single track. We don't handle this. - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL( - "Multiple codecs encountered while updating audio track")); + bool hasMultipleCodecs = false; + bool hasMultipleCrypto = false; + Mp4parseCodec codecType = audioOrVideoInfo->sample_info[0].codec_type; + for (uint32_t i = 0; i < audioOrVideoInfo->sample_info_count; i++) { + if (audioOrVideoInfo->sample_info[0].codec_type != codecType) { + hasMultipleCodecs = true; } // Update our encryption info if any is present on the sample info. - if (audio->sample_info[i].protected_data.is_encrypted) { + if (audioOrVideoInfo->sample_info[i].protected_data.is_encrypted) { if (hasCrypto) { - // Multiple crypto entries found. We don't handle this. - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL( - "Multiple crypto info encountered while updating audio track")); + hasMultipleCrypto = true; } + hasCrypto = true; + } + } + + Telemetry::Accumulate( + Telemetry:: + MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS, + hasMultipleCodecs); + + Telemetry::Accumulate( + Telemetry:: + MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO, + hasMultipleCrypto); + + if (audioOrVideoInfo->sample_info_count == 0) { + return MediaResult( + NS_ERROR_DOM_MEDIA_METADATA_ERR, + RESULT_DETAIL("Got 0 sample info while verifying track.")); + } + + if (hasMultipleCodecs) { + // Different codecs in a single track. We don't handle this. + return MediaResult( + NS_ERROR_DOM_MEDIA_METADATA_ERR, + RESULT_DETAIL("Multiple codecs encountered while verifying track.")); + } + + if (hasMultipleCrypto) { + // Multiple crypto entries found. We don't handle this. + return MediaResult( + NS_ERROR_DOM_MEDIA_METADATA_ERR, + RESULT_DETAIL( + "Multiple crypto info encountered while verifying track.")); + } + return NS_OK; +} + +MediaResult MP4AudioInfo::Update(const Mp4parseTrackInfo* track, + const Mp4parseTrackAudioInfo* audio) { + auto rv = VerifyAudioOrVideoInfoAndRecordTelemetry(audio); + NS_ENSURE_SUCCESS(rv, rv); + + Mp4parseCodec codecType = audio->sample_info[0].codec_type; + for (uint32_t i = 0; i < audio->sample_info_count; i++) { + if (audio->sample_info[i].protected_data.is_encrypted) { auto rv = UpdateTrackProtectedInfo(*this, audio->sample_info[i].protected_data); NS_ENSURE_SUCCESS(rv, rv); - hasCrypto = true; + break; } } @@ -158,40 +203,25 @@ MediaResult MP4AudioInfo::Update(const Mp4parseTrackInfo* track, return NS_OK; } +bool MP4AudioInfo::IsValid() const { + return mChannels > 0 && mRate > 0 && + // Accept any mime type here, but if it's aac, validate the profile. + (!mMimeType.EqualsLiteral("audio/mp4a-latm") || mProfile > 0 || + mExtendedProfile > 0); +} + MediaResult MP4VideoInfo::Update(const Mp4parseTrackInfo* track, const Mp4parseTrackVideoInfo* video) { - MOZ_DIAGNOSTIC_ASSERT(video->sample_info_count > 0, - "Must have at least one video sample info"); - if (video->sample_info_count == 0) { - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL("Got 0 audio sample info while updating video track")); - } + auto rv = VerifyAudioOrVideoInfoAndRecordTelemetry(video); + NS_ENSURE_SUCCESS(rv, rv); - bool hasCrypto = false; Mp4parseCodec codecType = video->sample_info[0].codec_type; for (uint32_t i = 0; i < video->sample_info_count; i++) { - if (video->sample_info[0].codec_type != codecType) { - // Different codecs in a single track. We don't handle this. - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL( - "Multiple codecs encountered while updating video track")); - } - - // Update our encryption info if any is present on the sample info. if (video->sample_info[i].protected_data.is_encrypted) { - if (hasCrypto) { - // Multiple crypto entries found. We don't handle this. - return MediaResult( - NS_ERROR_DOM_MEDIA_METADATA_ERR, - RESULT_DETAIL( - "Multiple crypto info encountered while updating video track")); - } auto rv = UpdateTrackProtectedInfo(*this, video->sample_info[i].protected_data); NS_ENSURE_SUCCESS(rv, rv); - hasCrypto = true; + break; } } diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 453beb7b3c5c..7a7a00ae0418 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -8680,6 +8680,31 @@ "n_values": 10, "description": "Counts types of deprecation warnings logged on every successful call to navigator.requestMediaKeySystemAccess(). 0=No warnings logged, 1=MediaEMENoCapabilitiesDeprecatedWarning, 2=MediaEMENoCodecsDeprecatedWarning." }, + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS": { + "record_in_processes": ["main", "content"], + "alert_emails": ["bvandyk@mozilla.com", "jya@mozilla.com", "drno@ohlmeier.org"], + "bug_numbers": [1513651], + "expires_in_version": "never", + "kind": "boolean", + "description": "Records if multiple codecs are present in a track's sample description entries. Recorded each time we process a track's metadata while parsing mp4s." + }, + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO": { + "record_in_processes": ["main", "content"], + "alert_emails": ["bvandyk@mozilla.com", "jya@mozilla.com", "drno@ohlmeier.org"], + "bug_numbers": [1513651], + "expires_in_version": "never", + "kind": "boolean", + "description": "Records if multiple sets of crypto info are present in a track's sample description entries. Recorded each time we process a track's metadata while parsing mp4s." + }, + "MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES": { + "record_in_processes": ["main", "content"], + "alert_emails": ["bvandyk@mozilla.com", "jya@mozilla.com", "drno@ohlmeier.org"], + "bug_numbers": [1513651], + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 5, + "description": "Counts the number of entries in the sample description box (stsd) for a track in an mp4. Recorded each time we process a track's metadata while parsing mp4s." + }, "MEDIACACHE_WATERMARK_KB": { "record_in_processes": ["main", "content"], "alert_emails": ["gsquelart@mozilla.com"], From db46b71d9d23dc88a96fa8c2ab0114d62a82051b Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Mon, 11 Feb 2019 20:15:22 +0000 Subject: [PATCH 15/84] Bug 1513651 - Add gtest for MP4 metadata telemetry probes. r=chutten Add a gtest to cover the new telemetry probes which collect info on sample description entries. Add a new init segment to those already in our gtests. This segment has data for one video track, and covers the case where multiple sample description entries are present for a single track. In this case, because separate sample description entries are used for unencrypted and encrypted samples. For reference, the test init segment was created from our existing bipbop using shaka-packager via the following command (non-init segments were discarded and the output was renamed): packager-win.exe in=bipbop.mp4,stream=video,init_segment=bipbop_cbcs_video_init.mp4,segment_template=bipbop_cbcs_video_$Number$.m4s --protection_scheme cbcs --enable_raw_key_encryption --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421 --iv 11223344556677889900112233445566 --generate_static_mpd --mpd_output bipbop_cbcs.mpd Depends on D14426 Differential Revision: https://phabricator.services.mozilla.com/D19386 --HG-- extra : moz-landing-system : lando --- dom/media/gtest/mp4_demuxer/TestParser.cpp | 210 ++++++++++++++++++ dom/media/gtest/mp4_demuxer/moz.build | 2 + ...e_1513651-2-sample-description-entries.mp4 | Bin 0 -> 1100 bytes 3 files changed, 212 insertions(+) create mode 100644 dom/media/gtest/mp4_demuxer/test_case_1513651-2-sample-description-entries.mp4 diff --git a/dom/media/gtest/mp4_demuxer/TestParser.cpp b/dom/media/gtest/mp4_demuxer/TestParser.cpp index 13ef2770b7f2..6f27b7c8f90b 100644 --- a/dom/media/gtest/mp4_demuxer/TestParser.cpp +++ b/dom/media/gtest/mp4_demuxer/TestParser.cpp @@ -7,9 +7,12 @@ #include "MediaData.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Preferences.h" +#include "mozilla/Tuple.h" #include "BufferStream.h" #include "MP4Metadata.h" #include "MoofParser.h" +#include "TelemetryFixture.h" +#include "TelemetryTestHelpers.h" class TestStream; namespace mozilla { @@ -767,3 +770,210 @@ TEST(MP4Metadata, EmptyCTTS) { EXPECT_TRUE(metadata.CanSeek()); EXPECT_FALSE(metadata.Crypto().Ref()->valid); } + +// Fixture so we test telemetry probes. +class MP4MetadataTelemetryFixture : public TelemetryTestFixture {}; + +TEST_F(MP4MetadataTelemetryFixture, Telemetry) { + // Helper to fetch the metadata from a file and send telemetry in the process. + auto UpdateMetadataAndHistograms = [](const char* testFileName) { + nsTArray buffer = ReadTestFile(testFileName); + ASSERT_FALSE(buffer.IsEmpty()); + RefPtr stream = + new TestStream(buffer.Elements(), buffer.Length()); + + MP4Metadata::ResultAndByteBuffer metadataBuffer = + MP4Metadata::Metadata(stream); + EXPECT_EQ(NS_OK, metadataBuffer.Result()); + EXPECT_TRUE(metadataBuffer.Ref()); + + MP4Metadata metadata(stream); + nsresult res = metadata.Parse(); + EXPECT_TRUE(NS_SUCCEEDED(res)); + auto audioTrackCount = metadata.GetNumberTracks(TrackInfo::kAudioTrack); + ASSERT_NE(audioTrackCount.Ref(), MP4Metadata::NumberTracksError()); + auto videoTrackCount = metadata.GetNumberTracks(TrackInfo::kVideoTrack); + ASSERT_NE(videoTrackCount.Ref(), MP4Metadata::NumberTracksError()); + + // Need to read the track data to get telemetry to fire. + for (uint32_t i = 0; i < audioTrackCount.Ref(); i++) { + metadata.GetTrackInfo(TrackInfo::kAudioTrack, i); + } + for (uint32_t i = 0; i < videoTrackCount.Ref(); i++) { + metadata.GetTrackInfo(TrackInfo::kVideoTrack, i); + } + }; + + AutoJSContextWithGlobal cx(mCleanGlobal); + + // Checks the current state of the histograms relating to sample description + // entries and verifies they're in an expected state. + // aExpectedMultipleCodecCounts is a tuple where the first value represents + // the number of expected 'false' count, and the second the expected 'true' + // count for the sample description entries have multiple codecs histogram. + // aExpectedMultipleCryptoCounts is the same, but for the sample description + // entires have multiple crypto histogram. + // aExpectedSampleDescriptionEntryCounts is a tuple with 6 values, each is + // the expected number of sample description seen. I.e, the first value in the + // tuple is the number of tracks we've seen with 0 sample descriptions, the + // second value with 1 sample description, and so on up to 5 sample + // descriptions. aFileName is the name of the most recent file we've parsed, + // and is used to log if our telem counts are not in an expected state. + auto CheckHistograms = + [this, &cx]( + const Tuple& aExpectedMultipleCodecCounts, + const Tuple& aExpectedMultipleCryptoCounts, + const Tuple& aExpectedSampleDescriptionEntryCounts, + const char* aFileName) { + // Get a snapshot of the current histograms + JS::RootedValue snapshot(cx.GetJSContext()); + TelemetryTestHelpers::GetSnapshots(cx.GetJSContext(), mTelemetry, + "" /* this string is unused */, + &snapshot, false /* is_keyed */); + + // We'll use these to pull values out of the histograms. + JS::RootedValue values(cx.GetJSContext()); + JS::RootedValue value(cx.GetJSContext()); + + // Verify our multiple codecs count histogram. + JS::RootedValue multipleCodecsHistogram(cx.GetJSContext()); + TelemetryTestHelpers::GetProperty( + cx.GetJSContext(), + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS", + snapshot, &multipleCodecsHistogram); + ASSERT_TRUE(multipleCodecsHistogram.isObject()) + << "Multiple codecs histogram should exist!"; + + TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values", + multipleCodecsHistogram, &values); + // False count. + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value); + uint32_t uValue = 0; + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<0>(aExpectedMultipleCodecCounts), uValue) + << "Unexpected number of false multiple codecs after parsing " + << aFileName; + // True count. + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<1>(aExpectedMultipleCodecCounts), uValue) + << "Unexpected number of true multiple codecs after parsing " + << aFileName; + + // Verify our multiple crypto count histogram. + JS::RootedValue multipleCryptoHistogram(cx.GetJSContext()); + TelemetryTestHelpers::GetProperty( + cx.GetJSContext(), + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO", + snapshot, &multipleCryptoHistogram); + ASSERT_TRUE(multipleCryptoHistogram.isObject()) + << "Multiple crypto histogram should exist!"; + + TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values", + multipleCryptoHistogram, &values); + // False count. + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<0>(aExpectedMultipleCryptoCounts), uValue) + << "Unexpected number of false multiple cryptos after parsing " + << aFileName; + // True count. + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<1>(aExpectedMultipleCryptoCounts), uValue) + << "Unexpected number of true multiple cryptos after parsing " + << aFileName; + + // Verify our sample description entry count histogram. + JS::RootedValue numSamplesHistogram(cx.GetJSContext()); + TelemetryTestHelpers::GetProperty( + cx.GetJSContext(), "MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES", + snapshot, &numSamplesHistogram); + ASSERT_TRUE(numSamplesHistogram.isObject()) + << "Num sample description entries histogram should exist!"; + + TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values", + numSamplesHistogram, &values); + + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<0>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 0 sample entry descriptions after parsing " + << aFileName; + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<1>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 1 sample entry descriptions after parsing " + << aFileName; + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 2, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<2>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 2 sample entry descriptions after parsing " + << aFileName; + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 3, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<3>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 3 sample entry descriptions after parsing " + << aFileName; + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 4, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<4>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 4 sample entry descriptions after parsing " + << aFileName; + TelemetryTestHelpers::GetElement(cx.GetJSContext(), 5, values, &value); + JS::ToUint32(cx.GetJSContext(), value, &uValue); + EXPECT_EQ(Get<5>(aExpectedSampleDescriptionEntryCounts), uValue) + << "Unexpected number of 5 sample entry descriptions after parsing " + << aFileName; + }; + + // Clear histograms + TelemetryTestHelpers::GetAndClearHistogram( + cx.GetJSContext(), mTelemetry, + NS_LITERAL_CSTRING( + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS"), + false /* is_keyed */); + + TelemetryTestHelpers::GetAndClearHistogram( + cx.GetJSContext(), mTelemetry, + NS_LITERAL_CSTRING( + "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO"), + false /* is_keyed */); + + TelemetryTestHelpers::GetAndClearHistogram( + cx.GetJSContext(), mTelemetry, + NS_LITERAL_CSTRING("MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES"), + false /* is_keyed */); + + // The snapshot won't have any data in it until we populate our histograms, so + // we don't check for a baseline here. Just read out first MP4 metadata. + + // Grab one of the test cases we know should parse and parse it, this should + // trigger telemetry gathering. + + // This file contains 2 moovs, each with a video and audio track with one + // sample description entry. So we should see 4 tracks, each with a single + // codec, no crypto, and a single sample description entry. + UpdateMetadataAndHistograms("test_case_1185230.mp4"); + + // Verify our histograms are updated. + CheckHistograms( + MakeTuple(4, 0), MakeTuple(4, 0), + MakeTuple( + 0, 4, 0, 0, 0, 0), + "test_case_1185230.mp4"); + + // Parse another test case. This one has a single moov with a single video + // track. However, the track has two sample description entries, and our + // updated telemetry should reflect that. + UpdateMetadataAndHistograms( + "test_case_1513651-2-sample-description-entries.mp4"); + + // Verify our histograms are updated. + CheckHistograms( + MakeTuple(5, 0), MakeTuple(5, 0), + MakeTuple( + 0, 4, 1, 0, 0, 0), + "test_case_1513651-2-sample-description-entries.mp4"); +} diff --git a/dom/media/gtest/mp4_demuxer/moz.build b/dom/media/gtest/mp4_demuxer/moz.build index 619b4edfaf2b..ef8bd3d0dcad 100644 --- a/dom/media/gtest/mp4_demuxer/moz.build +++ b/dom/media/gtest/mp4_demuxer/moz.build @@ -42,6 +42,7 @@ TEST_HARNESS_FILES.gtest += [ 'test_case_1389527.mp4', 'test_case_1395244.mp4', 'test_case_1410565.mp4', + 'test_case_1513651-2-sample-description-entries.mp4', 'test_case_1519617-cenc-init-with-track_id-0.mp4', 'test_case_1519617-track2-trafs-removed.mp4', 'test_case_1519617-video-has-track_id-0.mp4', @@ -53,6 +54,7 @@ TEST_HARNESS_FILES.gtest += [ ] LOCAL_INCLUDES += [ '../../mp4', + '/toolkit/components/telemetry/tests/gtest', ] FINAL_LIBRARY = 'xul-gtest' diff --git a/dom/media/gtest/mp4_demuxer/test_case_1513651-2-sample-description-entries.mp4 b/dom/media/gtest/mp4_demuxer/test_case_1513651-2-sample-description-entries.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..2f8f235a9b4b826547a387fdb4ffc801d317a9b3 GIT binary patch literal 1100 zcmc&z&1(}u6rTwJQCoqBi*iJPcb93*&%E#>W8=LDLu&xr~YCTYwD;3An?sm6q1+wA< zf#Zt`RM}&t0ke9{5h00cA_U# zX- z^=&Ygc%m10C=jDyIy2j$ZzMK-t#sE1S}CpKiv}Jq<3RK+8~~K55`Y*&`fK39g+h31$i4V_<;>>6&uc)@OgFK!i@4`EiwVM7 literal 0 HcmV?d00001 From 38ee1554b6791c65bcce518e4b81536a689a92be Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Thu, 14 Feb 2019 11:14:07 +0000 Subject: [PATCH 16/84] Bug 1513651 - Add test file with 2 sample description entries to MP4 parser general gtests. r=jya Add a test file that was used to test mp4 parser telemetry to the general suite. This file was added in the revision before this, and is also useful to provide further coverage for other tests. Differential Revision: https://phabricator.services.mozilla.com/D19387 --HG-- extra : moz-landing-system : lando --- dom/media/gtest/mp4_demuxer/TestParser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dom/media/gtest/mp4_demuxer/TestParser.cpp b/dom/media/gtest/mp4_demuxer/TestParser.cpp index 6f27b7c8f90b..5ef1ef15061a 100644 --- a/dom/media/gtest/mp4_demuxer/TestParser.cpp +++ b/dom/media/gtest/mp4_demuxer/TestParser.cpp @@ -237,6 +237,8 @@ static const TestFileData testFiles[] = { false, 0}, {"test_case_1410565.mp4", false, 0, false, 0, 0, 0, 0, 0, false, 955100, true, true, 2}, // negative 'timescale' + {"test_case_1513651-2-sample-description-entries.mp4", true, 1, true, + 9843344, 400, 300, 0, -1, true, 0, false, false, 0}, {"test_case_1519617-cenc-init-with-track_id-0.mp4", true, 1, true, 0, 1272, 530, 0, -1, false, 0, false, false, 0}, // Uses bad track id 0 and has a sinf but no pssh From 11e921c98326140d2670b38e1acdb006fef8e347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sta=C5=9B=20Ma=C5=82olepszy?= Date: Wed, 13 Feb 2019 18:28:08 +0000 Subject: [PATCH 17/84] Bug 1526875 - Land intl/l10n/FluentSyntax.jsm r=zbraniecki Differential Revision: https://phabricator.services.mozilla.com/D19391 --HG-- extra : moz-landing-system : lando --- intl/l10n/FluentSyntax.jsm | 1930 ++++++++++++++++++++++++++++++++++++ intl/l10n/moz.build | 1 + 2 files changed, 1931 insertions(+) create mode 100644 intl/l10n/FluentSyntax.jsm diff --git a/intl/l10n/FluentSyntax.jsm b/intl/l10n/FluentSyntax.jsm new file mode 100644 index 000000000000..28c349e4af99 --- /dev/null +++ b/intl/l10n/FluentSyntax.jsm @@ -0,0 +1,1930 @@ +/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ + +/* Copyright 2019 Mozilla Foundation and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/* fluent-syntax@0.10.0 */ + +/* + * Base class for all Fluent AST nodes. + * + * All productions described in the ASDL subclass BaseNode, including Span and + * Annotation. + * + */ +class BaseNode { + constructor() {} +} + +/* + * Base class for AST nodes which can have Spans. + */ +class SyntaxNode extends BaseNode { + addSpan(start, end) { + this.span = new Span(start, end); + } +} + +class Resource extends SyntaxNode { + constructor(body = []) { + super(); + this.type = "Resource"; + this.body = body; + } +} + +/* + * An abstract base class for useful elements of Resource.body. + */ +class Entry extends SyntaxNode {} + +class Message extends Entry { + constructor(id, value = null, attributes = [], comment = null) { + super(); + this.type = "Message"; + this.id = id; + this.value = value; + this.attributes = attributes; + this.comment = comment; + } +} + +class Term extends Entry { + constructor(id, value, attributes = [], comment = null) { + super(); + this.type = "Term"; + this.id = id; + this.value = value; + this.attributes = attributes; + this.comment = comment; + } +} + +class VariantList extends SyntaxNode { + constructor(variants) { + super(); + this.type = "VariantList"; + this.variants = variants; + } +} + +class Pattern extends SyntaxNode { + constructor(elements) { + super(); + this.type = "Pattern"; + this.elements = elements; + } +} + +/* + * An abstract base class for elements of Patterns. + */ +class PatternElement extends SyntaxNode {} + +class TextElement extends PatternElement { + constructor(value) { + super(); + this.type = "TextElement"; + this.value = value; + } +} + +class Placeable extends PatternElement { + constructor(expression) { + super(); + this.type = "Placeable"; + this.expression = expression; + } +} + +/* + * An abstract base class for expressions. + */ +class Expression extends SyntaxNode {} + +class StringLiteral extends Expression { + constructor(raw, value) { + super(); + this.type = "StringLiteral"; + this.raw = raw; + this.value = value; + } +} + +class NumberLiteral extends Expression { + constructor(value) { + super(); + this.type = "NumberLiteral"; + this.value = value; + } +} + +class MessageReference extends Expression { + constructor(id) { + super(); + this.type = "MessageReference"; + this.id = id; + } +} + +class TermReference extends Expression { + constructor(id) { + super(); + this.type = "TermReference"; + this.id = id; + } +} + +class VariableReference extends Expression { + constructor(id) { + super(); + this.type = "VariableReference"; + this.id = id; + } +} + +class FunctionReference extends Expression { + constructor(id) { + super(); + this.type = "FunctionReference"; + this.id = id; + } +} + +class SelectExpression extends Expression { + constructor(selector, variants) { + super(); + this.type = "SelectExpression"; + this.selector = selector; + this.variants = variants; + } +} + +class AttributeExpression extends Expression { + constructor(ref, name) { + super(); + this.type = "AttributeExpression"; + this.ref = ref; + this.name = name; + } +} + +class VariantExpression extends Expression { + constructor(ref, key) { + super(); + this.type = "VariantExpression"; + this.ref = ref; + this.key = key; + } +} + +class CallExpression extends Expression { + constructor(callee, positional = [], named = []) { + super(); + this.type = "CallExpression"; + this.callee = callee; + this.positional = positional; + this.named = named; + } +} + +class Attribute extends SyntaxNode { + constructor(id, value) { + super(); + this.type = "Attribute"; + this.id = id; + this.value = value; + } +} + +class Variant extends SyntaxNode { + constructor(key, value, def = false) { + super(); + this.type = "Variant"; + this.key = key; + this.value = value; + this.default = def; + } +} + +class NamedArgument extends SyntaxNode { + constructor(name, value) { + super(); + this.type = "NamedArgument"; + this.name = name; + this.value = value; + } +} + +class Identifier extends SyntaxNode { + constructor(name) { + super(); + this.type = "Identifier"; + this.name = name; + } +} + +class BaseComment extends Entry { + constructor(content) { + super(); + this.type = "BaseComment"; + this.content = content; + } +} + +class Comment extends BaseComment { + constructor(content) { + super(content); + this.type = "Comment"; + } +} + +class GroupComment extends BaseComment { + constructor(content) { + super(content); + this.type = "GroupComment"; + } +} +class ResourceComment extends BaseComment { + constructor(content) { + super(content); + this.type = "ResourceComment"; + } +} + +class Junk extends SyntaxNode { + constructor(content) { + super(); + this.type = "Junk"; + this.annotations = []; + this.content = content; + } + + addAnnotation(annot) { + this.annotations.push(annot); + } +} + +class Span extends BaseNode { + constructor(start, end) { + super(); + this.type = "Span"; + this.start = start; + this.end = end; + } +} + +class Annotation extends SyntaxNode { + constructor(code, args = [], message) { + super(); + this.type = "Annotation"; + this.code = code; + this.args = args; + this.message = message; + } +} + +const ast = ({ + Resource: Resource, + Entry: Entry, + Message: Message, + Term: Term, + VariantList: VariantList, + Pattern: Pattern, + PatternElement: PatternElement, + TextElement: TextElement, + Placeable: Placeable, + Expression: Expression, + StringLiteral: StringLiteral, + NumberLiteral: NumberLiteral, + MessageReference: MessageReference, + TermReference: TermReference, + VariableReference: VariableReference, + FunctionReference: FunctionReference, + SelectExpression: SelectExpression, + AttributeExpression: AttributeExpression, + VariantExpression: VariantExpression, + CallExpression: CallExpression, + Attribute: Attribute, + Variant: Variant, + NamedArgument: NamedArgument, + Identifier: Identifier, + BaseComment: BaseComment, + Comment: Comment, + GroupComment: GroupComment, + ResourceComment: ResourceComment, + Junk: Junk, + Span: Span, + Annotation: Annotation +}); + +class ParseError extends Error { + constructor(code, ...args) { + super(); + this.code = code; + this.args = args; + this.message = getErrorMessage(code, args); + } +} + +/* eslint-disable complexity */ +function getErrorMessage(code, args) { + switch (code) { + case "E0001": + return "Generic error"; + case "E0002": + return "Expected an entry start"; + case "E0003": { + const [token] = args; + return `Expected token: "${token}"`; + } + case "E0004": { + const [range] = args; + return `Expected a character from range: "${range}"`; + } + case "E0005": { + const [id] = args; + return `Expected message "${id}" to have a value or attributes`; + } + case "E0006": { + const [id] = args; + return `Expected term "-${id}" to have a value`; + } + case "E0007": + return "Keyword cannot end with a whitespace"; + case "E0008": + return "The callee has to be an upper-case identifier or a term"; + case "E0009": + return "The key has to be a simple identifier"; + case "E0010": + return "Expected one of the variants to be marked as default (*)"; + case "E0011": + return 'Expected at least one variant after "->"'; + case "E0012": + return "Expected value"; + case "E0013": + return "Expected variant key"; + case "E0014": + return "Expected literal"; + case "E0015": + return "Only one variant can be marked as default (*)"; + case "E0016": + return "Message references cannot be used as selectors"; + case "E0017": + return "Terms cannot be used as selectors"; + case "E0018": + return "Attributes of messages cannot be used as selectors"; + case "E0019": + return "Attributes of terms cannot be used as placeables"; + case "E0020": + return "Unterminated string expression"; + case "E0021": + return "Positional arguments must not follow named arguments"; + case "E0022": + return "Named arguments must be unique"; + case "E0024": + return "Cannot access variants of a message."; + case "E0025": { + const [char] = args; + return `Unknown escape sequence: \\${char}.`; + } + case "E0026": { + const [sequence] = args; + return `Invalid Unicode escape sequence: ${sequence}.`; + } + case "E0027": + return "Unbalanced closing brace in TextElement."; + case "E0028": + return "Expected an inline expression"; + default: + return code; + } +} + +function includes(arr, elem) { + return arr.indexOf(elem) > -1; +} + +/* eslint no-magic-numbers: "off" */ + +class ParserStream { + constructor(string) { + this.string = string; + this.index = 0; + this.peekOffset = 0; + } + + charAt(offset) { + // When the cursor is at CRLF, return LF but don't move the cursor. + // The cursor still points to the EOL position, which in this case is the + // beginning of the compound CRLF sequence. This ensures slices of + // [inclusive, exclusive) continue to work properly. + if (this.string[offset] === "\r" + && this.string[offset + 1] === "\n") { + return "\n"; + } + + return this.string[offset]; + } + + get currentChar() { + return this.charAt(this.index); + } + + get currentPeek() { + return this.charAt(this.index + this.peekOffset); + } + + next() { + this.peekOffset = 0; + // Skip over the CRLF as if it was a single character. + if (this.string[this.index] === "\r" + && this.string[this.index + 1] === "\n") { + this.index++; + } + this.index++; + return this.string[this.index]; + } + + peek() { + // Skip over the CRLF as if it was a single character. + if (this.string[this.index + this.peekOffset] === "\r" + && this.string[this.index + this.peekOffset + 1] === "\n") { + this.peekOffset++; + } + this.peekOffset++; + return this.string[this.index + this.peekOffset]; + } + + resetPeek(offset = 0) { + this.peekOffset = offset; + } + + skipToPeek() { + this.index += this.peekOffset; + this.peekOffset = 0; + } +} + +const EOL = "\n"; +const EOF = undefined; +const SPECIAL_LINE_START_CHARS = ["}", ".", "[", "*"]; + +class FluentParserStream extends ParserStream { + peekBlankInline() { + const start = this.index + this.peekOffset; + while (this.currentPeek === " ") { + this.peek(); + } + return this.string.slice(start, this.index + this.peekOffset); + } + + skipBlankInline() { + const blank = this.peekBlankInline(); + this.skipToPeek(); + return blank; + } + + peekBlankBlock() { + let blank = ""; + while (true) { + const lineStart = this.peekOffset; + this.peekBlankInline(); + if (this.currentPeek === EOL) { + blank += EOL; + this.peek(); + continue; + } + if (this.currentPeek === EOF) { + // Treat the blank line at EOF as a blank block. + return blank; + } + // Any other char; reset to column 1 on this line. + this.resetPeek(lineStart); + return blank; + } + } + + skipBlankBlock() { + const blank = this.peekBlankBlock(); + this.skipToPeek(); + return blank; + } + + peekBlank() { + while (this.currentPeek === " " || this.currentPeek === EOL) { + this.peek(); + } + } + + skipBlank() { + this.peekBlank(); + this.skipToPeek(); + } + + expectChar(ch) { + if (this.currentChar === ch) { + this.next(); + return true; + } + + throw new ParseError("E0003", ch); + } + + expectLineEnd() { + if (this.currentChar === EOF) { + // EOF is a valid line end in Fluent. + return true; + } + + if (this.currentChar === EOL) { + this.next(); + return true; + } + + // Unicode Character 'SYMBOL FOR NEWLINE' (U+2424) + throw new ParseError("E0003", "\u2424"); + } + + takeChar(f) { + const ch = this.currentChar; + if (ch === EOF) { + return EOF; + } + if (f(ch)) { + this.next(); + return ch; + } + return null; + } + + isCharIdStart(ch) { + if (ch === EOF) { + return false; + } + + const cc = ch.charCodeAt(0); + return (cc >= 97 && cc <= 122) || // a-z + (cc >= 65 && cc <= 90); // A-Z + } + + isIdentifierStart() { + return this.isCharIdStart(this.currentPeek); + } + + isNumberStart() { + const ch = this.currentChar === "-" + ? this.peek() + : this.currentChar; + + if (ch === EOF) { + this.resetPeek(); + return false; + } + + const cc = ch.charCodeAt(0); + const isDigit = cc >= 48 && cc <= 57; // 0-9 + this.resetPeek(); + return isDigit; + } + + isCharPatternContinuation(ch) { + if (ch === EOF) { + return false; + } + + return !includes(SPECIAL_LINE_START_CHARS, ch); + } + + isValueStart() { + // Inline Patterns may start with any char. + const ch = this.currentPeek; + return ch !== EOL && ch !== EOF; + } + + isValueContinuation() { + const column1 = this.peekOffset; + this.peekBlankInline(); + + if (this.currentPeek === "{") { + this.resetPeek(column1); + return true; + } + + if (this.peekOffset - column1 === 0) { + return false; + } + + if (this.isCharPatternContinuation(this.currentPeek)) { + this.resetPeek(column1); + return true; + } + + return false; + } + + // -1 - any + // 0 - comment + // 1 - group comment + // 2 - resource comment + isNextLineComment(level = -1) { + if (this.currentChar !== EOL) { + return false; + } + + let i = 0; + + while (i <= level || (level === -1 && i < 3)) { + if (this.peek() !== "#") { + if (i <= level && level !== -1) { + this.resetPeek(); + return false; + } + break; + } + i++; + } + + // The first char after #, ## or ###. + const ch = this.peek(); + if (ch === " " || ch === EOL) { + this.resetPeek(); + return true; + } + + this.resetPeek(); + return false; + } + + isVariantStart() { + const currentPeekOffset = this.peekOffset; + if (this.currentPeek === "*") { + this.peek(); + } + if (this.currentPeek === "[") { + this.resetPeek(currentPeekOffset); + return true; + } + this.resetPeek(currentPeekOffset); + return false; + } + + isAttributeStart() { + return this.currentPeek === "."; + } + + skipToNextEntryStart(junkStart) { + let lastNewline = this.string.lastIndexOf(EOL, this.index); + if (junkStart < lastNewline) { + // Last seen newline is _after_ the junk start. It's safe to rewind + // without the risk of resuming at the same broken entry. + this.index = lastNewline; + } + while (this.currentChar) { + // We're only interested in beginnings of line. + if (this.currentChar !== EOL) { + this.next(); + continue; + } + + // Break if the first char in this line looks like an entry start. + const first = this.next(); + if (this.isCharIdStart(first) || first === "-" || first === "#") { + break; + } + } + } + + takeIDStart() { + if (this.isCharIdStart(this.currentChar)) { + const ret = this.currentChar; + this.next(); + return ret; + } + + throw new ParseError("E0004", "a-zA-Z"); + } + + takeIDChar() { + const closure = ch => { + const cc = ch.charCodeAt(0); + return ((cc >= 97 && cc <= 122) || // a-z + (cc >= 65 && cc <= 90) || // A-Z + (cc >= 48 && cc <= 57) || // 0-9 + cc === 95 || cc === 45); // _- + }; + + return this.takeChar(closure); + } + + takeDigit() { + const closure = ch => { + const cc = ch.charCodeAt(0); + return (cc >= 48 && cc <= 57); // 0-9 + }; + + return this.takeChar(closure); + } + + takeHexDigit() { + const closure = ch => { + const cc = ch.charCodeAt(0); + return (cc >= 48 && cc <= 57) // 0-9 + || (cc >= 65 && cc <= 70) // A-F + || (cc >= 97 && cc <= 102); // a-f + }; + + return this.takeChar(closure); + } +} + +/* eslint no-magic-numbers: [0] */ + + +const trailingWSRe = /[ \t\n\r]+$/; + + +function withSpan(fn) { + return function(ps, ...args) { + if (!this.withSpans) { + return fn.call(this, ps, ...args); + } + + const start = ps.index; + const node = fn.call(this, ps, ...args); + + // Don't re-add the span if the node already has it. This may happen when + // one decorated function calls another decorated function. + if (node.span) { + return node; + } + + const end = ps.index; + node.addSpan(start, end); + return node; + }; +} + + +class FluentParser { + constructor({ + withSpans = true, + } = {}) { + this.withSpans = withSpans; + + // Poor man's decorators. + const methodNames = [ + "getComment", "getMessage", "getTerm", "getAttribute", "getIdentifier", + "getVariant", "getNumber", "getPattern", "getVariantList", + "getTextElement", "getPlaceable", "getExpression", + "getInlineExpression", "getCallArgument", "getString", + "getSimpleExpression", "getLiteral", + ]; + for (const name of methodNames) { + this[name] = withSpan(this[name]); + } + } + + parse(source) { + const ps = new FluentParserStream(source); + ps.skipBlankBlock(); + + const entries = []; + let lastComment = null; + + while (ps.currentChar) { + const entry = this.getEntryOrJunk(ps); + const blankLines = ps.skipBlankBlock(); + + // Regular Comments require special logic. Comments may be attached to + // Messages or Terms if they are followed immediately by them. However + // they should parse as standalone when they're followed by Junk. + // Consequently, we only attach Comments once we know that the Message + // or the Term parsed successfully. + if (entry.type === "Comment" + && blankLines.length === 0 + && ps.currentChar) { + // Stash the comment and decide what to do with it in the next pass. + lastComment = entry; + continue; + } + + if (lastComment) { + if (entry.type === "Message" || entry.type === "Term") { + entry.comment = lastComment; + if (this.withSpans) { + entry.span.start = entry.comment.span.start; + } + } else { + entries.push(lastComment); + } + // In either case, the stashed comment has been dealt with; clear it. + lastComment = null; + } + + // No special logic for other types of entries. + entries.push(entry); + } + + const res = new Resource(entries); + + if (this.withSpans) { + res.addSpan(0, ps.index); + } + + return res; + } + + /* + * Parse the first Message or Term in `source`. + * + * Skip all encountered comments and start parsing at the first Message or + * Term start. Return Junk if the parsing is not successful. + * + * Preceding comments are ignored unless they contain syntax errors + * themselves, in which case Junk for the invalid comment is returned. + */ + parseEntry(source) { + const ps = new FluentParserStream(source); + ps.skipBlankBlock(); + + while (ps.currentChar === "#") { + const skipped = this.getEntryOrJunk(ps); + if (skipped.type === "Junk") { + // Don't skip Junk comments. + return skipped; + } + ps.skipBlankBlock(); + } + + return this.getEntryOrJunk(ps); + } + + getEntryOrJunk(ps) { + const entryStartPos = ps.index; + + try { + const entry = this.getEntry(ps); + ps.expectLineEnd(); + return entry; + } catch (err) { + if (!(err instanceof ParseError)) { + throw err; + } + + let errorIndex = ps.index; + ps.skipToNextEntryStart(entryStartPos); + const nextEntryStart = ps.index; + if (nextEntryStart < errorIndex) { + // The position of the error must be inside of the Junk's span. + errorIndex = nextEntryStart; + } + + // Create a Junk instance + const slice = ps.string.substring(entryStartPos, nextEntryStart); + const junk = new Junk(slice); + if (this.withSpans) { + junk.addSpan(entryStartPos, nextEntryStart); + } + const annot = new Annotation(err.code, err.args, err.message); + annot.addSpan(errorIndex, errorIndex); + junk.addAnnotation(annot); + return junk; + } + } + + getEntry(ps) { + if (ps.currentChar === "#") { + return this.getComment(ps); + } + + if (ps.currentChar === "-") { + return this.getTerm(ps); + } + + if (ps.isIdentifierStart()) { + return this.getMessage(ps); + } + + throw new ParseError("E0002"); + } + + getComment(ps) { + // 0 - comment + // 1 - group comment + // 2 - resource comment + let level = -1; + let content = ""; + + while (true) { + let i = -1; + while (ps.currentChar === "#" && (i < (level === -1 ? 2 : level))) { + ps.next(); + i++; + } + + if (level === -1) { + level = i; + } + + if (ps.currentChar !== EOL) { + ps.expectChar(" "); + let ch; + while ((ch = ps.takeChar(x => x !== EOL))) { + content += ch; + } + } + + if (ps.isNextLineComment(level)) { + content += ps.currentChar; + ps.next(); + } else { + break; + } + } + + let Comment$$1; + switch (level) { + case 0: + Comment$$1 = Comment; + break; + case 1: + Comment$$1 = GroupComment; + break; + case 2: + Comment$$1 = ResourceComment; + break; + } + return new Comment$$1(content); + } + + getMessage(ps) { + const id = this.getIdentifier(ps); + + ps.skipBlankInline(); + ps.expectChar("="); + + const value = this.maybeGetPattern(ps); + const attrs = this.getAttributes(ps); + + if (value === null && attrs.length === 0) { + throw new ParseError("E0005", id.name); + } + + return new Message(id, value, attrs); + } + + getTerm(ps) { + ps.expectChar("-"); + const id = this.getIdentifier(ps); + + ps.skipBlankInline(); + ps.expectChar("="); + + // Syntax 0.8 compat: VariantLists are supported but deprecated. They can + // only be found as values of Terms. Nested VariantLists are not allowed. + const value = this.maybeGetVariantList(ps) || this.maybeGetPattern(ps); + if (value === null) { + throw new ParseError("E0006", id.name); + } + + const attrs = this.getAttributes(ps); + return new Term(id, value, attrs); + } + + getAttribute(ps) { + ps.expectChar("."); + + const key = this.getIdentifier(ps); + + ps.skipBlankInline(); + ps.expectChar("="); + + const value = this.maybeGetPattern(ps); + if (value === null) { + throw new ParseError("E0012"); + } + + return new Attribute(key, value); + } + + getAttributes(ps) { + const attrs = []; + ps.peekBlank(); + while (ps.isAttributeStart()) { + ps.skipToPeek(); + const attr = this.getAttribute(ps); + attrs.push(attr); + ps.peekBlank(); + } + return attrs; + } + + getIdentifier(ps) { + let name = ps.takeIDStart(); + + let ch; + while ((ch = ps.takeIDChar())) { + name += ch; + } + + return new Identifier(name); + } + + getVariantKey(ps) { + const ch = ps.currentChar; + + if (ch === EOF) { + throw new ParseError("E0013"); + } + + const cc = ch.charCodeAt(0); + + if ((cc >= 48 && cc <= 57) || cc === 45) { // 0-9, - + return this.getNumber(ps); + } + + return this.getIdentifier(ps); + } + + getVariant(ps, {hasDefault}) { + let defaultIndex = false; + + if (ps.currentChar === "*") { + if (hasDefault) { + throw new ParseError("E0015"); + } + ps.next(); + defaultIndex = true; + } + + ps.expectChar("["); + + ps.skipBlank(); + + const key = this.getVariantKey(ps); + + ps.skipBlank(); + ps.expectChar("]"); + + const value = this.maybeGetPattern(ps); + if (value === null) { + throw new ParseError("E0012"); + } + + return new Variant(key, value, defaultIndex); + } + + getVariants(ps) { + const variants = []; + let hasDefault = false; + + ps.skipBlank(); + while (ps.isVariantStart()) { + const variant = this.getVariant(ps, {hasDefault}); + + if (variant.default) { + hasDefault = true; + } + + variants.push(variant); + ps.expectLineEnd(); + ps.skipBlank(); + } + + if (variants.length === 0) { + throw new ParseError("E0011"); + } + + if (!hasDefault) { + throw new ParseError("E0010"); + } + + return variants; + } + + getDigits(ps) { + let num = ""; + + let ch; + while ((ch = ps.takeDigit())) { + num += ch; + } + + if (num.length === 0) { + throw new ParseError("E0004", "0-9"); + } + + return num; + } + + getNumber(ps) { + let num = ""; + + if (ps.currentChar === "-") { + num += "-"; + ps.next(); + } + + num = `${num}${this.getDigits(ps)}`; + + if (ps.currentChar === ".") { + num += "."; + ps.next(); + num = `${num}${this.getDigits(ps)}`; + } + + return new NumberLiteral(num); + } + + // maybeGetPattern distinguishes between patterns which start on the same line + // as the identifier (a.k.a. inline signleline patterns and inline multiline + // patterns) and patterns which start on a new line (a.k.a. block multiline + // patterns). The distinction is important for the dedentation logic: the + // indent of the first line of a block pattern must be taken into account when + // calculating the maximum common indent. + maybeGetPattern(ps) { + ps.peekBlankInline(); + if (ps.isValueStart()) { + ps.skipToPeek(); + return this.getPattern(ps, {isBlock: false}); + } + + ps.peekBlankBlock(); + if (ps.isValueContinuation()) { + ps.skipToPeek(); + return this.getPattern(ps, {isBlock: true}); + } + + return null; + } + + // Deprecated in Syntax 0.8. VariantLists are only allowed as values of Terms. + // Values of Messages, Attributes and Variants must be Patterns. This method + // is only used in getTerm. + maybeGetVariantList(ps) { + ps.peekBlank(); + if (ps.currentPeek === "{") { + const start = ps.peekOffset; + ps.peek(); + ps.peekBlankInline(); + if (ps.currentPeek === EOL) { + ps.peekBlank(); + if (ps.isVariantStart()) { + ps.resetPeek(start); + ps.skipToPeek(); + return this.getVariantList(ps); + } + } + } + + ps.resetPeek(); + return null; + } + + getVariantList(ps) { + ps.expectChar("{"); + var variants = this.getVariants(ps); + ps.expectChar("}"); + return new VariantList(variants); + } + + getPattern(ps, {isBlock}) { + const elements = []; + if (isBlock) { + // A block pattern is a pattern which starts on a new line. Store and + // measure the indent of this first line for the dedentation logic. + const blankStart = ps.index; + const firstIndent = ps.skipBlankInline(); + elements.push(this.getIndent(ps, firstIndent, blankStart)); + var commonIndentLength = firstIndent.length; + } else { + var commonIndentLength = Infinity; + } + + let ch; + elements: while ((ch = ps.currentChar)) { + switch (ch) { + case EOL: { + const blankStart = ps.index; + const blankLines = ps.peekBlankBlock(); + if (ps.isValueContinuation()) { + ps.skipToPeek(); + const indent = ps.skipBlankInline(); + commonIndentLength = Math.min(commonIndentLength, indent.length); + elements.push(this.getIndent(ps, blankLines + indent, blankStart)); + continue elements; + } + + // The end condition for getPattern's while loop is a newline + // which is not followed by a valid pattern continuation. + ps.resetPeek(); + break elements; + } + case "{": + elements.push(this.getPlaceable(ps)); + continue elements; + case "}": + throw new ParseError("E0027"); + default: + const element = this.getTextElement(ps); + elements.push(element); + } + } + + const dedented = this.dedent(elements, commonIndentLength); + return new Pattern(dedented); + } + + // Create a token representing an indent. It's not part of the AST and it will + // be trimmed and merged into adjacent TextElements, or turned into a new + // TextElement, if it's surrounded by two Placeables. + getIndent(ps, value, start) { + return { + type: "Indent", + span: {start, end: ps.index}, + value, + }; + } + + // Dedent a list of elements by removing the maximum common indent from the + // beginning of text lines. The common indent is calculated in getPattern. + dedent(elements, commonIndent) { + const trimmed = []; + + for (let element of elements) { + if (element.type === "Placeable") { + trimmed.push(element); + continue; + } + + if (element.type === "Indent") { + // Strip common indent. + element.value = element.value.slice( + 0, element.value.length - commonIndent); + if (element.value.length === 0) { + continue; + } + } + + let prev = trimmed[trimmed.length - 1]; + if (prev && prev.type === "TextElement") { + // Join adjacent TextElements by replacing them with their sum. + const sum = new TextElement(prev.value + element.value); + if (this.withSpans) { + sum.addSpan(prev.span.start, element.span.end); + } + trimmed[trimmed.length - 1] = sum; + continue; + } + + if (element.type === "Indent") { + // If the indent hasn't been merged into a preceding TextElement, + // convert it into a new TextElement. + const textElement = new TextElement(element.value); + if (this.withSpans) { + textElement.addSpan(element.span.start, element.span.end); + } + element = textElement; + } + + trimmed.push(element); + } + + // Trim trailing whitespace from the Pattern. + const lastElement = trimmed[trimmed.length - 1]; + if (lastElement.type === "TextElement") { + lastElement.value = lastElement.value.replace(trailingWSRe, ""); + if (lastElement.value.length === 0) { + trimmed.pop(); + } + } + + return trimmed; + } + + getTextElement(ps) { + let buffer = ""; + + let ch; + while ((ch = ps.currentChar)) { + if (ch === "{" || ch === "}") { + return new TextElement(buffer); + } + + if (ch === EOL) { + return new TextElement(buffer); + } + + buffer += ch; + ps.next(); + } + + return new TextElement(buffer); + } + + getEscapeSequence(ps) { + const next = ps.currentChar; + + switch (next) { + case "\\": + case "\"": + ps.next(); + return [`\\${next}`, next]; + case "u": + return this.getUnicodeEscapeSequence(ps, next, 4); + case "U": + return this.getUnicodeEscapeSequence(ps, next, 6); + default: + throw new ParseError("E0025", next); + } + } + + getUnicodeEscapeSequence(ps, u, digits) { + ps.expectChar(u); + + let sequence = ""; + for (let i = 0; i < digits; i++) { + const ch = ps.takeHexDigit(); + + if (!ch) { + throw new ParseError( + "E0026", `\\${u}${sequence}${ps.currentChar}`); + } + + sequence += ch; + } + + const codepoint = parseInt(sequence, 16); + const unescaped = codepoint <= 0xD7FF || 0xE000 <= codepoint + // It's a Unicode scalar value. + ? String.fromCodePoint(codepoint) + // Escape sequences reresenting surrogate code points are well-formed + // but invalid in Fluent. Replace them with U+FFFD REPLACEMENT + // CHARACTER. + : "�"; + return [`\\${u}${sequence}`, unescaped]; + } + + getPlaceable(ps) { + ps.expectChar("{"); + ps.skipBlank(); + const expression = this.getExpression(ps); + ps.expectChar("}"); + return new Placeable(expression); + } + + getExpression(ps) { + const selector = this.getInlineExpression(ps); + ps.skipBlank(); + + if (ps.currentChar === "-") { + if (ps.peek() !== ">") { + ps.resetPeek(); + return selector; + } + + if (selector.type === "MessageReference") { + throw new ParseError("E0016"); + } + + if (selector.type === "AttributeExpression" + && selector.ref.type === "MessageReference") { + throw new ParseError("E0018"); + } + + if (selector.type === "TermReference" + || selector.type === "VariantExpression") { + throw new ParseError("E0017"); + } + + if (selector.type === "CallExpression" + && selector.callee.type === "TermReference") { + throw new ParseError("E0017"); + } + + ps.next(); + ps.next(); + + ps.skipBlankInline(); + ps.expectLineEnd(); + + const variants = this.getVariants(ps); + return new SelectExpression(selector, variants); + } + + if (selector.type === "AttributeExpression" + && selector.ref.type === "TermReference") { + throw new ParseError("E0019"); + } + + if (selector.type === "CallExpression" + && selector.callee.type === "AttributeExpression") { + throw new ParseError("E0019"); + } + + return selector; + } + + getInlineExpression(ps) { + if (ps.currentChar === "{") { + return this.getPlaceable(ps); + } + + let expr = this.getSimpleExpression(ps); + switch (expr.type) { + case "NumberLiteral": + case "StringLiteral": + case "VariableReference": + return expr; + case "MessageReference": { + if (ps.currentChar === ".") { + ps.next(); + const attr = this.getIdentifier(ps); + return new AttributeExpression(expr, attr); + } + + if (ps.currentChar === "(") { + // It's a Function. Ensure it's all upper-case. + if (!/^[A-Z][A-Z_?-]*$/.test(expr.id.name)) { + throw new ParseError("E0008"); + } + + const func = new FunctionReference(expr.id); + if (this.withSpans) { + func.addSpan(expr.span.start, expr.span.end); + } + return new CallExpression(func, ...this.getCallArguments(ps)); + } + + return expr; + } + case "TermReference": { + if (ps.currentChar === "[") { + ps.next(); + const key = this.getVariantKey(ps); + ps.expectChar("]"); + return new VariantExpression(expr, key); + } + + if (ps.currentChar === ".") { + ps.next(); + const attr = this.getIdentifier(ps); + expr = new AttributeExpression(expr, attr); + } + + if (ps.currentChar === "(") { + return new CallExpression(expr, ...this.getCallArguments(ps)); + } + + return expr; + } + default: + throw new ParseError("E0028"); + } + } + + getSimpleExpression(ps) { + if (ps.isNumberStart()) { + return this.getNumber(ps); + } + + if (ps.currentChar === '"') { + return this.getString(ps); + } + + if (ps.currentChar === "$") { + ps.next(); + const id = this.getIdentifier(ps); + return new VariableReference(id); + } + + if (ps.currentChar === "-") { + ps.next(); + const id = this.getIdentifier(ps); + return new TermReference(id); + } + + if (ps.isIdentifierStart()) { + const id = this.getIdentifier(ps); + return new MessageReference(id); + } + + throw new ParseError("E0028"); + } + + getCallArgument(ps) { + const exp = this.getInlineExpression(ps); + + ps.skipBlank(); + + if (ps.currentChar !== ":") { + return exp; + } + + if (exp.type !== "MessageReference") { + throw new ParseError("E0009"); + } + + ps.next(); + ps.skipBlank(); + + const value = this.getLiteral(ps); + return new NamedArgument(exp.id, value); + } + + getCallArguments(ps) { + const positional = []; + const named = []; + const argumentNames = new Set(); + + ps.expectChar("("); + ps.skipBlank(); + + while (true) { + if (ps.currentChar === ")") { + break; + } + + const arg = this.getCallArgument(ps); + if (arg.type === "NamedArgument") { + if (argumentNames.has(arg.name.name)) { + throw new ParseError("E0022"); + } + named.push(arg); + argumentNames.add(arg.name.name); + } else if (argumentNames.size > 0) { + throw new ParseError("E0021"); + } else { + positional.push(arg); + } + + ps.skipBlank(); + + if (ps.currentChar === ",") { + ps.next(); + ps.skipBlank(); + continue; + } + + break; + } + + ps.expectChar(")"); + return [positional, named]; + } + + getString(ps) { + let raw = ""; + let value = ""; + + ps.expectChar("\""); + + let ch; + while ((ch = ps.takeChar(x => x !== '"' && x !== EOL))) { + if (ch === "\\") { + const [sequence, unescaped] = this.getEscapeSequence(ps); + raw += sequence; + value += unescaped; + } else { + raw += ch; + value += ch; + } + } + + if (ps.currentChar === EOL) { + throw new ParseError("E0020"); + } + + ps.expectChar("\""); + + return new StringLiteral(raw, value); + } + + getLiteral(ps) { + if (ps.isNumberStart()) { + return this.getNumber(ps); + } + + if (ps.currentChar === '"') { + return this.getString(ps); + } + + throw new ParseError("E0014"); + } +} + +function indent(content) { + return content.split("\n").join("\n "); +} + +function includesNewLine(elem) { + return elem.type === "TextElement" && includes(elem.value, "\n"); +} + +function isSelectExpr(elem) { + return elem.type === "Placeable" + && elem.expression.type === "SelectExpression"; +} + +// Bit masks representing the state of the serializer. +const HAS_ENTRIES = 1; + +class FluentSerializer { + constructor({ withJunk = false } = {}) { + this.withJunk = withJunk; + } + + serialize(resource) { + if (resource.type !== "Resource") { + throw new Error(`Unknown resource type: ${resource.type}`); + } + + let state = 0; + const parts = []; + + for (const entry of resource.body) { + if (entry.type !== "Junk" || this.withJunk) { + parts.push(this.serializeEntry(entry, state)); + if (!(state & HAS_ENTRIES)) { + state |= HAS_ENTRIES; + } + } + } + + return parts.join(""); + } + + serializeEntry(entry, state = 0) { + switch (entry.type) { + case "Message": + return serializeMessage(entry); + case "Term": + return serializeTerm(entry); + case "Comment": + if (state & HAS_ENTRIES) { + return `\n${serializeComment(entry, "#")}\n`; + } + return `${serializeComment(entry, "#")}\n`; + case "GroupComment": + if (state & HAS_ENTRIES) { + return `\n${serializeComment(entry, "##")}\n`; + } + return `${serializeComment(entry, "##")}\n`; + case "ResourceComment": + if (state & HAS_ENTRIES) { + return `\n${serializeComment(entry, "###")}\n`; + } + return `${serializeComment(entry, "###")}\n`; + case "Junk": + return serializeJunk(entry); + default : + throw new Error(`Unknown entry type: ${entry.type}`); + } + } + + serializeExpression(expr) { + return serializeExpression(expr); + } +} + + +function serializeComment(comment, prefix = "#") { + const prefixed = comment.content.split("\n").map( + line => line.length ? `${prefix} ${line}` : prefix + ).join("\n"); + // Add the trailing newline. + return `${prefixed}\n`; +} + + +function serializeJunk(junk) { + return junk.content; +} + + +function serializeMessage(message) { + const parts = []; + + if (message.comment) { + parts.push(serializeComment(message.comment)); + } + + parts.push(`${message.id.name} =`); + + if (message.value) { + parts.push(serializeValue(message.value)); + } + + for (const attribute of message.attributes) { + parts.push(serializeAttribute(attribute)); + } + + parts.push("\n"); + return parts.join(""); +} + + +function serializeTerm(term) { + const parts = []; + + if (term.comment) { + parts.push(serializeComment(term.comment)); + } + + parts.push(`-${term.id.name} =`); + parts.push(serializeValue(term.value)); + + for (const attribute of term.attributes) { + parts.push(serializeAttribute(attribute)); + } + + parts.push("\n"); + return parts.join(""); +} + + +function serializeAttribute(attribute) { + const value = indent(serializeValue(attribute.value)); + return `\n .${attribute.id.name} =${value}`; +} + + +function serializeValue(value) { + switch (value.type) { + case "Pattern": + return serializePattern(value); + case "VariantList": + return serializeVariantList(value); + default: + throw new Error(`Unknown value type: ${value.type}`); + } +} + + +function serializePattern(pattern) { + const content = pattern.elements.map(serializeElement).join(""); + const startOnNewLine = + pattern.elements.some(isSelectExpr) || + pattern.elements.some(includesNewLine); + + if (startOnNewLine) { + return `\n ${indent(content)}`; + } + + return ` ${content}`; +} + + +function serializeVariantList(varlist) { + const content = varlist.variants.map(serializeVariant).join(""); + return `\n {${indent(content)}\n }`; +} + + +function serializeVariant(variant) { + const key = serializeVariantKey(variant.key); + const value = indent(serializeValue(variant.value)); + + if (variant.default) { + return `\n *[${key}]${value}`; + } + + return `\n [${key}]${value}`; +} + + +function serializeElement(element) { + switch (element.type) { + case "TextElement": + return element.value; + case "Placeable": + return serializePlaceable(element); + default: + throw new Error(`Unknown element type: ${element.type}`); + } +} + + +function serializePlaceable(placeable) { + const expr = placeable.expression; + + switch (expr.type) { + case "Placeable": + return `{${serializePlaceable(expr)}}`; + case "SelectExpression": + // Special-case select expression to control the whitespace around the + // opening and the closing brace. + return `{ ${serializeSelectExpression(expr)}}`; + default: + return `{ ${serializeExpression(expr)} }`; + } +} + + +function serializeExpression(expr) { + switch (expr.type) { + case "StringLiteral": + return `"${expr.raw}"`; + case "NumberLiteral": + return expr.value; + case "MessageReference": + case "FunctionReference": + return expr.id.name; + case "TermReference": + return `-${expr.id.name}`; + case "VariableReference": + return `$${expr.id.name}`; + case "AttributeExpression": + return serializeAttributeExpression(expr); + case "VariantExpression": + return serializeVariantExpression(expr); + case "CallExpression": + return serializeCallExpression(expr); + case "SelectExpression": + return serializeSelectExpression(expr); + case "Placeable": + return serializePlaceable(expr); + default: + throw new Error(`Unknown expression type: ${expr.type}`); + } +} + + +function serializeSelectExpression(expr) { + const parts = []; + const selector = `${serializeExpression(expr.selector)} ->`; + parts.push(selector); + + for (const variant of expr.variants) { + parts.push(serializeVariant(variant)); + } + + parts.push("\n"); + return parts.join(""); +} + + +function serializeAttributeExpression(expr) { + const ref = serializeExpression(expr.ref); + return `${ref}.${expr.name.name}`; +} + + +function serializeVariantExpression(expr) { + const ref = serializeExpression(expr.ref); + const key = serializeVariantKey(expr.key); + return `${ref}[${key}]`; +} + + +function serializeCallExpression(expr) { + const callee = serializeExpression(expr.callee); + const positional = expr.positional.map(serializeExpression).join(", "); + const named = expr.named.map(serializeNamedArgument).join(", "); + if (expr.positional.length > 0 && expr.named.length > 0) { + return `${callee}(${positional}, ${named})`; + } + return `${callee}(${positional || named})`; +} + + +function serializeNamedArgument(arg) { + const value = serializeExpression(arg.value); + return `${arg.name.name}: ${value}`; +} + + +function serializeVariantKey(key) { + switch (key.type) { + case "Identifier": + return key.name; + default: + return serializeExpression(key); + } +} + +/* eslint object-shorthand: "off", + no-unused-vars: "off", + no-redeclare: "off", + comma-dangle: "off", + no-labels: "off" */ + +this.EXPORTED_SYMBOLS = [ + "FluentParser", + "FluentSerializer", + ...Object.keys(ast), +]; diff --git a/intl/l10n/moz.build b/intl/l10n/moz.build index 85be6e0f9ce7..719e89ed6196 100644 --- a/intl/l10n/moz.build +++ b/intl/l10n/moz.build @@ -7,6 +7,7 @@ EXTRA_JS_MODULES += [ 'DOMLocalization.jsm', 'Fluent.jsm', + 'FluentSyntax.jsm', 'L10nRegistry.jsm', 'Localization.jsm', ] From b6a41eda703bed545d077c36d43a5b948eeab45c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 14 Feb 2019 14:43:51 +0000 Subject: [PATCH 18/84] Bug 1527724 - Let the preselected result not modify the urlbar value. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D19762 --HG-- extra : moz-landing-system : lando --- browser/components/urlbar/UrlbarView.jsm | 4 ++-- .../urlbar/tests/browser/browser_action_searchengine_alias.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/browser/components/urlbar/UrlbarView.jsm b/browser/components/urlbar/UrlbarView.jsm index 5327c68b2dd8..82e1f7fe8b20 100644 --- a/browser/components/urlbar/UrlbarView.jsm +++ b/browser/components/urlbar/UrlbarView.jsm @@ -162,7 +162,7 @@ class UrlbarView { if (queryContext.lastResultCount == 0) { if (queryContext.preselected) { - this._selectItem(fragment.firstElementChild); + this._selectItem(fragment.firstElementChild, false); } else { // Clear the selection when we get a new set of results. this._selectItem(null); @@ -172,7 +172,7 @@ class UrlbarView { // TODO bug 1523602: the selection should stay on the node that had it, if // it's still in the current result set. let resultIndex = this._selected.getAttribute("resultIndex"); - this._selectItem(fragment.children[resultIndex]); + this._selectItem(fragment.children[resultIndex], false); } // TODO bug 1523602: For now, clear the results for each set received. diff --git a/browser/components/urlbar/tests/browser/browser_action_searchengine_alias.js b/browser/components/urlbar/tests/browser/browser_action_searchengine_alias.js index ca86f5601096..63194202956d 100644 --- a/browser/components/urlbar/tests/browser/browser_action_searchengine_alias.js +++ b/browser/components/urlbar/tests/browser/browser_action_searchengine_alias.js @@ -31,6 +31,10 @@ add_task(async function() { await PlacesUtils.history.clear(); }); + await promiseAutocompleteResultPopup("moz"); + Assert.equal(gURLBar.textValue, "moz", + "Preselected search keyword result shouldn't automatically add a space"); + await promiseAutocompleteResultPopup("moz open a search"); let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0); if (UrlbarPrefs.get("quantumbar")) { From 3571f40e763508024fb87c4ddc3c5dad76a0f1bc Mon Sep 17 00:00:00 2001 From: Dimi Lee Date: Thu, 14 Feb 2019 13:29:45 +0000 Subject: [PATCH 19/84] Bug 1526885 - P1. Add extensions to download protectionn executable list. r=gcp Those extensions are set to SAMPLED_PING by google, which means they are not really dangerous. Add these extensions to sync up with google's list but comment them because we don't need to trigger remote lookup request for them. Differential Revision: https://phabricator.services.mozilla.com/D19758 --HG-- extra : moz-landing-system : lando --- .../ApplicationReputation.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/toolkit/components/reputationservice/ApplicationReputation.cpp b/toolkit/components/reputationservice/ApplicationReputation.cpp index af8c91091d15..106ec91fcc09 100644 --- a/toolkit/components/reputationservice/ApplicationReputation.cpp +++ b/toolkit/components/reputationservice/ApplicationReputation.cpp @@ -491,6 +491,7 @@ static const char* const kBinaryFileExtensions[] = { ".crt", // Windows signed certificate ".crx", // Chrome extensions ".csh", // Linux shell + //".csv", ".dart", // Mac disk image ".dc42", // Apple DiskCopy Image ".deb", // Linux package @@ -503,6 +504,7 @@ static const char* const kBinaryFileExtensions[] = { ".dll", // Windows executable ".dmg", // Mac disk image ".dmgpart", // Mac disk image + //".doc", //".docb", // MS Office //".docm", // MS Word //".docx", // MS Word @@ -517,6 +519,7 @@ static const char* const kBinaryFileExtensions[] = { ".fon", // Windows font ".fxp", // MS FoxPro ".gadget", // Windows + //".gif", ".grp", // Windows ".gz", // Linux archive (gzip) ".gzip", // Linux archive (gzip) @@ -526,6 +529,7 @@ static const char* const kBinaryFileExtensions[] = { ".hta", // HTML trusted application ".htm", ".html", ".htt", // MS HTML template + //".ica", ".img", // Mac disk image ".imgpart", // Mac disk image ".inf", // Windows installer @@ -538,6 +542,8 @@ static const char* const kBinaryFileExtensions[] = { ".jar", // Java ".jnlp", // Java //".job", // Windows + //".jpg", + //".jpeg", ".js", // JavaScript script ".jse", // JScript ".ksh", // Linux shell @@ -570,8 +576,12 @@ static const char* const kBinaryFileExtensions[] = { ".mht", // MS HTML ".mhtml", // MS HTML ".mim", // MS Mail + //".mkv", ".mmc", // MS Office ".mof", // Windows + //".mov", + //".mp3", + //".mp4", ".mpkg", // Mac installer ".msc", // Windows executable ".msg", // MS Outlook @@ -592,6 +602,7 @@ static const char* const kBinaryFileExtensions[] = { ".osax", // AppleScript //".out", // Linux binary ".oxt", // OpenOffice extension, can execute arbitrary code + //".package", //".paf", // PortableApps package //".paq8f", //".paq8jd", @@ -607,9 +618,11 @@ static const char* const kBinaryFileExtensions[] = { ".pkg", // Mac installer ".pl", // Perl script ".plg", // MS Visual Studio + //".png", //".potx", // MS PowerPoint //".ppam", // MS PowerPoint //".ppsx", // MS PowerPoint + //".ppt", //".pptm", // MS PowerPoint //".pptx", // MS PowerPoint ".prf", // MS Outlook @@ -699,10 +712,12 @@ static const char* const kBinaryFileExtensions[] = { ".tbz", // Linux archive (bzip2) ".tbz2", // Linux archive (bzip2) ".tcsh", // Linux shell + //".tif", ".tgz", // Linux archive (gzip) //".toast", // Roxio disk image ".torrent", // Bittorrent ".tpz", // Linux archive (gzip) + //".txt", ".txz", // Linux archive (xz) ".tz", // Linux archive (gzip) //".u3p", // U3 Smart Apps @@ -732,6 +747,8 @@ static const char* const kBinaryFileExtensions[] = { ".vsw", // MS Visio ".vsx", // MS Visio ".vtx", // MS Visio + //".wav", + //".webp", ".website", // Windows ".wim", // Windows Imaging //".workflow", // Mac Automator @@ -744,6 +761,7 @@ static const char* const kBinaryFileExtensions[] = { ".xbap", // XAML Browser Application ".xhtml", ".xhtm", ".xht", ".xip", // Mac archive + //".xls", //".xlsm", // MS Excel //".xlsx", // MS Excel //".xltm", // MS Excel From 418cd3709cd6d9d306b7f4991cb83570f62f1ea4 Mon Sep 17 00:00:00 2001 From: Dimi Lee Date: Thu, 14 Feb 2019 13:30:38 +0000 Subject: [PATCH 20/84] Bug 1526885 - P2. Add MS Office files to the list of executable extensions in download protection. r=gcp Sync with the list in chrome, chrome adds office docs because they have been abused in the past through embedded executables. Differential Revision: https://phabricator.services.mozilla.com/D19759 --HG-- extra : moz-landing-system : lando --- .../ApplicationReputation.cpp | 144 ++++++++++-------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/toolkit/components/reputationservice/ApplicationReputation.cpp b/toolkit/components/reputationservice/ApplicationReputation.cpp index 106ec91fcc09..c70e217af9eb 100644 --- a/toolkit/components/reputationservice/ApplicationReputation.cpp +++ b/toolkit/components/reputationservice/ApplicationReputation.cpp @@ -487,10 +487,10 @@ static const char* const kBinaryFileExtensions[] = { ".cpi", // Control Panel Item. Executable used for adding icons // to Control Panel //".cpio", - ".cpl", // Windows executable - ".crt", // Windows signed certificate - ".crx", // Chrome extensions - ".csh", // Linux shell + ".cpl", // Windows executable + ".crt", // Windows signed certificate + ".crx", // Chrome extensions + ".csh", // Linux shell //".csv", ".dart", // Mac disk image ".dc42", // Apple DiskCopy Image @@ -504,31 +504,33 @@ static const char* const kBinaryFileExtensions[] = { ".dll", // Windows executable ".dmg", // Mac disk image ".dmgpart", // Mac disk image - //".doc", - //".docb", // MS Office - //".docm", // MS Word - //".docx", // MS Word - //".dotm", // MS Word - //".dott", // MS Office - ".drv", // Windows driver - ".dvdr", // Mac Disk image - ".efi", // Firmware - ".eml", // MS Outlook - ".exe", // Windows executable + ".doc", // MS Office + ".docb", // MS Office + ".docm", // MS Word + ".docx", // MS Word + ".dot", // MS Word + ".dotm", // MS Word + ".dott", // MS Office + ".dotx", // MS Word + ".drv", // Windows driver + ".dvdr", // Mac Disk image + ".efi", // Firmware + ".eml", // MS Outlook + ".exe", // Windows executable //".fat", ".fon", // Windows font ".fxp", // MS FoxPro ".gadget", // Windows //".gif", - ".grp", // Windows - ".gz", // Linux archive (gzip) - ".gzip", // Linux archive (gzip) - ".hfs", // Mac disk image - ".hlp", // Windows Help - ".hqx", // Mac archive - ".hta", // HTML trusted application + ".grp", // Windows + ".gz", // Linux archive (gzip) + ".gzip", // Linux archive (gzip) + ".hfs", // Mac disk image + ".hlp", // Windows Help + ".hqx", // Mac archive + ".hta", // HTML trusted application ".htm", ".html", - ".htt", // MS HTML template + ".htt", // MS HTML template //".ica", ".img", // Mac disk image ".imgpart", // Mac disk image @@ -577,24 +579,24 @@ static const char* const kBinaryFileExtensions[] = { ".mhtml", // MS HTML ".mim", // MS Mail //".mkv", - ".mmc", // MS Office - ".mof", // Windows + ".mmc", // MS Office + ".mof", // Windows //".mov", //".mp3", //".mp4", - ".mpkg", // Mac installer - ".msc", // Windows executable - ".msg", // MS Outlook - ".msh", // Windows shell - ".msh1", // Windows shell - ".msh1xml", // Windows shell - ".msh2", // Windows shell - ".msh2xml", // Windows shell - ".mshxml", // Windows - ".msi", // Windows installer - ".msp", // Windows installer - ".mst", // Windows installer - ".ndif", // Mac disk image + ".mpkg", // Mac installer + ".msc", // Windows executable + ".msg", // MS Outlook + ".msh", // Windows shell + ".msh1", // Windows shell + ".msh1xml", // Windows shell + ".msh2", // Windows shell + ".msh2xml", // Windows shell + ".mshxml", // Windows + ".msi", // Windows installer + ".msp", // Windows installer + ".mst", // Windows installer + ".ndif", // Mac disk image //".ntfs", // 7z ".ocx", // ActiveX ".ops", // MS Office @@ -619,12 +621,16 @@ static const char* const kBinaryFileExtensions[] = { ".pl", // Perl script ".plg", // MS Visual Studio //".png", - //".potx", // MS PowerPoint - //".ppam", // MS PowerPoint - //".ppsx", // MS PowerPoint - //".ppt", - //".pptm", // MS PowerPoint - //".pptx", // MS PowerPoint + ".pot", // MS PowerPoint + ".potm", // MS PowerPoint + ".potx", // MS PowerPoint + ".ppam", // MS PowerPoint + ".pps", // MS PowerPoint + ".ppsm", // MS PowerPoint + ".ppsx", // MS PowerPoint + ".ppt", // MS PowerPoint + ".pptm", // MS PowerPoint + ".pptx", // MS PowerPoint ".prf", // MS Outlook ".prg", // Windows ".ps1", // Windows shell @@ -677,7 +683,7 @@ static const char* const kBinaryFileExtensions[] = { ".rels", // MS Office //".rgs", // Windows Registry ".rpm", // Linux package - //".rtf", // MS Office + ".rtf", // MS Office //".run", // Linux shell ".scf", // Windows shell ".scpt", // AppleScript @@ -694,14 +700,14 @@ static const char* const kBinaryFileExtensions[] = { ".shtml", // HTML ".shtm", // HTML ".sht", // HTML - //".sldm", // MS PowerPoint - //".sldx", // MS PowerPoint - ".slk", // MS Excel - ".slp", // Linux package - ".smi", // Mac disk image - ".sparsebundle", // Mac disk image - ".sparseimage", // Mac disk image - ".spl", // Adobe Flash + ".sldm", // MS PowerPoint + ".sldx", // MS PowerPoint + ".slk", // MS Excel + ".slp", // Linux package + ".smi", // Mac disk image + ".sparsebundle", // Mac disk image + ".sparseimage", // Mac disk image + ".spl", // Adobe Flash //".squashfs", ".svg", ".swf", // Adobe Flash @@ -713,13 +719,13 @@ static const char* const kBinaryFileExtensions[] = { ".tbz2", // Linux archive (bzip2) ".tcsh", // Linux shell //".tif", - ".tgz", // Linux archive (gzip) + ".tgz", // Linux archive (gzip) //".toast", // Roxio disk image ".torrent", // Bittorrent ".tpz", // Linux archive (gzip) //".txt", - ".txz", // Linux archive (xz) - ".tz", // Linux archive (gzip) + ".txz", // Linux archive (xz) + ".tz", // Linux archive (gzip) //".u3p", // U3 Smart Apps ".udf", // MS Excel ".udif", // Mac disk image @@ -749,8 +755,8 @@ static const char* const kBinaryFileExtensions[] = { ".vtx", // MS Visio //".wav", //".webp", - ".website", // Windows - ".wim", // Windows Imaging + ".website", // Windows + ".wim", // Windows Imaging //".workflow", // Mac Automator //".wrc", // FreeArc archive ".ws", // Windows script @@ -760,13 +766,21 @@ static const char* const kBinaryFileExtensions[] = { ".xar", // MS Excel ".xbap", // XAML Browser Application ".xhtml", ".xhtm", ".xht", - ".xip", // Mac archive - //".xls", - //".xlsm", // MS Excel - //".xlsx", // MS Excel - //".xltm", // MS Excel - //".xltx", // MS Excel - ".xml", + ".xip", // Mac archive + ".xla", // MS Excel + ".xlam", // MS Excel + ".xldm", // MS Excel + ".xll", // MS Excel + ".xlm", // MS Excel + ".xls", // MS Excel + ".xlsb", // MS Excel + ".xlsm", // MS Excel + ".xlsx", // MS Excel + ".xlt", // MS Excel + ".xltm", // MS Excel + ".xltx", // MS Excel + ".xlw", // MS Excel + ".xml", // MS Excel ".xnk", // MS Exchange ".xrm-ms", // Windows ".xsl", // XML Stylesheet From 55264a1e43f4c35e6336b30331376b5d17f385c2 Mon Sep 17 00:00:00 2001 From: Bogdan Tara Date: Thu, 14 Feb 2019 17:29:40 +0200 Subject: [PATCH 21/84] Backed out changeset 14f7c02566c2 (bug 1525125) for browser_ext_windows_create_tabId.js failures CLOSED TREE --- browser/base/content/browser.js | 2 +- browser/base/content/utilityOverlay.js | 17 +- .../extensions/ExtensionControlledPopup.jsm | 9 +- .../extensions/parent/ext-windows.js | 9 +- ...wser_ext_chrome_settings_overrides_home.js | 124 ------------ .../browser_ext_url_overrides_newtab.js | 183 ------------------ browser/components/nsBrowserContentHandler.js | 10 +- .../components/sessionstore/SessionStore.jsm | 2 +- browser/modules/HomePage.jsm | 26 +-- 9 files changed, 13 insertions(+), 369 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index d9237bd5036c..9994cb518a03 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2174,7 +2174,7 @@ function BrowserHome(aEvent) { aEvent.button == 2) // right-click: do nothing return; - var homePage = HomePage.get(window); + var homePage = HomePage.get(); var where = whereToOpenLink(aEvent, false, true); var urls; var notifyObservers; diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 896fe5c6fc25..e1fd134a7985 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -24,19 +24,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", Object.defineProperty(this, "BROWSER_NEW_TAB_URL", { enumerable: true, get() { - if (PrivateBrowsingUtils.isWindowPrivate(window)) { - if (!PrivateBrowsingUtils.permanentPrivateBrowsing && - !aboutNewTabService.overridden) { - return "about:privatebrowsing"; - } - // If the extension does not have private browsing permission, - // use about:privatebrowsing. - if (aboutNewTabService.newTabURL.startsWith("moz-extension")) { - let url = new URL(aboutNewTabService.newTabURL); - if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) { - return "about:privatebrowsing"; - } - } + if (PrivateBrowsingUtils.isWindowPrivate(window) && + !PrivateBrowsingUtils.permanentPrivateBrowsing && + !aboutNewTabService.overridden) { + return "about:privatebrowsing"; } return aboutNewTabService.newTabURL; }, diff --git a/browser/components/extensions/ExtensionControlledPopup.jsm b/browser/components/extensions/ExtensionControlledPopup.jsm index f264a4582942..821cdca9fa63 100644 --- a/browser/components/extensions/ExtensionControlledPopup.jsm +++ b/browser/components/extensions/ExtensionControlledPopup.jsm @@ -31,8 +31,6 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); -ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); let { makeWidgetId, @@ -197,12 +195,6 @@ class ExtensionControlledPopup { extensionId = item && item.id; } - let win = targetWindow || this.topWindow; - let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win); - if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) { - return; - } - // The item should have an extension and the user shouldn't have confirmed // the change here, but just to be sure check that it is still controlled // and the user hasn't already confirmed the change. @@ -211,6 +203,7 @@ class ExtensionControlledPopup { return; } + let win = targetWindow || this.topWindow; // If the window closes while waiting for focus, this might reject/throw, // and we should stop trying to show the popup. try { diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index 7812b69d8146..f44f7508d24a 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -191,13 +191,8 @@ this.windows = class extends ExtensionAPI { args.appendElement(mkstr(createData.url)); } } else { - let url; - if (createData.incognito) { - url = PrivateBrowsingUtils.permanentPrivateBrowsing ? - HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing"; - } else { - url = HomePage.get().split("|", 1)[0]; - } + let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ? + "about:privatebrowsing" : HomePage.get().split("|", 1)[0]; args.appendElement(mkstr(url)); if (url.startsWith("about:") && diff --git a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js index c623327a7355..ef702f0b832d 100644 --- a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js +++ b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js @@ -422,127 +422,3 @@ add_task(async function test_doorhanger_new_window() { ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall"); }); - -add_task(async function test_overriding_home_page_incognito_not_allowed() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - chrome_settings_overrides: {"homepage": "home.html"}, - name: "extension", - }, - background() { - browser.test.sendMessage("url", browser.runtime.getURL("home.html")); - }, - files: {"home.html": "

1

"}, - useAddonManager: "temporary", - }); - - await extension.startup(); - let url = await extension.awaitMessage("url"); - - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url}); - let win = OpenBrowserWindow(); - await windowOpenedPromise; - let doc = win.document; - let description = doc.getElementById("extension-homepage-notification-description"); - let panel = doc.getElementById("extension-notification-panel"); - await promisePopupShown(panel); - - let popupnotification = description.closest("popupnotification"); - is(description.textContent, - "An extension, extension, changed what you see when you open your homepage and new windows.Learn more", - "The extension name is in the popup"); - is(popupnotification.hidden, false, "The expected popup notification is visible"); - - ok(win.gURLBar.value.endsWith("home.html"), "extension is in control"); - await BrowserTestUtils.closeWindow(win); - - // Verify a private window does not open the extension page. - windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - win.BrowserHome(); - await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); - - is(win.gURLBar.value, "", "home page not used in private window"); - await BrowserTestUtils.closeWindow(win); - - // Verify manually setting the pref to the extension page does not work. - Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url); - windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - win.BrowserHome(); - await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); - - is(win.gURLBar.value, "", "home page not used in private window"); - Services.prefs.clearUserPref(HOMEPAGE_URL_PREF); - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); - -add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - name: "extension", - }, - background() { - browser.test.sendMessage("url", browser.runtime.getURL("home.html")); - }, - files: {"home.html": "

1

"}, - useAddonManager: "temporary", - }); - - await extension.startup(); - let url = await extension.awaitMessage("url"); - - // Verify manually setting the pref to the extension page does not work. - Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url); - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - let win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - win.BrowserHome(); - await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); - - is(win.gURLBar.value, "", "home page not used in private window"); - Services.prefs.clearUserPref(HOMEPAGE_URL_PREF); - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); - -add_task(async function test_overriding_home_page_incognito_spanning() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - chrome_settings_overrides: {"homepage": "home.html"}, - name: "private extension", - applications: { - gecko: {id: "@spanning-home"}, - }, - }, - files: {"home.html": "

1

"}, - useAddonManager: "permanent", - incognitoOverride: "spanning", - }); - - await extension.startup(); - - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - let win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - let doc = win.document; - let panel = doc.getElementById("extension-notification-panel"); - win.BrowserHome(); - await promisePopupShown(panel); - - ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window"); - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); diff --git a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js index 105e3b78478d..a8ae9a53aa89 100644 --- a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js +++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js @@ -5,9 +5,6 @@ ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); -XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", - "@mozilla.org/browser/aboutnewtab-service;1", - "nsIAboutNewTabService"); const NEWTAB_URI_1 = "webext-newtab-1.html"; @@ -525,183 +522,3 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() { BrowserTestUtils.removeTab(tab); await extension.unload(); }); - -add_task(async function test_overriding_newtab_incognito_not_allowed() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let panel = getNewTabDoorhanger().closest("panel"); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - chrome_url_overrides: {"newtab": "newtab.html"}, - name: "extension", - applications: { - gecko: {id: "@not-allowed-newtab"}, - }, - }, - files: { - "newtab.html": ` - - - - - - - - - `, - - "newtab.js": function() { - window.onload = () => { - browser.test.sendMessage("from-newtab-page", window.location.href); - }; - }, - }, - useAddonManager: "permanent", - }); - - await extension.startup(); - - let popupShown = promisePopupShown(panel); - BrowserOpenTab(); - await popupShown; - - let url = await extension.awaitMessage("from-newtab-page"); - ok(url.endsWith("newtab.html"), - "Newtab url is overridden by the extension."); - - // This will show a confirmation doorhanger, make sure we don't leave it open. - let popupHidden = promisePopupHidden(panel); - panel.hidePopup(); - await popupHidden; - - BrowserTestUtils.removeTab(gBrowser.selectedTab); - - // Verify a private window does not open the extension page. We would - // get an extra notification that we don't listen for if it gets loaded. - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - let win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - - let newTabOpened = waitForNewTab(); - win.BrowserOpenTab(); - await newTabOpened; - - is(win.gURLBar.value, "", "newtab not used in private window"); - - // Verify setting the pref directly doesn't bypass permissions. - aboutNewTabService.newTabURL = url; - newTabOpened = waitForNewTab(); - win.BrowserOpenTab(); - await newTabOpened; - - is(win.gURLBar.value, "", "directly set newtab not used in private window"); - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); - -add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - name: "extension", - applications: { - gecko: {id: "@not-allowed-newtab"}, - }, - }, - background() { - browser.test.sendMessage("url", browser.runtime.getURL("newtab.html")); - }, - files: { - "newtab.html": ` - - - - - - - - `, - }, - useAddonManager: "permanent", - }); - - await extension.startup(); - let url = await extension.awaitMessage("url"); - - // Verify setting the pref directly doesn't bypass permissions. - aboutNewTabService.newTabURL = url; - - // Verify a private window does not open the extension page. We would - // get an extra notification that we don't listen for if it gets loaded. - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - let win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - - let newTabOpened = waitForNewTab(); - win.BrowserOpenTab(); - await newTabOpened; - - is(win.gURLBar.value, "", "directly set newtab not used in private window"); - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); - -add_task(async function test_overriding_newtab_incognito_spanning() { - await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); - - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - chrome_url_overrides: {"newtab": "newtab.html"}, - name: "extension", - applications: { - gecko: {id: "@spanning-newtab"}, - }, - }, - files: { - "newtab.html": ` - - - - - - - - - `, - - "newtab.js": function() { - window.onload = () => { - browser.test.sendMessage("from-newtab-page", window.location.href); - }; - }, - }, - useAddonManager: "permanent", - incognitoOverride: "spanning", - }); - - await extension.startup(); - - let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); - let win = OpenBrowserWindow({private: true}); - await windowOpenedPromise; - let panel = win.document.getElementById("extension-new-tab-notification").closest("panel"); - let popupShown = promisePopupShown(panel); - win.BrowserOpenTab(); - await popupShown; - - let url = await extension.awaitMessage("from-newtab-page"); - ok(url.endsWith("newtab.html"), - "Newtab url is overridden by the extension."); - - // This will show a confirmation doorhanger, make sure we don't leave it open. - let popupHidden = promisePopupHidden(panel); - panel.hidePopup(); - await popupHidden; - - await extension.unload(); - await BrowserTestUtils.closeWindow(win); -}); diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index 874159a13362..ecb08a61cd2f 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -207,7 +207,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData let args; if (!urlOrUrlList) { // Just pass in the defaultArgs directly. We'll use system principal on the other end. - args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)]; + args = [gBrowserContentHandler.defaultArgs]; } else { let pService = Cc["@mozilla.org/toolkit/profile-service;1"]. getService(Ci.nsIToolkitProfileService); @@ -522,7 +522,7 @@ nsBrowserContentHandler.prototype = { /* nsIBrowserHandler */ - getDefaultArgs(forcePrivate = false) { + get defaultArgs() { var prefb = Services.prefs; if (!gFirstWindow) { @@ -607,7 +607,7 @@ nsBrowserContentHandler.prototype = { try { var choice = prefb.getIntPref("browser.startup.page"); if (choice == 1 || choice == 3) - startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get(); + startPage = HomePage.get(); } catch (e) { Cu.reportError(e); } @@ -625,10 +625,6 @@ nsBrowserContentHandler.prototype = { return overridePage || startPage || "about:blank"; }, - get defaultArgs() { - return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing); - }, - mFeatures: null, getFeatures: function bch_features(cmdLine) { diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index ae671e9f9ca1..a3d092977e0a 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3299,7 +3299,7 @@ var SessionStoreInternal = { let tabbrowser = aWindow.gBrowser; let startupPref = this._prefBranch.getIntPref("startup.page"); if (startupPref == 1) - homePages = homePages.concat(HomePage.get(aWindow).split("|")); + homePages = homePages.concat(HomePage.get().split("|")); for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; diff --git a/browser/modules/HomePage.jsm b/browser/modules/HomePage.jsm index 2f7a3aa491fb..486209167e87 100644 --- a/browser/modules/HomePage.jsm +++ b/browser/modules/HomePage.jsm @@ -10,8 +10,6 @@ var EXPORTED_SYMBOLS = ["HomePage"]; const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); -ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); const kPrefName = "browser.startup.homepage"; @@ -45,11 +43,7 @@ function getHomepagePref(useDefault) { } let HomePage = { - get(aWindow) { - if (PrivateBrowsingUtils.permanentPrivateBrowsing || - (aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) { - return this.getPrivate(); - } + get() { return getHomepagePref(); }, @@ -57,24 +51,6 @@ let HomePage = { return getHomepagePref(true); }, - getPrivate() { - let homePages = getHomepagePref(); - if (!homePages.includes("moz-extension")) { - return homePages; - } - // Verify private access and build a new list. - let privateHomePages = homePages.split("|").filter(page => { - let url = new URL(page); - if (url.protocol !== "moz-extension:") { - return true; - } - let policy = WebExtensionPolicy.getByHostname(url.hostname); - return policy && policy.privateBrowsingAllowed; - }); - // Extensions may not be ready on startup, fallback to defaults. - return privateHomePages.join("|") || this.getDefault(); - }, - get overridden() { return Services.prefs.prefHasUserValue(kPrefName); }, From 7e50e9ddb5e96e8d530c20b22c95b3090ad025bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 14 Feb 2019 15:46:16 +0000 Subject: [PATCH 22/84] Bug 1525318 - Quantumbar: Make clicking one off buttons work. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D19776 --HG-- extra : moz-landing-system : lando --- browser/components/urlbar/UrlbarInput.jsm | 49 ++++++++++++++--------- browser/components/urlbar/UrlbarUtils.jsm | 35 ++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/browser/components/urlbar/UrlbarInput.jsm b/browser/components/urlbar/UrlbarInput.jsm index 99fca36a72c6..752cd264ee80 100644 --- a/browser/components/urlbar/UrlbarInput.jsm +++ b/browser/components/urlbar/UrlbarInput.jsm @@ -217,43 +217,54 @@ class UrlbarInput { return; } - // TODO: Hook up one-off button handling. // Determine whether to use the selected one-off search button. In // one-off search buttons parlance, "selected" means that the button // has been navigated to via the keyboard. So we want to use it if // the triggering event is not a mouse click -- i.e., it's a Return // key -- or if the one-off was mouse-clicked. - // let selectedOneOff = this.popup.oneOffSearchButtons.selectedButton; - // if (selectedOneOff && - // isMouseEvent && - // event.originalTarget != selectedOneOff) { - // selectedOneOff = null; - // } - // - // // Do the command of the selected one-off if it's not an engine. - // if (selectedOneOff && !selectedOneOff.engine) { - // selectedOneOff.doCommand(); - // return; - // } + let selectedOneOff; + if (this.view.isOpen) { + selectedOneOff = this.view.oneOffSearchButtons.selectedButton; + if (selectedOneOff && + isMouseEvent && + event.target != selectedOneOff) { + selectedOneOff = null; + } + // Do the command of the selected one-off if it's not an engine. + if (selectedOneOff && !selectedOneOff.engine) { + selectedOneOff.doCommand(); + return; + } + } - // Use the selected result if we have one; this should always be the case + // Use the selected result if we have one; this is usually the case // when the view is open. - let result = this.view.selectedResult; + let result = !selectedOneOff && this.view.selectedResult; if (result) { this.pickResult(event, result); return; } - // Use the current value if we don't have a UrlbarResult e.g. because the - // view is closed. - let url = this.value; + let url; + if (selectedOneOff) { + // If there's a selected one-off button then load a search using + // the button's engine. + [url, openParams.postData] = UrlbarUtils.getSearchQueryUrl( + selectedOneOff.engine, this._lastSearchString); + this._recordSearch(selectedOneOff.engine, event); + } else { + // Use the current value if we don't have a UrlbarResult e.g. because the + // view is closed. + url = this.value; + openParams.postData = null; + } + if (!url) { return; } let where = openWhere || this._whereToOpen(event); - openParams.postData = null; openParams.allowInheritPrincipal = false; // TODO: Work out how we get the user selection behavior, probably via passing diff --git a/browser/components/urlbar/UrlbarUtils.jsm b/browser/components/urlbar/UrlbarUtils.jsm index 7a3b06a78034..ec5fa408e8cc 100644 --- a/browser/components/urlbar/UrlbarUtils.jsm +++ b/browser/components/urlbar/UrlbarUtils.jsm @@ -256,7 +256,7 @@ var UrlbarUtils = { }; case UrlbarUtils.RESULT_TYPE.SEARCH: { const engine = Services.search.getEngineByName(result.payload.engine); - let [url, postData] = getSearchQueryUrl( + let [url, postData] = this.getSearchQueryUrl( engine, result.payload.suggestion || result.payload.query); return {url, postData}; } @@ -264,6 +264,22 @@ var UrlbarUtils = { return {url: null, postData: null}; }, + /** + * Get the url to load for the search query. + * + * @param {nsISearchEngine} engine + * The engine to generate the query for. + * @param {string} query + * The query string to search for. + * @returns {array} + * Returns an array containing the query url (string) and the + * post data (object). + */ + getSearchQueryUrl(engine, query) { + let submission = engine.getSubmission(query, null, "keyword"); + return [submission.uri.spec, submission.postData]; + }, + /** * Tries to initiate a speculative connection to a given url. * @param {nsISearchEngine|nsIURI|URL|string} urlOrEngine entity to initiate @@ -325,23 +341,6 @@ var UrlbarUtils = { }, }; -/** - * Get the url to load for the search query and records in telemetry that it - * is being loaded. - * - * @param {nsISearchEngine} engine - * The engine to generate the query for. - * @param {string} query - * The query string to search for. - * @returns {array} - * Returns an array containing the query url (string) and the - * post data (object). - */ -function getSearchQueryUrl(engine, query) { - let submission = engine.getSubmission(query, null, "keyword"); - return [submission.uri.spec, submission.postData]; -} - /** * UrlbarQueryContext defines a user's autocomplete input from within the urlbar. * It supplements it with details of how the search results should be obtained From 7d559ef8c3b8c5fb321d99d3d2ffc46ef0e1be1d Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 14 Feb 2019 15:03:44 +0000 Subject: [PATCH 23/84] Bug 1527860 - Remove ENABLE_BIGINT #ifdef r=jandem,froydnj Differential Revision: https://phabricator.services.mozilla.com/D19766 --HG-- extra : moz-landing-system : lando --- dom/bindings/BindingUtils.h | 2 - js/moz.configure | 13 ------ js/public/Class.h | 2 - js/public/CompileOptions.h | 2 - js/public/GCPolicyAPI.h | 2 +- js/public/MemoryMetrics.h | 8 ++-- js/public/ProtoKey.h | 7 ++- js/public/TraceKind.h | 4 +- js/public/TracingAPI.h | 4 -- js/public/TypeDecls.h | 16 ------- js/public/UbiNode.h | 2 - js/public/Value.h | 32 -------------- js/src/NamespaceImports.h | 10 ----- js/src/builtin/Array.cpp | 2 +- js/src/builtin/Boolean.cpp | 6 +-- js/src/builtin/JSON.cpp | 13 ++---- js/src/builtin/MapObject.cpp | 6 +-- js/src/builtin/Object.cpp | 4 +- js/src/builtin/ReflectParse.cpp | 8 +--- js/src/frontend/BytecodeEmitter.cpp | 8 ---- js/src/frontend/BytecodeEmitter.h | 2 - js/src/frontend/FoldConstants.cpp | 14 +----- js/src/frontend/FullParseHandler.h | 2 - js/src/frontend/NameFunctions.cpp | 2 - js/src/frontend/ParseNode.cpp | 8 ---- js/src/frontend/ParseNode.h | 30 +++---------- js/src/frontend/Parser.cpp | 6 --- js/src/frontend/Parser.h | 8 ---- js/src/frontend/SyntaxParseHandler.h | 2 - js/src/frontend/TokenKind.h | 2 +- js/src/frontend/TokenStream.cpp | 27 ++---------- js/src/frontend/TokenStream.h | 4 -- js/src/fuzz-tests/tests.cpp | 2 - js/src/gc/AllocKind.h | 2 +- js/src/gc/AtomMarking.cpp | 12 +++--- js/src/gc/DeletePolicy.h | 2 - js/src/gc/GC.cpp | 13 +----- js/src/gc/Marking-inl.h | 7 +-- js/src/gc/Marking.cpp | 18 ++------ js/src/gc/RootMarking.cpp | 2 - js/src/gc/Tracer.cpp | 6 +-- js/src/gdb/lib-for-tests/prologue.py | 7 --- js/src/gdb/mozilla/jsval.py | 12 +----- js/src/gdb/tests/test-jsval.cpp | 8 +--- js/src/gdb/tests/test-jsval.py | 3 +- js/src/jit/BaselineBailouts.cpp | 2 - js/src/jit/BaselineCompiler.cpp | 2 - js/src/jit/BaselineCompiler.h | 2 +- js/src/jit/BaselineIC.cpp | 4 -- js/src/jit/BaselineInspector.cpp | 2 - js/src/jit/CacheIR.cpp | 12 ++---- js/src/jit/CacheIR.h | 8 +--- js/src/jit/CacheIRCompiler.cpp | 4 -- js/src/jit/CacheIRCompiler.h | 2 +- js/src/jit/CodeGenerator.cpp | 24 ++--------- js/src/jit/IonAnalysis.cpp | 4 +- js/src/jit/IonBuilder.cpp | 24 ++--------- js/src/jit/IonTypes.h | 14 +----- js/src/jit/JitFrames.cpp | 8 ---- js/src/jit/LIR.h | 2 - js/src/jit/Lowering.cpp | 8 ---- js/src/jit/MCallOptimize.cpp | 14 +++--- js/src/jit/MIR.cpp | 43 ++++--------------- js/src/jit/MIR.h | 23 +++------- js/src/jit/MacroAssembler.cpp | 9 +--- js/src/jit/MacroAssembler.h | 8 ---- js/src/jit/Snapshots.cpp | 2 - js/src/jit/TypePolicy.cpp | 8 +--- js/src/jit/VMFunctions.cpp | 26 ++++------- js/src/jit/VMFunctions.h | 4 -- js/src/jit/arm/MacroAssembler-arm-inl.h | 2 - js/src/jit/arm/MacroAssembler-arm.cpp | 10 ----- js/src/jit/arm/MacroAssembler-arm.h | 12 ------ js/src/jit/arm64/CodeGenerator-arm64.cpp | 4 -- js/src/jit/arm64/MacroAssembler-arm64-inl.h | 2 - js/src/jit/arm64/MacroAssembler-arm64.h | 10 ----- js/src/jit/mips32/MacroAssembler-mips32-inl.h | 2 - js/src/jit/mips64/CodeGenerator-mips64.cpp | 4 -- js/src/jit/mips64/MacroAssembler-mips64-inl.h | 2 - js/src/jit/mips64/MacroAssembler-mips64.cpp | 2 - js/src/jit/mips64/MacroAssembler-mips64.h | 2 - js/src/jit/none/MacroAssembler-none.h | 4 -- js/src/jit/shared/CodeGenerator-shared.cpp | 2 - js/src/jit/shared/Lowering-shared-inl.h | 5 +-- js/src/jit/x64/CodeGenerator-x64.cpp | 4 -- js/src/jit/x64/MacroAssembler-x64.h | 12 ------ .../MacroAssembler-x86-shared-inl.h | 2 - js/src/jit/x86/MacroAssembler-x86.h | 10 ----- js/src/jsapi-tests/testJitRValueAlloc.cpp | 4 +- js/src/jsapi-tests/tests.cpp | 2 - js/src/jsapi.cpp | 4 -- js/src/jsapi.h | 6 --- js/src/jsexn.cpp | 8 +--- js/src/jsfriendapi.cpp | 6 +-- js/src/jsnum.cpp | 16 +------ js/src/jsnum.h | 2 - js/src/jspubtd.h | 2 - js/src/moz.build | 8 +--- js/src/shell/js.cpp | 24 ++++------- js/src/util/StringBuffer.cpp | 2 - js/src/vm/BytecodeUtil.cpp | 3 -- js/src/vm/BytecodeUtil.h | 4 +- js/src/vm/Compartment-inl.h | 2 - js/src/vm/Compartment.cpp | 2 - js/src/vm/Compartment.h | 2 - js/src/vm/EqualityOperations.cpp | 8 +--- js/src/vm/GlobalObject.cpp | 6 +-- js/src/vm/Initialization.cpp | 4 +- js/src/vm/Interpreter-inl.h | 20 --------- js/src/vm/Interpreter.cpp | 23 +--------- js/src/vm/JSAtom.cpp | 2 - js/src/vm/JSContext-inl.h | 11 +---- js/src/vm/JSObject.cpp | 12 +----- js/src/vm/JSScript.cpp | 20 ++------- js/src/vm/MemoryMetrics.cpp | 6 +-- js/src/vm/Opcodes.h | 3 +- js/src/vm/StringType.cpp | 8 +--- js/src/vm/StructuredClone.cpp | 32 ++------------ js/src/vm/TypeInference-inl.h | 4 -- js/src/vm/TypeInference.cpp | 8 ---- js/src/vm/TypeSet.h | 14 +----- js/src/vm/TypedArrayObject-inl.h | 2 +- js/src/vm/UbiNode.cpp | 18 ++------ js/xpconnect/src/XPCJSContext.cpp | 6 --- modules/libpref/init/StaticPrefList.h | 2 - 125 files changed, 142 insertions(+), 866 deletions(-) diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index a62a74f61af2..0eabf0ef4279 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -967,7 +967,6 @@ MOZ_ALWAYS_INLINE bool MaybeWrapValue(JSContext* cx, if (rval.isObject()) { return MaybeWrapObjectValue(cx, rval); } -#ifdef ENABLE_BIGINT // This could be optimized by checking the zone first, similar to // the way strings are handled. At present, this is used primarily // for structured cloning, so avoiding the overhead of JS_WrapValue @@ -975,7 +974,6 @@ MOZ_ALWAYS_INLINE bool MaybeWrapValue(JSContext* cx, if (rval.isBigInt()) { return JS_WrapValue(cx, rval); } -#endif MOZ_ASSERT(rval.isSymbol()); JS_MarkCrossZoneId(cx, SYMBOL_TO_JSID(rval.toSymbol())); } diff --git a/js/moz.configure b/js/moz.configure index cd26f93e8d96..8c799253c19a 100644 --- a/js/moz.configure +++ b/js/moz.configure @@ -107,19 +107,6 @@ def disable_export_js(value): die('Setting %s is deprecated, use %s instead.', value.format('DISABLE_EXPORT_JS'), suggestion) -# Experimental BigInt support -# ======================================================= -js_option('--disable-bigint', - help='{Enable|Disable} BigInt') - -@depends('--disable-bigint') -def enable_bigint(value): - if value: - return True - -set_config('ENABLE_BIGINT', enable_bigint) -set_define('ENABLE_BIGINT', enable_bigint) - # JIT support # ======================================================= @depends(target) diff --git a/js/public/Class.h b/js/public/Class.h index 9da1b863a735..c04694cee39c 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -1038,9 +1038,7 @@ enum class ESClass { SetIterator, Arguments, Error, -#ifdef ENABLE_BIGINT BigInt, -#endif /** None of the above. */ Other diff --git a/js/public/CompileOptions.h b/js/public/CompileOptions.h index 7d8e462cdba4..8fa95a201215 100644 --- a/js/public/CompileOptions.h +++ b/js/public/CompileOptions.h @@ -116,9 +116,7 @@ class JS_PUBLIC_API TransitiveCompileOptions { bool allowHTMLComments = true; bool isProbablySystemCode = false; bool hideScriptFromDebugger = false; -#ifdef ENABLE_BIGINT bool bigIntEnabledOption = false; -#endif /** * |introductionType| is a statically allocated C string: one of "eval", diff --git a/js/public/GCPolicyAPI.h b/js/public/GCPolicyAPI.h index 7d2185a96f23..9eb1644e0fc3 100644 --- a/js/public/GCPolicyAPI.h +++ b/js/public/GCPolicyAPI.h @@ -47,7 +47,7 @@ // Expand the given macro D for each public GC pointer. #define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \ D(JS::Symbol*) \ - IF_BIGINT(D(JS::BigInt*), ) \ + D(JS::BigInt*) \ D(JSAtom*) \ D(JSFunction*) \ D(JSObject*) \ diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index 4236439a5b40..69d27259743e 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -569,7 +569,7 @@ struct UnusedGCThingSizes { MACRO(Other, GCHeapUnused, objectGroup) \ MACRO(Other, GCHeapUnused, string) \ MACRO(Other, GCHeapUnused, symbol) \ - IF_BIGINT(MACRO(Other, GCHeapUnused, bigInt), ) \ + MACRO(Other, GCHeapUnused, bigInt) \ MACRO(Other, GCHeapUnused, jitcode) \ MACRO(Other, GCHeapUnused, scope) \ MACRO(Other, GCHeapUnused, regExpShared) @@ -590,11 +590,9 @@ struct UnusedGCThingSizes { case JS::TraceKind::Symbol: symbol += n; break; -#ifdef ENABLE_BIGINT case JS::TraceKind::BigInt: bigInt += n; break; -#endif case JS::TraceKind::Script: script += n; break; @@ -648,8 +646,8 @@ struct UnusedGCThingSizes { struct ZoneStats { #define FOR_EACH_SIZE(MACRO) \ MACRO(Other, GCHeapUsed, symbolsGCHeap) \ - IF_BIGINT(MACRO(Other, GCHeapUsed, bigIntsGCHeap), ) \ - IF_BIGINT(MACRO(Other, MallocHeap, bigIntsMallocHeap), ) \ + MACRO(Other, GCHeapUsed, bigIntsGCHeap) \ + MACRO(Other, MallocHeap, bigIntsMallocHeap) \ MACRO(Other, GCHeapAdmin, gcHeapArenaAdmin) \ MACRO(Other, GCHeapUsed, lazyScriptsGCHeap) \ MACRO(Other, MallocHeap, lazyScriptsMallocHeap) \ diff --git a/js/public/ProtoKey.h b/js/public/ProtoKey.h index ddce5f0add8e..a4427b15e215 100644 --- a/js/public/ProtoKey.h +++ b/js/public/ProtoKey.h @@ -55,7 +55,7 @@ #endif #define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_BDATA, \ - REAL_IF_SAB, REAL_IF_BIGINT) \ + REAL_IF_SAB) \ IMAGINARY(Null, InitNullClass, dummy) \ REAL(Object, InitViaClassSpec, OCLASP(Plain)) \ REAL(Function, InitViaClassSpec, &JSFunction::class_) \ @@ -90,7 +90,7 @@ REAL(Float32Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32)) \ REAL(Float64Array, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64)) \ REAL(Uint8ClampedArray, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \ - REAL_IF_BIGINT(BigInt, InitViaClassSpec, OCLASP(BigInt)) \ + REAL(BigInt, InitViaClassSpec, OCLASP(BigInt)) \ REAL(Proxy, InitProxyClass, &js::ProxyClass) \ REAL(WeakMap, InitViaClassSpec, OCLASP(WeakMap)) \ REAL(Map, InitViaClassSpec, OCLASP(Map)) \ @@ -131,8 +131,7 @@ #define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \ JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \ - IF_BDATA(REAL, IMAGINARY), IF_SAB(REAL, IMAGINARY), \ - IF_BIGINT(REAL, IMAGINARY)) + IF_BDATA(REAL, IMAGINARY), IF_SAB(REAL, IMAGINARY)) #define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO) diff --git a/js/public/TraceKind.h b/js/public/TraceKind.h index b67dbb17584f..574f6b1b3ab8 100644 --- a/js/public/TraceKind.h +++ b/js/public/TraceKind.h @@ -62,9 +62,7 @@ enum class TraceKind { LazyScript = 0x2F, Scope = 0x3F, RegExpShared = 0x4F, -#ifdef ENABLE_BIGINT BigInt = 0x5F -#endif }; const static uintptr_t OutOfLineTraceKindMask = 0x07; @@ -113,7 +111,7 @@ struct MapTypeToTraceKind { D(Shape, js::Shape, true) \ D(String, JSString, false) \ D(Symbol, JS::Symbol, false) \ - IF_BIGINT(D(BigInt, JS::BigInt, false), ) \ + D(BigInt, JS::BigInt, false) \ D(RegExpShared, js::RegExpShared, true) // Map from all public types to their trace kind. diff --git a/js/public/TracingAPI.h b/js/public/TracingAPI.h index 633b4aafdb22..07942bb4e13f 100644 --- a/js/public/TracingAPI.h +++ b/js/public/TracingAPI.h @@ -159,9 +159,7 @@ class JS_PUBLIC_API CallbackTracer : public JSTracer { virtual void onSymbolEdge(JS::Symbol** symp) { onChild(JS::GCCellPtr(*symp)); } -#ifdef ENABLE_BIGINT virtual void onBigIntEdge(JS::BigInt** bip) { onChild(JS::GCCellPtr(*bip)); } -#endif virtual void onScriptEdge(JSScript** scriptp) { onChild(JS::GCCellPtr(*scriptp)); } @@ -259,9 +257,7 @@ class JS_PUBLIC_API CallbackTracer : public JSTracer { void dispatchToOnEdge(JSObject** objp) { onObjectEdge(objp); } void dispatchToOnEdge(JSString** strp) { onStringEdge(strp); } void dispatchToOnEdge(JS::Symbol** symp) { onSymbolEdge(symp); } -#ifdef ENABLE_BIGINT void dispatchToOnEdge(JS::BigInt** bip) { onBigIntEdge(bip); } -#endif void dispatchToOnEdge(JSScript** scriptp) { onScriptEdge(scriptp); } void dispatchToOnEdge(js::Shape** shapep) { onShapeEdge(shapep); } void dispatchToOnEdge(js::ObjectGroup** groupp) { onObjectGroupEdge(groupp); } diff --git a/js/public/TypeDecls.h b/js/public/TypeDecls.h index 4370b4b92f0e..5fae7562d6f6 100644 --- a/js/public/TypeDecls.h +++ b/js/public/TypeDecls.h @@ -40,9 +40,7 @@ struct PropertyKey; typedef unsigned char Latin1Char; class Symbol; -#ifdef ENABLE_BIGINT class BigInt; -#endif union Value; class Compartment; @@ -65,9 +63,7 @@ typedef Handle HandleObject; typedef Handle HandleScript; typedef Handle HandleString; typedef Handle HandleSymbol; -#ifdef ENABLE_BIGINT typedef Handle HandleBigInt; -#endif typedef Handle HandleValue; typedef MutableHandle MutableHandleFunction; @@ -76,9 +72,7 @@ typedef MutableHandle MutableHandleObject; typedef MutableHandle MutableHandleScript; typedef MutableHandle MutableHandleString; typedef MutableHandle MutableHandleSymbol; -#ifdef ENABLE_BIGINT typedef MutableHandle MutableHandleBigInt; -#endif typedef MutableHandle MutableHandleValue; typedef Rooted RootedObject; @@ -86,9 +80,7 @@ typedef Rooted RootedFunction; typedef Rooted RootedScript; typedef Rooted RootedString; typedef Rooted RootedSymbol; -#ifdef ENABLE_BIGINT typedef Rooted RootedBigInt; -#endif typedef Rooted RootedId; typedef Rooted RootedValue; @@ -98,19 +90,11 @@ typedef PersistentRooted PersistentRootedObject; typedef PersistentRooted PersistentRootedScript; typedef PersistentRooted PersistentRootedString; typedef PersistentRooted PersistentRootedSymbol; -#ifdef ENABLE_BIGINT typedef PersistentRooted PersistentRootedBigInt; -#endif typedef PersistentRooted PersistentRootedValue; } // namespace JS using jsid = JS::PropertyKey; -#ifdef ENABLE_BIGINT -# define IF_BIGINT(x, y) x -#else -# define IF_BIGINT(x, y) y -#endif - #endif /* js_TypeDecls_h */ diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index 417839c5994e..8758f2f6bd9b 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -1080,7 +1080,6 @@ class JS_PUBLIC_API Concrete : TracerConcrete { static const char16_t concreteTypeName[]; }; -#ifdef ENABLE_BIGINT template <> class JS_PUBLIC_API Concrete : TracerConcrete { protected: @@ -1096,7 +1095,6 @@ class JS_PUBLIC_API Concrete : TracerConcrete { const char16_t* typeName() const override { return concreteTypeName; } static const char16_t concreteTypeName[]; }; -#endif template <> class JS_PUBLIC_API Concrete : TracerConcreteWithRealm { diff --git a/js/public/Value.h b/js/public/Value.h index c58d3b206965..bdd42a5331e7 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -61,9 +61,7 @@ enum JSValueType : uint8_t { JSVAL_TYPE_STRING = 0x06, JSVAL_TYPE_SYMBOL = 0x07, JSVAL_TYPE_PRIVATE_GCTHING = 0x08, -#ifdef ENABLE_BIGINT JSVAL_TYPE_BIGINT = 0x09, -#endif JSVAL_TYPE_OBJECT = 0x0c, // These never appear in a jsval; they are only provided as an out-of-band @@ -87,9 +85,7 @@ JS_ENUM_HEADER(JSValueTag, uint32_t){ JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING, JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING, -# ifdef ENABLE_BIGINT JSVAL_TAG_BIGINT = JSVAL_TAG_CLEAR | JSVAL_TYPE_BIGINT, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT} JS_ENUM_FOOTER(JSValueTag); @@ -109,9 +105,7 @@ JS_ENUM_HEADER(JSValueTag, uint32_t){ JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING, -# ifdef ENABLE_BIGINT JSVAL_TAG_BIGINT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BIGINT, -# endif JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT} JS_ENUM_FOOTER(JSValueTag); @@ -132,9 +126,7 @@ enum JSValueShiftedTag : uint64_t { JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT), JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT), -# ifdef ENABLE_BIGINT JSVAL_SHIFTED_TAG_BIGINT = (((uint64_t)JSVAL_TAG_BIGINT) << JSVAL_TAG_SHIFT), -# endif JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) }; @@ -357,9 +349,7 @@ union alignas(8) Value { uint32_t boo_; // Don't use |bool| -- it must be four bytes. JSString* str_; JS::Symbol* sym_; -# ifdef ENABLE_BIGINT JS::BigInt* bi_; -# endif JSObject* obj_; js::gc::Cell* cell_; void* ptr_; @@ -458,12 +448,10 @@ union alignas(8) Value { asBits_ = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym)); } -#ifdef ENABLE_BIGINT void setBigInt(JS::BigInt* bi) { MOZ_ASSERT(js::gc::IsCellPointerValid(bi)); asBits_ = bitsFromTagAndPayload(JSVAL_TAG_BIGINT, PayloadType(bi)); } -#endif void setObject(JSObject& obj) { MOZ_ASSERT(js::gc::IsCellPointerValid(&obj)); @@ -611,9 +599,7 @@ union alignas(8) Value { bool isSymbol() const { return toTag() == JSVAL_TAG_SYMBOL; } -#ifdef ENABLE_BIGINT bool isBigInt() const { return toTag() == JSVAL_TAG_BIGINT; } -#endif bool isObject() const { #if defined(JS_NUNBOX32) @@ -671,11 +657,9 @@ union alignas(8) Value { if (MOZ_UNLIKELY(isPrivateGCThing())) { return JS::GCThingTraceKind(toGCThing()); } -#ifdef ENABLE_BIGINT if (MOZ_UNLIKELY(isBigInt())) { return JS::TraceKind::BigInt; } -#endif return JS::TraceKind(toTag() & 0x03); } @@ -736,7 +720,6 @@ union alignas(8) Value { #endif } -#ifdef ENABLE_BIGINT JS::BigInt* toBigInt() const { MOZ_ASSERT(isBigInt()); # if defined(JS_NUNBOX32) @@ -745,7 +728,6 @@ union alignas(8) Value { return reinterpret_cast(asBits_ ^ JSVAL_SHIFTED_TAG_BIGINT); # endif } -#endif JSObject& toObject() const { MOZ_ASSERT(isObject()); @@ -861,11 +843,9 @@ union alignas(8) Value { MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Symbol, "Private GC thing Values must not be symbols. Make a " "SymbolValue instead."); -#ifdef ENABLE_BIGINT MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::BigInt, "Private GC thing Values must not be BigInts. Make a " "BigIntValue instead."); -#endif MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object, "Private GC thing Values must not be objects. Make an " "ObjectValue instead."); @@ -969,13 +949,11 @@ static inline Value SymbolValue(JS::Symbol* sym) { return v; } -#ifdef ENABLE_BIGINT static inline Value BigIntValue(JS::BigInt* bi) { Value v; v.setBigInt(bi); return v; } -#endif static inline Value BooleanValue(bool boo) { Value v; @@ -1178,9 +1156,7 @@ class WrappedPtrOperations { bool isDouble() const { return value().isDouble(); } bool isString() const { return value().isString(); } bool isSymbol() const { return value().isSymbol(); } -#ifdef ENABLE_BIGINT bool isBigInt() const { return value().isBigInt(); } -#endif bool isObject() const { return value().isObject(); } bool isMagic() const { return value().isMagic(); } bool isMagic(JSWhyMagic why) const { return value().isMagic(why); } @@ -1196,9 +1172,7 @@ class WrappedPtrOperations { double toDouble() const { return value().toDouble(); } JSString* toString() const { return value().toString(); } JS::Symbol* toSymbol() const { return value().toSymbol(); } -#ifdef ENABLE_BIGINT JS::BigInt* toBigInt() const { return value().toBigInt(); } -#endif JSObject& toObject() const { return value().toObject(); } JSObject* toObjectOrNull() const { return value().toObjectOrNull(); } gc::Cell* toGCThing() const { return value().toGCThing(); } @@ -1238,9 +1212,7 @@ class MutableWrappedPtrOperations bool setNumber(double d) { return value().setNumber(d); } void setString(JSString* str) { this->value().setString(str); } void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); } -#ifdef ENABLE_BIGINT void setBigInt(JS::BigInt* bi) { this->value().setBigInt(bi); } -#endif void setObject(JSObject& obj) { this->value().setObject(obj); } void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); } void setPrivate(void* ptr) { this->value().setPrivate(ptr); } @@ -1271,9 +1243,7 @@ class HeapBase void setMagic(JSWhyMagic why) { setBarriered(JS::MagicValue(why)); } void setString(JSString* str) { setBarriered(JS::StringValue(str)); } void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); } -#ifdef ENABLE_BIGINT void setBigInt(JS::BigInt* bi) { setBarriered(JS::BigIntValue(bi)); } -#endif void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); } void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); @@ -1329,13 +1299,11 @@ auto MapGCThingTyped(const JS::Value& val, F&& f) { MOZ_ASSERT(gc::IsCellPointerValid(sym)); return mozilla::Some(f(sym)); } -#ifdef ENABLE_BIGINT if (val.isBigInt()) { JS::BigInt* bi = val.toBigInt(); MOZ_ASSERT(gc::IsCellPointerValid(bi)); return mozilla::Some(f(bi)); } -#endif if (MOZ_UNLIKELY(val.isPrivateGCThing())) { MOZ_ASSERT(gc::IsCellPointerValid(val.toGCThing())); return mozilla::Some(MapGCThingTyped(val.toGCCellPtr(), std::move(f))); diff --git a/js/src/NamespaceImports.h b/js/src/NamespaceImports.h index e99018d316c4..4a6c3a98b09f 100644 --- a/js/src/NamespaceImports.h +++ b/js/src/NamespaceImports.h @@ -110,9 +110,7 @@ using JS::RootedObject; using JS::RootedScript; using JS::RootedString; using JS::RootedSymbol; -#ifdef ENABLE_BIGINT using JS::RootedBigInt; -#endif using JS::RootedValue; using JS::PersistentRooted; @@ -122,9 +120,7 @@ using JS::PersistentRootedObject; using JS::PersistentRootedScript; using JS::PersistentRootedString; using JS::PersistentRootedSymbol; -#ifdef ENABLE_BIGINT using JS::PersistentRootedBigInt; -#endif using JS::PersistentRootedValue; using JS::Handle; @@ -134,9 +130,7 @@ using JS::HandleObject; using JS::HandleScript; using JS::HandleString; using JS::HandleSymbol; -#ifdef ENABLE_BIGINT using JS::HandleBigInt; -#endif using JS::HandleValue; using JS::MutableHandle; @@ -146,9 +140,7 @@ using JS::MutableHandleObject; using JS::MutableHandleScript; using JS::MutableHandleString; using JS::MutableHandleSymbol; -#ifdef ENABLE_BIGINT using JS::MutableHandleBigInt; -#endif using JS::MutableHandleValue; using JS::FalseHandleValue; @@ -168,9 +160,7 @@ using JS::Zone; using JS::Symbol; using JS::SymbolCode; -#ifdef ENABLE_BIGINT using JS::BigInt; -#endif } /* namespace js */ diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp index 41584b395f21..9895e3b3610d 100644 --- a/js/src/builtin/Array.cpp +++ b/js/src/builtin/Array.cpp @@ -1312,7 +1312,7 @@ static bool ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, * with those as well. */ break; - } else if (IF_BIGINT(elem.isBigInt(), false)) { + } else if (elem.isBigInt()) { // ToString(bigint) doesn't access bigint.toString or // anything like that, so it can't mutate the array we're // walking through, so it *could* be handled here. We don't diff --git a/js/src/builtin/Boolean.cpp b/js/src/builtin/Boolean.cpp index 4c53476b8def..443734fe912b 100644 --- a/js/src/builtin/Boolean.cpp +++ b/js/src/builtin/Boolean.cpp @@ -16,9 +16,7 @@ #include "jit/InlinableNatives.h" #include "js/PropertySpec.h" #include "util/StringBuffer.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/GlobalObject.h" #include "vm/JSAtom.h" #include "vm/JSContext.h" @@ -162,11 +160,9 @@ JS_PUBLIC_API bool js::ToBooleanSlow(HandleValue v) { if (v.isString()) { return v.toString()->length() != 0; } -#ifdef ENABLE_BIGINT if (v.isBigInt()) { return !v.toBigInt()->isZero(); } -#endif MOZ_ASSERT(v.isObject()); return !EmulatesUndefined(&v.toObject()); diff --git a/js/src/builtin/JSON.cpp b/js/src/builtin/JSON.cpp index 9abc984b9eca..1d5ada8d1401 100644 --- a/js/src/builtin/JSON.cpp +++ b/js/src/builtin/JSON.cpp @@ -16,9 +16,7 @@ #include "jsutil.h" #include "builtin/Array.h" -#ifdef ENABLE_BIGINT -# include "builtin/BigInt.h" -#endif +#include "builtin/BigInt.h" #include "builtin/String.h" #include "js/PropertySpec.h" #include "js/StableStringChars.h" @@ -291,7 +289,7 @@ static bool PreprocessValue(JSContext* cx, HandleObject holder, KeyType key, // Step 2. Modified by BigInt spec 6.1 to check for a toJSON method on the // BigInt prototype when the value is a BigInt. - if (vp.isObject() || IF_BIGINT(vp.isBigInt(), false)) { + if (vp.isObject() || vp.isBigInt()) { RootedValue toJSON(cx); RootedObject obj(cx, JS::ToObject(cx, vp)); if (!obj) { @@ -359,14 +357,11 @@ static bool PreprocessValue(JSContext* cx, HandleObject holder, KeyType key, if (!Unbox(cx, obj, vp)) { return false; } - } -#ifdef ENABLE_BIGINT - else if (cls == ESClass::BigInt) { + } else if (cls == ESClass::BigInt) { if (!Unbox(cx, obj, vp)) { return false; } } -#endif } return true; @@ -681,14 +676,12 @@ static bool Str(JSContext* cx, const Value& v, StringifyContext* scx) { return NumberValueToStringBuffer(cx, v, scx->sb); } -#ifdef ENABLE_BIGINT /* Step 10 in the BigInt proposal. */ if (v.isBigInt()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BIGINT_NOT_SERIALIZABLE); return false; } -#endif /* Step 10. */ MOZ_ASSERT(v.isObject()); diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index bf2f57ce3bb6..d764987f5e26 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -59,7 +59,7 @@ bool HashableValue::setValue(JSContext* cx, HandleValue v) { MOZ_ASSERT(value.isUndefined() || value.isNull() || value.isBoolean() || value.isNumber() || value.isString() || value.isSymbol() || - value.isObject() || IF_BIGINT(value.isBigInt(), false)); + value.isObject() || value.isBigInt()); return true; } @@ -80,11 +80,9 @@ static HashNumber HashValue(const Value& v, if (v.isSymbol()) { return v.toSymbol()->hash(); } -#ifdef ENABLE_BIGINT if (v.isBigInt()) { return v.toBigInt()->hash(); } -#endif if (v.isObject()) { return hcs.scramble(v.asRawBits()); } @@ -101,7 +99,6 @@ bool HashableValue::operator==(const HashableValue& other) const { // Two HashableValues are equal if they have equal bits. bool b = (value.asRawBits() == other.value.asRawBits()); -#ifdef ENABLE_BIGINT // BigInt values are considered equal if they represent the same // integer. This test should use a comparison function that doesn't // require a JSContext once one is defined in the BigInt class. @@ -111,7 +108,6 @@ bool HashableValue::operator==(const HashableValue& other) const { RootedValue otherRoot(cx, other.value); SameValue(cx, valueRoot, otherRoot, &b); } -#endif #ifdef DEBUG bool same; diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 3929df7a3d68..5f1f1ce37751 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -8,9 +8,7 @@ #include "mozilla/MaybeOneOf.h" -#ifdef ENABLE_BIGINT -# include "builtin/BigInt.h" -#endif +#include "builtin/BigInt.h" #include "builtin/Eval.h" #include "builtin/SelfHostingDefines.h" #include "builtin/String.h" diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index c1277e17ac71..7ad0a5eb7b0e 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -21,9 +21,7 @@ #include "frontend/Parser.h" #include "js/CharacterEncoding.h" #include "js/StableStringChars.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/JSAtom.h" #include "vm/JSObject.h" #include "vm/RegExpObject.h" @@ -2950,9 +2948,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) { case ParseNodeKind::StringExpr: case ParseNodeKind::RegExpExpr: case ParseNodeKind::NumberExpr: -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: -#endif case ParseNodeKind::TrueExpr: case ParseNodeKind::FalseExpr: case ParseNodeKind::NullExpr: @@ -3125,14 +3121,12 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) { val.setNumber(pn->as().value()); break; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: { BigInt* x = pn->as().box()->value(); cx->check(x); val.setBigInt(x); break; } -#endif case ParseNodeKind::NullExpr: val.setNull(); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 99c2865ac808..1cd5e8b0b996 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1061,12 +1061,10 @@ restart: *answer = false; return true; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: MOZ_ASSERT(pn->is()); *answer = false; return true; -#endif // |this| can throw in derived class constructors, including nested arrow // functions or eval. @@ -4394,11 +4392,9 @@ bool ParseNode::getConstantValue(JSContext* cx, case ParseNodeKind::NumberExpr: vp.setNumber(as().value()); return true; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: vp.setBigInt(as().box()->value()); return true; -#endif case ParseNodeKind::TemplateStringExpr: case ParseNodeKind::StringExpr: vp.setString(as().atom()); @@ -4977,14 +4973,12 @@ bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) { return true; } -#ifdef ENABLE_BIGINT bool BytecodeEmitter::emitBigIntOp(BigInt* bigint) { if (!numberList.append(BigIntValue(bigint))) { return false; } return emitIndex32(JSOP_BIGINT, numberList.length() - 1); } -#endif bool BytecodeEmitter::emitIterator() { // Convert iterable to iterator. @@ -9244,13 +9238,11 @@ bool BytecodeEmitter::emitTree( } break; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: if (!emitBigIntOp(pn->as().box()->value())) { return false; } break; -#endif case ParseNodeKind::RegExpExpr: if (!emitRegExp(objectList.add(pn->as().objbox()))) { diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index ebd5ef3f6b8b..d0a6f5b5c5f9 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -540,9 +540,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter { MOZ_MUST_USE bool emitNumberOp(double dval); -#ifdef ENABLE_BIGINT MOZ_MUST_USE bool emitBigIntOp(BigInt* bigint); -#endif MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn); MOZ_MUST_USE bool emitGetFunctionThis(NameNode* thisName); diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 501420c4eb4a..04e62f9f03b8 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -398,9 +398,7 @@ restart: case ParseNodeKind::ThisExpr: case ParseNodeKind::Elision: case ParseNodeKind::NumberExpr: -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: -#endif case ParseNodeKind::NewExpr: case ParseNodeKind::Generator: case ParseNodeKind::ParamsBody: @@ -482,9 +480,7 @@ static bool IsEffectless(ParseNode* node) { node->isKind(ParseNodeKind::StringExpr) || node->isKind(ParseNodeKind::TemplateStringExpr) || node->isKind(ParseNodeKind::NumberExpr) || -#ifdef ENABLE_BIGINT node->isKind(ParseNodeKind::BigIntExpr) || -#endif node->isKind(ParseNodeKind::NullExpr) || node->isKind(ParseNodeKind::RawUndefinedExpr) || node->isKind(ParseNodeKind::Function); @@ -500,11 +496,9 @@ static Truthiness Boolish(ParseNode* pn) { ? Truthy : Falsy; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: return (pn->as().box()->value()->isZero()) ? Falsy : Truthy; -#endif case ParseNodeKind::StringExpr: case ParseNodeKind::TemplateStringExpr: @@ -574,13 +568,9 @@ static bool FoldTypeOfExpr(JSContext* cx, FullParseHandler* handler, result = cx->names().string; } else if (expr->isKind(ParseNodeKind::NumberExpr)) { result = cx->names().number; - } -#ifdef ENABLE_BIGINT - else if (expr->isKind(ParseNodeKind::BigIntExpr)) { + } else if (expr->isKind(ParseNodeKind::BigIntExpr)) { result = cx->names().bigint; - } -#endif - else if (expr->isKind(ParseNodeKind::NullExpr)) { + } else if (expr->isKind(ParseNodeKind::NullExpr)) { result = cx->names().object; } else if (expr->isKind(ParseNodeKind::TrueExpr) || expr->isKind(ParseNodeKind::FalseExpr)) { diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index cfabb761ffbc..34c8f43f11d6 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -130,7 +130,6 @@ class FullParseHandler { return new_(value, decimalPoint, pos); } -#ifdef ENABLE_BIGINT // The Boxer object here is any object that can allocate BigIntBoxes. // Specifically, a Boxer has a .newBigIntBox(T) method that accepts a // BigInt* argument and returns a BigIntBox*. @@ -142,7 +141,6 @@ class FullParseHandler { } return new_(box, pos); } -#endif BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) { return new_(cond, pos); diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 35c040cf2fb7..159424e3b39b 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -464,11 +464,9 @@ class NameResolver { MOZ_ASSERT(cur->is()); break; -#ifdef ENABLE_BIGINT case ParseNodeKind::BigIntExpr: MOZ_ASSERT(cur->is()); break; -#endif case ParseNodeKind::TypeOfNameExpr: case ParseNodeKind::SuperBase: diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 080daf25ebc5..3547d895c314 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -169,11 +169,9 @@ void ParseNode::dump(GenericPrinter& out, int indent) { case PN_NUMBER: as().dump(out, indent); return; -# ifdef ENABLE_BIGINT case PN_BIGINT: as().dump(out, indent); return; -# endif case PN_REGEXP: as().dump(out, indent); return; @@ -220,11 +218,9 @@ void NumericLiteral::dump(GenericPrinter& out, int indent) { } } -# ifdef ENABLE_BIGINT void BigIntLiteral::dump(GenericPrinter& out, int indent) { out.printf("(%s)", parseNodeNames[size_t(getKind())]); } -# endif void RegExpLiteral::dump(GenericPrinter& out, int indent) { out.printf("(%s)", parseNodeNames[size_t(getKind())]); @@ -432,22 +428,18 @@ TraceListNode::TraceListNode(js::gc::Cell* gcThing, TraceListNode* traceLink) MOZ_ASSERT(gcThing->isTenured()); } -#ifdef ENABLE_BIGINT BigIntBox* TraceListNode::asBigIntBox() { MOZ_ASSERT(isBigIntBox()); return static_cast(this); } -#endif ObjectBox* TraceListNode::asObjectBox() { MOZ_ASSERT(isObjectBox()); return static_cast(this); } -#ifdef ENABLE_BIGINT BigIntBox::BigIntBox(BigInt* bi, TraceListNode* traceLink) : TraceListNode(bi, traceLink) {} -#endif ObjectBox::ObjectBox(JSObject* obj, TraceListNode* traceLink) : TraceListNode(obj, traceLink), emitLink(nullptr) { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 0c04720db454..c2b3f4f9b41c 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -10,9 +10,7 @@ #include "mozilla/Attributes.h" #include "frontend/TokenStream.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/BytecodeUtil.h" #include "vm/Printer.h" #include "vm/Scope.h" @@ -48,9 +46,7 @@ class ParseContext; class FullParseHandler; class FunctionBox; class ObjectBox; -#ifdef ENABLE_BIGINT class BigIntBox; -#endif #define FOR_EACH_PARSE_NODE_KIND(F) \ F(EmptyStmt, NullaryNode) \ @@ -80,7 +76,7 @@ class BigIntBox; F(PrivateName, NameNode) \ F(ComputedName, UnaryNode) \ F(NumberExpr, NumericLiteral) \ - IF_BIGINT(F(BigIntExpr, BigIntLiteral), /**/) \ + F(BigIntExpr, BigIntLiteral) \ F(StringExpr, NameNode) \ F(TemplateStringListExpr, ListNode) \ F(TemplateStringExpr, NameNode) \ @@ -535,12 +531,10 @@ enum ParseNodeArity { PN_NAME, /* name, label, string */ PN_FIELD, /* field name, optional initializer */ PN_NUMBER, /* numeric literal */ -#ifdef ENABLE_BIGINT - PN_BIGINT, /* BigInt literal */ -#endif - PN_REGEXP, /* regexp literal */ - PN_LOOP, /* loop control (break/continue) */ - PN_SCOPE /* lexical scope */ + PN_BIGINT, /* BigInt literal */ + PN_REGEXP, /* regexp literal */ + PN_LOOP, /* loop control (break/continue) */ + PN_SCOPE /* lexical scope */ }; // FIXME: Remove `*Type` (bug 1489008) @@ -579,7 +573,7 @@ enum ParseNodeArity { MACRO(RawUndefinedLiteral, RawUndefinedLiteralType, asRawUndefinedLiteral) \ \ MACRO(NumericLiteral, NumericLiteralType, asNumericLiteral) \ - IF_BIGINT(MACRO(BigIntLiteral, BigIntLiteralType, asBigIntLiteral), ) \ + MACRO(BigIntLiteral, BigIntLiteralType, asBigIntLiteral) \ \ MACRO(RegExpLiteral, RegExpLiteralType, asRegExpLiteral) \ \ @@ -708,9 +702,7 @@ class ParseNode { /* True if pn is a parsenode representing a literal constant. */ bool isLiteral() const { return isKind(ParseNodeKind::NumberExpr) || -#ifdef ENABLE_BIGINT isKind(ParseNodeKind::BigIntExpr) || -#endif isKind(ParseNodeKind::StringExpr) || isKind(ParseNodeKind::TrueExpr) || isKind(ParseNodeKind::FalseExpr) || @@ -1531,7 +1523,6 @@ class NumericLiteral : public ParseNode { void setDecimalPoint(DecimalPoint d) { decimalPoint_ = d; } }; -#ifdef ENABLE_BIGINT class BigIntLiteral : public ParseNode { BigIntBox* box_; @@ -1558,7 +1549,6 @@ class BigIntLiteral : public ParseNode { BigIntBox* box() const { return box_; } }; -#endif class LexicalScopeNode : public ParseNode { LexicalScope::Data* bindings; @@ -2164,14 +2154,10 @@ class TraceListNode { TraceListNode(js::gc::Cell* gcThing, TraceListNode* traceLink); -#ifdef ENABLE_BIGINT bool isBigIntBox() const { return gcThing->is(); } -#endif bool isObjectBox() const { return gcThing->is(); } -#ifdef ENABLE_BIGINT BigIntBox* asBigIntBox(); -#endif ObjectBox* asObjectBox(); virtual void trace(JSTracer* trc); @@ -2180,13 +2166,11 @@ class TraceListNode { static void TraceList(JSTracer* trc, TraceListNode* listHead); }; -#ifdef ENABLE_BIGINT class BigIntBox : public TraceListNode { public: BigIntBox(BigInt* bi, TraceListNode* link); BigInt* value() const { return gcThing->as(); } }; -#endif class ObjectBox : public TraceListNode { protected: diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 98fb1c665f43..5bd02f91e025 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -275,11 +275,9 @@ ObjectBox* ParserBase::newObjectBox(JSObject* obj) { return newTraceListNode(obj); } -#ifdef ENABLE_BIGINT BigIntBox* ParserBase::newBigIntBox(BigInt* val) { return newTraceListNode(val); } -#endif template FunctionBox* PerHandlerParser::newFunctionBox( @@ -9020,7 +9018,6 @@ GeneralParser::newRegExp() { return asFinalParser()->newRegExp(); } -#ifdef ENABLE_BIGINT template BigIntLiteral* Parser::newBigInt() { // The token's charBuffer contains the DecimalIntegerLiteral or @@ -9054,7 +9051,6 @@ typename ParseHandler::BigIntLiteralType GeneralParser::newBigInt() { return asFinalParser()->newBigInt(); } -#endif /* ENABLE_BIGINT */ // |exprPossibleError| is the PossibleError state within |expr|, // |possibleError| is the surrounding PossibleError state. @@ -10080,10 +10076,8 @@ typename ParseHandler::Node GeneralParser::primaryExpr( case TokenKind::Number: return newNumber(anyChars.currentToken()); -#ifdef ENABLE_BIGINT case TokenKind::BigInt: return newBigInt(); -#endif case TokenKind::True: return handler.newBooleanLiteral(true, pos()); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index ac248a5735a8..bb92c7badc44 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -399,9 +399,7 @@ class MOZ_STACK_CLASS ParserBase : private JS::AutoGCRooter, public: ObjectBox* newObjectBox(JSObject* obj); -#ifdef ENABLE_BIGINT BigIntBox* newBigIntBox(BigInt* val); -#endif mozilla::Maybe newGlobalScopeData( ParseContext::Scope& scope); @@ -1385,9 +1383,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos); } -#ifdef ENABLE_BIGINT inline BigIntLiteralType newBigInt(); -#endif protected: // Match the current token against the BindingIdentifier production with @@ -1530,9 +1526,7 @@ class MOZ_STACK_CLASS Parser final inline void setInParametersOfAsyncFunction(bool inParameters); RegExpLiteralType newRegExp(); -#ifdef ENABLE_BIGINT BigIntLiteralType newBigInt(); -#endif // Parse a module. ModuleNodeType moduleBody(ModuleSharedContext* modulesc); @@ -1685,9 +1679,7 @@ class MOZ_STACK_CLASS Parser final inline void setInParametersOfAsyncFunction(bool inParameters); RegExpLiteralType newRegExp(); -#ifdef ENABLE_BIGINT BigIntLiteralType newBigInt(); -#endif // Parse a module. ModuleNodeType moduleBody(ModuleSharedContext* modulesc); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 1eb0aeaf4d3a..c4ea3b38d391 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -207,9 +207,7 @@ class SyntaxParseHandler { return NodeGeneric; } -#ifdef ENABLE_BIGINT BigIntLiteralType newBigInt() { return NodeGeneric; } -#endif BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) { return NodeGeneric; diff --git a/js/src/frontend/TokenKind.h b/js/src/frontend/TokenKind.h index a572f2179794..2b0bb62a6e99 100644 --- a/js/src/frontend/TokenKind.h +++ b/js/src/frontend/TokenKind.h @@ -76,7 +76,7 @@ MACRO(PrivateName, "private identifier") \ MACRO(Number, "numeric literal") \ MACRO(String, "string literal") \ - IF_BIGINT(MACRO(BigInt, "bigint literal"), ) \ + MACRO(BigInt, "bigint literal") \ \ /* start of template literal with substitutions */ \ MACRO(TemplateHead, "'${'") \ diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index 743355343bff..46960f34d75e 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -2142,12 +2142,9 @@ MOZ_MUST_USE bool TokenStreamSpecific::decimalNumber( // Numbers contain no escapes, so we can read directly from |sourceUnits|. double dval; -#ifdef ENABLE_BIGINT bool isBigInt = false; -#endif DecimalPoint decimalPoint = NoDecimal; - if (unit != '.' && unit != 'e' && unit != 'E' && - IF_BIGINT(unit != 'n', true)) { + if (unit != '.' && unit != 'e' && unit != 'E' && unit != 'n') { // NOTE: |unit| may be EOF here. ungetCodeUnit(unit); @@ -2157,14 +2154,10 @@ MOZ_MUST_USE bool TokenStreamSpecific::decimalNumber( this->sourceUnits.addressOfNextCodeUnit(), &dval)) { return false; } - } -#ifdef ENABLE_BIGINT - else if (unit == 'n' && anyCharsAccess().options().bigIntEnabledOption) { + } else if (unit == 'n' && anyCharsAccess().options().bigIntEnabledOption) { isBigInt = true; unit = peekCodeUnit(); - } -#endif - else { + } else { // Consume any decimal dot and fractional component. if (unit == '.') { decimalPoint = HasDecimal; @@ -2226,11 +2219,9 @@ MOZ_MUST_USE bool TokenStreamSpecific::decimalNumber( noteBadToken.release(); -#ifdef ENABLE_BIGINT if (isBigInt) { return bigIntLiteral(start, modifier, out); } -#endif newNumberToken(dval, decimalPoint, start, modifier, out); return true; @@ -2361,7 +2352,6 @@ MOZ_MUST_USE bool TokenStreamSpecific::regexpLiteral( return true; } -#ifdef ENABLE_BIGINT template MOZ_MUST_USE bool TokenStreamSpecific::bigIntLiteral( TokenStart start, Modifier modifier, TokenKind* out) { @@ -2386,7 +2376,6 @@ MOZ_MUST_USE bool TokenStreamSpecific::bigIntLiteral( newBigIntToken(start, modifier, out); return true; } -#endif template MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( @@ -2552,10 +2541,8 @@ MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( if (c1kind == ZeroDigit) { TokenStart start(this->sourceUnits, -1); int radix; -#ifdef ENABLE_BIGINT bool isLegacyOctalOrNoctal = false; bool isBigInt = false; -#endif const Unit* numStart; unit = getCodeUnit(); if (unit == 'x' || unit == 'X') { @@ -2608,9 +2595,7 @@ MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( } } else if (IsAsciiDigit(unit)) { radix = 8; -#ifdef ENABLE_BIGINT isLegacyOctalOrNoctal = true; -#endif // one past the '0' numStart = this->sourceUnits.addressOfNextCodeUnit() - 1; @@ -2645,7 +2630,6 @@ MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( return decimalNumber(unit, start, numStart, modifier, ttp); } -#ifdef ENABLE_BIGINT if (unit == 'n' && anyCharsAccess().options().bigIntEnabledOption) { if (isLegacyOctalOrNoctal) { error(JSMSG_BIGINT_INVALID_SYNTAX); @@ -2656,9 +2640,6 @@ MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( } else { ungetCodeUnit(unit); } -#else - ungetCodeUnit(unit); -#endif // Error if an identifier-start code point appears immediately // after the number. Somewhat surprisingly, if we don't check @@ -2679,11 +2660,9 @@ MOZ_MUST_USE bool TokenStreamSpecific::getTokenInternal( } } -#ifdef ENABLE_BIGINT if (isBigInt) { return bigIntLiteral(start, modifier, ttp); } -#endif double dval; if (!GetFullInteger(anyCharsAccess().cx, numStart, diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index 97b7eec0f5fd..ae3e2fbd89fb 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -1954,12 +1954,10 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase { token->setNumber(dval, decimalPoint); } -#ifdef ENABLE_BIGINT void newBigIntToken(TokenStart start, TokenStreamShared::Modifier modifier, TokenKind* out) { newToken(TokenKind::BigInt, start, modifier, out); } -#endif void newAtomToken(TokenKind kind, JSAtom* atom, TokenStart start, TokenStreamShared::Modifier modifier, TokenKind* out) { @@ -2412,9 +2410,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific using TokenStreamCharsShared::copyCharBufferTo; using TokenStreamCharsShared::drainCharBufferIntoAtom; using TokenStreamCharsShared::isAsciiCodePoint; -#ifdef ENABLE_BIGINT using GeneralCharsBase::newBigIntToken; -#endif using CharsBase::peekCodeUnit; using GeneralCharsBase::newRegExpToken; using GeneralCharsBase::newSimpleToken; diff --git a/js/src/fuzz-tests/tests.cpp b/js/src/fuzz-tests/tests.cpp index e2d041dd2643..37a543aa5925 100644 --- a/js/src/fuzz-tests/tests.cpp +++ b/js/src/fuzz-tests/tests.cpp @@ -43,9 +43,7 @@ static JSObject* jsfuzz_createGlobal(JSContext* cx, JSPrincipals* principals) { JS::RootedObject newGlobal(cx); JS::RealmOptions options; options.creationOptions().setStreamsEnabled(true); -#ifdef ENABLE_BIGINT options.creationOptions().setBigIntEnabled(true); -#endif newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook, options); if (!newGlobal) { diff --git a/js/src/gc/AllocKind.h b/js/src/gc/AllocKind.h index 25b72e20d814..6610155e8e22 100644 --- a/js/src/gc/AllocKind.h +++ b/js/src/gc/AllocKind.h @@ -66,7 +66,7 @@ namespace gc { D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, true) \ D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, true) \ D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, true, false, false) \ - IF_BIGINT(D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, false, false),) \ + D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, false, false) \ D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, false, false, false) \ D(SCOPE, Scope, js::Scope, js::Scope, true, false, true) \ D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, true, false, true) diff --git a/js/src/gc/AtomMarking.cpp b/js/src/gc/AtomMarking.cpp index 943b07a2c291..282174c01899 100644 --- a/js/src/gc/AtomMarking.cpp +++ b/js/src/gc/AtomMarking.cpp @@ -184,9 +184,9 @@ void AtomMarkingRuntime::markAtomValue(JSContext* cx, const Value& value) { markAtom(cx, value.toSymbol()); return; } - MOZ_ASSERT_IF(value.isGCThing(), value.isObject() || - value.isPrivateGCThing() || - IF_BIGINT(value.isBigInt(), false)); + MOZ_ASSERT_IF(value.isGCThing(), + value.isObject() || value.isPrivateGCThing() || + value.isBigInt()); } void AtomMarkingRuntime::adoptMarkedAtoms(Zone* target, Zone* source) { @@ -267,9 +267,9 @@ bool AtomMarkingRuntime::valueIsMarked(Zone* zone, const Value& value) { return atomIsMarked(zone, value.toSymbol()); } - MOZ_ASSERT_IF(value.isGCThing(), value.isObject() || - value.isPrivateGCThing() || - IF_BIGINT(value.isBigInt(), false)); + MOZ_ASSERT_IF(value.isGCThing(), + value.isObject() || value.isPrivateGCThing() || + value.isBigInt()); return true; } diff --git a/js/src/gc/DeletePolicy.h b/js/src/gc/DeletePolicy.h index c9947e655c14..4f66ef3d2f3e 100644 --- a/js/src/gc/DeletePolicy.h +++ b/js/src/gc/DeletePolicy.h @@ -25,9 +25,7 @@ struct ClearEdgesTracer : public JS::CallbackTracer { void onObjectEdge(JSObject** objp) override; void onStringEdge(JSString** strp) override; void onSymbolEdge(JS::Symbol** symp) override; -#ifdef ENABLE_BIGINT void onBigIntEdge(JS::BigInt** bip) override; -#endif void onScriptEdge(JSScript** scriptp) override; void onShapeEdge(js::Shape** shapep) override; void onObjectGroupEdge(js::ObjectGroup** groupp) override; diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index b95eab747a2b..ec5e50c0687c 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -229,9 +229,7 @@ #include "js/SliceBudget.h" #include "proxy/DeadObjectProxy.h" #include "util/Windows.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/Debugger.h" #include "vm/GeckoProfiler.h" #include "vm/JSAtom.h" @@ -506,10 +504,7 @@ static const FinalizePhase BackgroundFinalizePhases[] = { {gcstats::PhaseKind::SWEEP_STRING, {AllocKind::FAT_INLINE_STRING, AllocKind::STRING, AllocKind::EXTERNAL_STRING, AllocKind::FAT_INLINE_ATOM, AllocKind::ATOM, - AllocKind::SYMBOL, -#ifdef ENABLE_BIGINT - AllocKind::BIGINT -#endif + AllocKind::SYMBOL, AllocKind::BIGINT }}, {gcstats::PhaseKind::SWEEP_SHAPE, {AllocKind::SHAPE, AllocKind::ACCESSOR_SHAPE, AllocKind::BASE_SHAPE, @@ -8383,10 +8378,8 @@ JS::GCCellPtr::GCCellPtr(const Value& v) : ptr(0) { ptr = checkedCast(&v.toObject(), JS::TraceKind::Object); } else if (v.isSymbol()) { ptr = checkedCast(v.toSymbol(), JS::TraceKind::Symbol); -#ifdef ENABLE_BIGINT } else if (v.isBigInt()) { ptr = checkedCast(v.toBigInt(), JS::TraceKind::BigInt); -#endif } else if (v.isPrivateGCThing()) { ptr = checkedCast(v.toGCThing(), v.toGCThing()->getTraceKind()); } else { @@ -9003,11 +8996,9 @@ void js::gc::ClearEdgesTracer::onStringEdge(JSString** strp) { void js::gc::ClearEdgesTracer::onSymbolEdge(JS::Symbol** symp) { clearEdge(symp); } -#ifdef ENABLE_BIGINT void js::gc::ClearEdgesTracer::onBigIntEdge(JS::BigInt** bip) { clearEdge(bip); } -#endif void js::gc::ClearEdgesTracer::onScriptEdge(JSScript** scriptp) { clearEdge(scriptp); } diff --git a/js/src/gc/Marking-inl.h b/js/src/gc/Marking-inl.h index 24a13408d0a6..ba0fc2347171 100644 --- a/js/src/gc/Marking-inl.h +++ b/js/src/gc/Marking-inl.h @@ -13,10 +13,7 @@ #include "gc/RelocationOverlay.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif - +#include "vm/BigIntType.h" #include "vm/RegExpShared.h" namespace js { @@ -32,9 +29,7 @@ struct TaggedPtr { static JS::Value wrap(JSObject* obj) { return JS::ObjectOrNullValue(obj); } static JS::Value wrap(JSString* str) { return JS::StringValue(str); } static JS::Value wrap(JS::Symbol* sym) { return JS::SymbolValue(sym); } -#ifdef ENABLE_BIGINT static JS::Value wrap(JS::BigInt* bi) { return JS::BigIntValue(bi); } -#endif template static JS::Value wrap(T* priv) { static_assert(mozilla::IsBaseOf::value, diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 2488dd42d97d..53de2b466388 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -22,9 +22,7 @@ #include "js/SliceBudget.h" #include "vm/ArgumentsObject.h" #include "vm/ArrayObject.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/Debugger.h" #include "vm/EnvironmentObject.h" #include "vm/RegExpShared.h" @@ -803,12 +801,10 @@ template <> void GCMarker::traverse(JS::Symbol* thing) { markAndTraceChildren(thing); } -#ifdef ENABLE_BIGINT template <> void GCMarker::traverse(JS::BigInt* thing) { markAndTraceChildren(thing); } -#endif template <> void GCMarker::traverse(RegExpShared* thing) { markAndTraceChildren(thing); @@ -1496,9 +1492,7 @@ void js::GCMarker::lazilyMarkChildren(ObjectGroup* group) { } } -#ifdef ENABLE_BIGINT void JS::BigInt::traceChildren(JSTracer* trc) { return; } -#endif template static void VisitTraceList(const Functor& f, const int32_t* traceList, @@ -1659,7 +1653,7 @@ inline static bool ObjectDenseElementsMayBeMarkable(NativeObject* nobj) { static const uint32_t flagMask = TYPE_FLAG_STRING | TYPE_FLAG_SYMBOL | TYPE_FLAG_LAZYARGS | TYPE_FLAG_ANYOBJECT | - IF_BIGINT(TYPE_FLAG_BIGINT, 0); + TYPE_FLAG_BIGINT; bool mayBeMarkable = typeSet->hasAnyFlag(flagMask) || typeSet->getObjectCount() != 0; @@ -1776,13 +1770,9 @@ scan_value_array: } } else if (v.isSymbol()) { traverseEdge(obj, v.toSymbol()); - } -#ifdef ENABLE_BIGINT - else if (v.isBigInt()) { + } else if (v.isBigInt()) { traverseEdge(obj, v.toBigInt()); - } -#endif - else if (v.isPrivateGCThing()) { + } else if (v.isPrivateGCThing()) { // v.toGCCellPtr cannot be inlined, so construct one manually. Cell* cell = v.toGCThing(); traverseEdge(obj, JS::GCCellPtr(cell, cell->getTraceKind())); diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 9b40245fcd20..d3eb1461ed5e 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -466,9 +466,7 @@ class BufferGrayRootsTracer final : public JS::CallbackTracer { void onStringEdge(JSString** stringp) override { bufferRoot(*stringp); } void onScriptEdge(JSScript** scriptp) override { bufferRoot(*scriptp); } void onSymbolEdge(JS::Symbol** symbolp) override { bufferRoot(*symbolp); } -#ifdef ENABLE_BIGINT void onBigIntEdge(JS::BigInt** bip) override { bufferRoot(*bip); } -#endif void onChild(const JS::GCCellPtr& thing) override { MOZ_CRASH("Unexpected gray root kind"); diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 2bfb68e50765..2483707109ec 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -15,9 +15,7 @@ #include "gc/PublicIterators.h" #include "gc/Zone.h" #include "util/Text.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/JSFunction.h" #include "vm/JSScript.h" #include "vm/Shape.h" @@ -334,11 +332,9 @@ JS_PUBLIC_API void JS_GetTraceThingInfo(char* buf, size_t bufsize, name = "symbol"; break; -#ifdef ENABLE_BIGINT case JS::TraceKind::BigInt: name = "BigInt"; break; -#endif default: name = "INVALID"; diff --git a/js/src/gdb/lib-for-tests/prologue.py b/js/src/gdb/lib-for-tests/prologue.py index 2735cf09c4d5..5b751d56547e 100644 --- a/js/src/gdb/lib-for-tests/prologue.py +++ b/js/src/gdb/lib-for-tests/prologue.py @@ -83,13 +83,6 @@ def assert_subprinter_registered(printer, subprinter): "%s" % (printer, subprinter, output)) -enable_bigint = False -try: - if gdb.lookup_type('JS::BigInt'): - enable_bigint = True -except Exception: - pass - # Request full stack traces for Python errors. gdb.execute('set python print-stack full') diff --git a/js/src/gdb/mozilla/jsval.py b/js/src/gdb/mozilla/jsval.py index b65a4b2fb1b1..0ec679bbcb6e 100644 --- a/js/src/gdb/mozilla/jsval.py +++ b/js/src/gdb/mozilla/jsval.py @@ -152,18 +152,10 @@ class JSValueTypeCache(object): self.MAGIC = get('JSVAL_TYPE_MAGIC') self.STRING = get('JSVAL_TYPE_STRING') self.SYMBOL = get('JSVAL_TYPE_SYMBOL') + self.BIGINT = get('JSVAL_TYPE_BIGINT') self.NULL = get('JSVAL_TYPE_NULL') self.OBJECT = get('JSVAL_TYPE_OBJECT') - self.enable_bigint = False - try: - # Looking up the tag will throw an exception if BigInt is not - # enabled. - self.BIGINT = get('JSVAL_TYPE_BIGINT') - self.enable_bigint = True - except Exception: - pass - # Let self.magic_names be an array whose i'th element is the name of # the i'th magic value. d = gdb.types.make_enum_dict(gdb.lookup_type('JSWhyMagic')) @@ -218,7 +210,7 @@ class JSValue(object): value = self.box.as_address().cast(self.cache.JSObject_ptr_t) elif tag == self.jtc.SYMBOL: value = self.box.as_address().cast(self.cache.JSSymbol_ptr_t) - elif self.jtc.enable_bigint and tag == self.jtc.BIGINT: + elif tag == self.jtc.BIGINT: return '$JS::BigIntValue()' else: value = 'unrecognized!' diff --git a/js/src/gdb/tests/test-jsval.cpp b/js/src/gdb/tests/test-jsval.cpp index 55c230e7cf6a..9fe172e6fcaf 100644 --- a/js/src/gdb/tests/test-jsval.cpp +++ b/js/src/gdb/tests/test-jsval.cpp @@ -2,9 +2,7 @@ #include "jsapi.h" #include "js/Symbol.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" FRAGMENT(jsval, simple) { using namespace JS; @@ -23,9 +21,7 @@ FRAGMENT(jsval, simple) { RootedString hello(cx, JS_NewStringCopyZ(cx, "Hello!")); RootedValue friendly_string(cx, StringValue(hello)); RootedValue symbol(cx, SymbolValue(GetSymbolFor(cx, hello))); -#ifdef ENABLE_BIGINT RootedValue bi(cx, BigIntValue(BigInt::zero(cx))); -#endif RootedValue global(cx); global.setObject(*CurrentGlobalOrNull(cx)); @@ -47,8 +43,6 @@ FRAGMENT(jsval, simple) { use(empty_string); use(friendly_string); use(symbol); -#ifdef ENABLE_BIGINT use(bi); -#endif use(global); } diff --git a/js/src/gdb/tests/test-jsval.py b/js/src/gdb/tests/test-jsval.py index 24e0f9685427..f542fc8eeb65 100644 --- a/js/src/gdb/tests/test-jsval.py +++ b/js/src/gdb/tests/test-jsval.py @@ -16,7 +16,6 @@ assert_pretty('elements_hole', '$JS::MagicValue(JS_ELEMENTS_HOLE)') assert_pretty('empty_string', '$JS::Value("")') assert_pretty('friendly_string', '$JS::Value("Hello!")') assert_pretty('symbol', '$JS::Value(Symbol.for("Hello!"))') -if enable_bigint: - assert_pretty('bi', '$JS::BigIntValue()') +assert_pretty('bi', '$JS::BigIntValue()') assert_pretty('global', '$JS::Value((JSObject *) [object global] delegate)') assert_pretty('onehundredthirtysevenonehundredtwentyeighths', '$JS::DoubleValue(1.0703125)') diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index be622c81353a..0ed68ff2cece 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -2183,9 +2183,7 @@ bool jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo) { case Bailout_NonObjectInput: case Bailout_NonStringInput: case Bailout_NonSymbolInput: -#ifdef ENABLE_BIGINT case Bailout_NonBigIntInput: -#endif case Bailout_NonSharedTypedArrayInput: case Bailout_Debugger: case Bailout_UninitializedThis: diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 4603bf7a0738..08f07ca796b9 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -2042,12 +2042,10 @@ bool BaselineInterpreterCodeGen::emit_JSOP_DOUBLE() { MOZ_CRASH("NYI: interpreter JSOP_DOUBLE"); } -#ifdef ENABLE_BIGINT template bool BaselineCodeGen::emit_JSOP_BIGINT() { return emit_JSOP_DOUBLE(); } -#endif template <> bool BaselineCompilerCodeGen::emit_JSOP_STRING() { diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index cf88e0b2af76..c99c9b78bd4f 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -55,7 +55,7 @@ namespace jit { _(JSOP_UINT24) \ _(JSOP_RESUMEINDEX) \ _(JSOP_DOUBLE) \ - IF_BIGINT(_(JSOP_BIGINT), ) \ + _(JSOP_BIGINT) \ _(JSOP_STRING) \ _(JSOP_SYMBOL) \ _(JSOP_OBJECT) \ diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 9787dbbd5f72..7e2042e0b50d 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -1464,11 +1464,9 @@ bool ICTypeMonitor_PrimitiveSet::Compiler::generateStubCode( masm.branchTestSymbol(Assembler::Equal, R0, &success); } -#ifdef ENABLE_BIGINT if (flags_ & TypeToFlag(JSVAL_TYPE_BIGINT)) { masm.branchTestBigInt(Assembler::Equal, R0, &success); } -#endif if (flags_ & TypeToFlag(JSVAL_TYPE_OBJECT)) { masm.branchTestObject(Assembler::Equal, R0, &success); @@ -1810,11 +1808,9 @@ bool ICTypeUpdate_PrimitiveSet::Compiler::generateStubCode( masm.branchTestSymbol(Assembler::Equal, R0, &success); } -#ifdef ENABLE_BIGINT if (flags_ & TypeToFlag(JSVAL_TYPE_BIGINT)) { masm.branchTestBigInt(Assembler::Equal, R0, &success); } -#endif if (flags_ & TypeToFlag(JSVAL_TYPE_OBJECT)) { masm.branchTestObject(Assembler::Equal, R0, &success); diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index 17c01b2e7ce2..c2952eccea44 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -485,11 +485,9 @@ static bool GuardType(CacheIRReader& reader, case CacheOp::GuardIsSymbol: guardType[guardOperand] = MIRType::Symbol; break; -#ifdef ENABLE_BIGINT case CacheOp::GuardIsBigInt: guardType[guardOperand] = MIRType::BigInt; break; -#endif case CacheOp::GuardIsNumber: guardType[guardOperand] = MIRType::Double; break; diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index 5ffef3c66ada..6469d953d1a4 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -1952,13 +1952,9 @@ bool GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId, HandleId id) { protoKey = JSProto_Boolean; } else if (val_.isSymbol()) { protoKey = JSProto_Symbol; - } -#ifdef ENABLE_BIGINT - else if (val_.isBigInt()) { + } else if (val_.isBigInt()) { protoKey = JSProto_BigInt; - } -#endif - else { + } else { MOZ_ASSERT(val_.isNullOrUndefined() || val_.isMagic()); return false; } @@ -5444,7 +5440,7 @@ bool CompareIRGenerator::tryAttachPrimitiveUndefined(ValOperandId lhsId, // undefined) auto isPrimitive = [](HandleValue& x) { return x.isString() || x.isSymbol() || x.isBoolean() || x.isNumber() || - IF_BIGINT(x.isBigInt(), false); + x.isBigInt(); }; if (!(lhsVal_.isNullOrUndefined() && isPrimitive(rhsVal_)) && @@ -5464,11 +5460,9 @@ bool CompareIRGenerator::tryAttachPrimitiveUndefined(ValOperandId lhsId, case JSVAL_TYPE_SYMBOL: writer.guardIsSymbol(id); return; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: writer.guardIsBigInt(id); return; -#endif case JSVAL_TYPE_STRING: writer.guardIsString(id); return; diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h index 25355b84460f..a8c8317fca23 100644 --- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -109,13 +109,11 @@ class SymbolOperandId : public OperandId { explicit SymbolOperandId(uint16_t id) : OperandId(id) {} }; -#ifdef ENABLE_BIGINT class BigIntOperandId : public OperandId { public: BigIntOperandId() = default; explicit BigIntOperandId(uint16_t id) : OperandId(id) {} }; -#endif class Int32OperandId : public OperandId { public: @@ -133,10 +131,8 @@ class TypedOperandId : public OperandId { : OperandId(id.id()), type_(JSVAL_TYPE_STRING) {} MOZ_IMPLICIT TypedOperandId(SymbolOperandId id) : OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL) {} -#ifdef ENABLE_BIGINT MOZ_IMPLICIT TypedOperandId(BigIntOperandId id) : OperandId(id.id()), type_(JSVAL_TYPE_BIGINT) {} -#endif MOZ_IMPLICIT TypedOperandId(Int32OperandId id) : OperandId(id.id()), type_(JSVAL_TYPE_INT32) {} MOZ_IMPLICIT TypedOperandId(ValueTagOperandId val) @@ -187,7 +183,7 @@ extern const char* const CacheKindNames[]; _(GuardIsBoolean) \ _(GuardIsString) \ _(GuardIsSymbol) \ - IF_BIGINT(_(GuardIsBigInt), ) \ + _(GuardIsBigInt) \ _(GuardIsNumber) \ _(GuardIsInt32) \ _(GuardIsInt32Index) \ @@ -608,12 +604,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter { writeOpWithOperandId(CacheOp::GuardIsSymbol, val); return SymbolOperandId(val.id()); } -#ifdef ENABLE_BIGINT BigIntOperandId guardIsBigInt(ValOperandId val) { writeOpWithOperandId(CacheOp::GuardIsBigInt, val); return BigIntOperandId(val.id()); } -#endif Int32OperandId guardIsInt32(ValOperandId val) { Int32OperandId res(nextOperandId_++); writeOpWithOperandId(CacheOp::GuardIsInt32, val); diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index f26473eddcea..21b851a71e03 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -1477,7 +1477,6 @@ bool CacheIRCompiler::emitGuardIsSymbol() { return true; } -#ifdef ENABLE_BIGINT bool CacheIRCompiler::emitGuardIsBigInt() { JitSpew(JitSpew_Codegen, __FUNCTION__); ValOperandId inputId = reader.valOperandId(); @@ -1493,7 +1492,6 @@ bool CacheIRCompiler::emitGuardIsBigInt() { masm.branchTestBigInt(Assembler::NotEqual, input, failure->label()); return true; } -#endif bool CacheIRCompiler::emitGuardIsInt32() { JitSpew(JitSpew_Codegen, __FUNCTION__); @@ -1591,11 +1589,9 @@ bool CacheIRCompiler::emitGuardType() { case JSVAL_TYPE_SYMBOL: masm.branchTestSymbol(Assembler::NotEqual, input, failure->label()); break; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: masm.branchTestBigInt(Assembler::NotEqual, input, failure->label()); break; -#endif case JSVAL_TYPE_INT32: masm.branchTestInt32(Assembler::NotEqual, input, failure->label()); break; diff --git a/js/src/jit/CacheIRCompiler.h b/js/src/jit/CacheIRCompiler.h index 4940b0db86dd..a7c0402681ae 100644 --- a/js/src/jit/CacheIRCompiler.h +++ b/js/src/jit/CacheIRCompiler.h @@ -26,7 +26,7 @@ namespace jit { _(GuardIsBoolean) \ _(GuardIsString) \ _(GuardIsSymbol) \ - IF_BIGINT(_(GuardIsBigInt), ) \ + _(GuardIsBigInt) \ _(GuardIsNumber) \ _(GuardIsInt32) \ _(GuardIsInt32Index) \ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index ec0c07ced119..59883fecf147 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -786,7 +786,7 @@ void CodeGenerator::testValueTruthyKernel( bool mightBeString = valueMIR->mightBeType(MIRType::String); bool mightBeSymbol = valueMIR->mightBeType(MIRType::Symbol); bool mightBeDouble = valueMIR->mightBeType(MIRType::Double); - bool mightBeBigInt = IF_BIGINT(valueMIR->mightBeType(MIRType::BigInt), false); + bool mightBeBigInt = valueMIR->mightBeType(MIRType::BigInt); int tagCount = int(mightBeUndefined) + int(mightBeNull) + int(mightBeBoolean) + int(mightBeInt32) + int(mightBeObject) + int(mightBeString) + int(mightBeSymbol) + int(mightBeDouble) + @@ -904,7 +904,6 @@ void CodeGenerator::testValueTruthyKernel( --tagCount; } -#ifdef ENABLE_BIGINT if (mightBeBigInt) { MOZ_ASSERT(tagCount != 0); Label notBigInt; @@ -921,7 +920,6 @@ void CodeGenerator::testValueTruthyKernel( masm.bind(¬BigInt); --tagCount; } -#endif if (mightBeSymbol) { // All symbols are truthy. @@ -1265,13 +1263,11 @@ void CodeGenerator::visitValueToString(LValueToString* lir) { bailoutFrom(&bail, lir->snapshot()); } -#ifdef ENABLE_BIGINT // BigInt if (lir->mir()->input()->mightBeType(MIRType::BigInt)) { // No fastpath currently implemented. masm.branchTestBigInt(Assembler::Equal, tag, ool->entry()); } -#endif #ifdef DEBUG masm.assumeUnreachable("Unexpected type for MValueToString."); @@ -4009,10 +4005,8 @@ void CodeGenerator::visitToNumeric(LToNumeric* lir) { bool maybeInt32 = lir->mir()->mightBeType(MIRType::Int32); bool maybeDouble = lir->mir()->mightBeType(MIRType::Double); bool maybeNumber = maybeInt32 || maybeDouble; -#ifdef ENABLE_BIGINT bool maybeBigInt = lir->mir()->mightBeType(MIRType::BigInt); -#endif - int checks = int(maybeNumber) + IF_BIGINT(int(maybeBigInt), 0); + int checks = int(maybeNumber) + int(maybeBigInt); OutOfLineCode* ool = oolCallVM(ToNumericInfo, lir, ArgList(operand), StoreValueTo(output)); @@ -4031,14 +4025,12 @@ void CodeGenerator::visitToNumeric(LToNumeric* lir) { Label* target = checks ? &done : ool->entry(); masm.branchTestNumber(cond, operand, target); } -#ifdef ENABLE_BIGINT if (maybeBigInt) { checks--; Condition cond = checks ? Equal : NotEqual; Label* target = checks ? &done : ool->entry(); masm.branchTestBigInt(cond, operand, target); } -#endif MOZ_ASSERT(checks == 0); masm.bind(&done); @@ -5676,7 +5668,7 @@ void CodeGenerator::emitAssertGCThingResult(Register input, MIRType type, const TemporaryTypeSet* typeset) { MOZ_ASSERT(type == MIRType::Object || type == MIRType::ObjectOrNull || type == MIRType::String || type == MIRType::Symbol || - IF_BIGINT(type == MIRType::BigInt, false)); + type == MIRType::BigInt); AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All()); regs.take(input); @@ -5734,11 +5726,9 @@ void CodeGenerator::emitAssertGCThingResult(Register input, MIRType type, case MIRType::Symbol: callee = JS_FUNC_TO_DATA_PTR(void*, AssertValidSymbolPtr); break; -# ifdef ENABLE_BIGINT case MIRType::BigInt: callee = JS_FUNC_TO_DATA_PTR(void*, AssertValidBigIntPtr); break; -# endif default: MOZ_CRASH(); } @@ -5853,9 +5843,7 @@ void CodeGenerator::emitDebugResultChecks(LInstruction* ins) { case MIRType::ObjectOrNull: case MIRType::String: case MIRType::Symbol: -# ifdef ENABLE_BIGINT case MIRType::BigInt: -# endif emitGCThingResultChecks(ins, mir); break; case MIRType::Value: @@ -11254,14 +11242,12 @@ void CodeGenerator::visitTypeOfV(LTypeOfV* lir) { bool testNull = input->mightBeType(MIRType::Null); bool testString = input->mightBeType(MIRType::String); bool testSymbol = input->mightBeType(MIRType::Symbol); -#ifdef ENABLE_BIGINT bool testBigInt = input->mightBeType(MIRType::BigInt); -#endif unsigned numTests = unsigned(testObject) + unsigned(testNumber) + unsigned(testBoolean) + unsigned(testUndefined) + unsigned(testNull) + unsigned(testString) + - unsigned(testSymbol) + unsigned(IF_BIGINT(testBigInt, 0)); + unsigned(testSymbol) + unsigned(testBigInt); MOZ_ASSERT_IF(!input->emptyResultTypeSet(), numTests > 0); @@ -11372,7 +11358,6 @@ void CodeGenerator::visitTypeOfV(LTypeOfV* lir) { numTests--; } -#ifdef ENABLE_BIGINT if (testBigInt) { Label notBigInt; if (numTests > 1) { @@ -11385,7 +11370,6 @@ void CodeGenerator::visitTypeOfV(LTypeOfV* lir) { masm.bind(¬BigInt); numTests--; } -#endif MOZ_ASSERT(numTests == 0); diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 5aa3b1d87ea6..f07dfef663b6 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -2345,7 +2345,7 @@ static bool CanCompareRegExp(MCompare* compare, MDefinition* def) { value->mightBeType(MIRType::Double) || value->mightBeType(MIRType::Float32) || value->mightBeType(MIRType::Symbol) || - IF_BIGINT(value->mightBeType(MIRType::BigInt), false)) { + value->mightBeType(MIRType::BigInt)) { return false; } @@ -3177,9 +3177,7 @@ static bool IsResumableMIRType(MIRType type) { case MIRType::Float32: case MIRType::String: case MIRType::Symbol: -# ifdef ENABLE_BIGINT case MIRType::BigInt: -# endif case MIRType::Object: case MIRType::MagicOptimizedArguments: case MIRType::MagicOptimizedOut: diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 30cd6833d3e7..55ae1594b120 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -717,11 +717,9 @@ AbortReasonOr IonBuilder::analyzeNewLoopTypes( case JSOP_DEC: type = inspector->expectedResultType(last); break; -#ifdef ENABLE_BIGINT case JSOP_BIGINT: type = MIRType::BigInt; break; -#endif default: break; } @@ -1341,9 +1339,7 @@ AbortReasonOr IonBuilder::addOsrValueTypeBarrier( case MIRType::Double: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif case MIRType::Object: if (type != def->type()) { MUnbox* unbox = MUnbox::New(alloc(), def, type, MUnbox::Fallible); @@ -1936,9 +1932,7 @@ AbortReasonOr IonBuilder::inspectOpcode(JSOp op) { return jsop_compare(op); case JSOP_DOUBLE: -#ifdef ENABLE_BIGINT case JSOP_BIGINT: -#endif pushConstant(info().getConst(pc)); return Ok(); @@ -2809,13 +2803,9 @@ AbortReasonOr IonBuilder::improveTypesAtTypeOfCompare(MCompare* ins, filter.addType(TypeSet::StringType(), alloc_->lifoAlloc()); } else if (constant->toString() == TypeName(JSTYPE_SYMBOL, names)) { filter.addType(TypeSet::SymbolType(), alloc_->lifoAlloc()); - } -#ifdef ENABLE_BIGINT - else if (constant->toString() == TypeName(JSTYPE_BIGINT, names)) { + } else if (constant->toString() == TypeName(JSTYPE_BIGINT, names)) { filter.addType(TypeSet::BigIntType(), alloc_->lifoAlloc()); - } -#endif - else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) { + } else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) { filter.addType(TypeSet::NullType(), alloc_->lifoAlloc()); if (trueBranch) { filter.addType(TypeSet::AnyObjectType(), alloc_->lifoAlloc()); @@ -3059,10 +3049,8 @@ AbortReasonOr IonBuilder::improveTypesAtTest(MDefinition* ins, alloc_->lifoAlloc()); // ToBoolean(0.0) == false base.addType(TypeSet::StringType(), alloc_->lifoAlloc()); // ToBoolean("") == false -#ifdef ENABLE_BIGINT base.addType(TypeSet::BigIntType(), alloc_->lifoAlloc()); // ToBoolean(0n) == false -#endif // If the typeset does emulate undefined, then we cannot filter out // objects. @@ -3371,7 +3359,7 @@ AbortReasonOr IonBuilder::bitnotTrySpecialized(bool* emitted, if (input->mightBeType(MIRType::Object) || input->mightBeType(MIRType::Symbol) || - IF_BIGINT(input->mightBeType(MIRType::BigInt), false)) { + input->mightBeType(MIRType::BigInt)) { return Ok(); } @@ -3825,9 +3813,7 @@ AbortReasonOr IonBuilder::jsop_tonumeric() { types->addType(TypeSet::Int32Type(), lifoAlloc); types->addType(TypeSet::DoubleType(), lifoAlloc); -#ifdef ENABLE_BIGINT types->addType(TypeSet::BigIntType(), lifoAlloc); -#endif if (peeked->type() == MIRType::Value && peeked->resultTypeSet() && peeked->resultTypeSet()->isSubset(types)) { @@ -6270,7 +6256,7 @@ static bool ObjectOrSimplePrimitive(MDefinition* op) { // Return true if op is either undefined/null/boolean/int32/symbol or an // object. return !op->mightBeType(MIRType::String) && - IF_BIGINT(!op->mightBeType(MIRType::BigInt), true) && + !op->mightBeType(MIRType::BigInt) && !op->mightBeType(MIRType::Double) && !op->mightBeType(MIRType::Float32) && !op->mightBeType(MIRType::MagicOptimizedArguments) && @@ -7521,11 +7507,9 @@ JSObject* IonBuilder::testSingletonPropertyTypes(MDefinition* obj, jsid id) { key = JSProto_Symbol; break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: key = JSProto_BigInt; break; -#endif case MIRType::Int32: case MIRType::Double: diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h index bcc18088bff9..152a13c51d83 100644 --- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -124,9 +124,7 @@ enum BailoutKind { Bailout_NonObjectInput, Bailout_NonStringInput, Bailout_NonSymbolInput, -#ifdef ENABLE_BIGINT Bailout_NonBigIntInput, -#endif // Atomic operations require shared memory, bail out if the typed array // maps unshared memory. @@ -226,10 +224,8 @@ inline const char* BailoutKindString(BailoutKind kind) { return "Bailout_NonStringInput"; case Bailout_NonSymbolInput: return "Bailout_NonSymbolInput"; -#ifdef ENABLE_BIGINT case Bailout_NonBigIntInput: return "Bailout_NonBigIntInput"; -#endif case Bailout_NonSharedTypedArrayInput: return "Bailout_NonSharedTypedArrayInput"; case Bailout_Debugger: @@ -448,9 +444,7 @@ enum class MIRType : uint8_t { // Types above have trivial conversion to a number. String, Symbol, -#ifdef ENABLE_BIGINT BigInt, -#endif // Types above are primitive (including undefined and null). Object, MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value. @@ -499,10 +493,8 @@ static inline MIRType MIRTypeFromValueType(JSValueType type) { return MIRType::String; case JSVAL_TYPE_SYMBOL: return MIRType::Symbol; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return MIRType::BigInt; -#endif case JSVAL_TYPE_BOOLEAN: return MIRType::Boolean; case JSVAL_TYPE_NULL: @@ -533,10 +525,8 @@ static inline JSValueType ValueTypeFromMIRType(MIRType type) { return JSVAL_TYPE_STRING; case MIRType::Symbol: return JSVAL_TYPE_SYMBOL; -#ifdef ENABLE_BIGINT case MIRType::BigInt: return JSVAL_TYPE_BIGINT; -#endif case MIRType::MagicOptimizedArguments: case MIRType::MagicOptimizedOut: case MIRType::MagicHole: @@ -591,10 +581,8 @@ static inline const char* StringFromMIRType(MIRType type) { return "String"; case MIRType::Symbol: return "Symbol"; -#ifdef ENABLE_BIGINT case MIRType::BigInt: return "BigInt"; -#endif case MIRType::Object: return "Object"; case MIRType::MagicOptimizedArguments: @@ -657,7 +645,7 @@ static inline bool IsNumberType(MIRType type) { } static inline bool IsNumericType(MIRType type) { - return IsNumberType(type) || IF_BIGINT(type == MIRType::BigInt, false); + return IsNumberType(type) || type == MIRType::BigInt; } static inline bool IsTypeRepresentableAsDouble(MIRType type) { diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index f21585669921..61b67ebb24ea 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -1500,11 +1500,9 @@ static Value FromSymbolPayload(uintptr_t payload) { return SymbolValue(reinterpret_cast(payload)); } -#ifdef ENABLE_BIGINT static Value FromBigIntPayload(uintptr_t payload) { return BigIntValue(reinterpret_cast(payload)); } -#endif static Value FromTypedPayload(JSValueType type, uintptr_t payload) { switch (type) { @@ -1516,10 +1514,8 @@ static Value FromTypedPayload(JSValueType type, uintptr_t payload) { return FromStringPayload(payload); case JSVAL_TYPE_SYMBOL: return FromSymbolPayload(payload); -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return FromBigIntPayload(payload); -#endif case JSVAL_TYPE_OBJECT: return FromObjectPayload(payload); default: @@ -1616,10 +1612,8 @@ Value SnapshotIterator::allocationValue(const RValueAllocation& alloc, return FromStringPayload(fromStack(alloc.stackOffset2())); case JSVAL_TYPE_SYMBOL: return FromSymbolPayload(fromStack(alloc.stackOffset2())); -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return FromBigIntPayload(fromStack(alloc.stackOffset2())); -#endif case JSVAL_TYPE_OBJECT: return FromObjectPayload(fromStack(alloc.stackOffset2())); default: @@ -1741,9 +1735,7 @@ void SnapshotIterator::writeAllocationValuePayload( break; case JSVAL_TYPE_STRING: case JSVAL_TYPE_SYMBOL: -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: -#endif case JSVAL_TYPE_OBJECT: WriteFrameSlot(fp_, alloc.stackOffset2(), uintptr_t(v.toGCThing())); break; diff --git a/js/src/jit/LIR.h b/js/src/jit/LIR.h index 49737de73423..a4f3835043c6 100644 --- a/js/src/jit/LIR.h +++ b/js/src/jit/LIR.h @@ -525,9 +525,7 @@ class LDefinition { return LDefinition::INT32; case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif case MIRType::Object: case MIRType::ObjectOrNull: return LDefinition::OBJECT; diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 413cca345e41..e917af4d80b6 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -606,11 +606,9 @@ void LIRGenerator::visitTest(MTest* test) { // TestPolicy). MOZ_ASSERT(opd->type() != MIRType::String); -#ifdef ENABLE_BIGINT // BigInt is boxed in type analysis. MOZ_ASSERT(opd->type() != MIRType::BigInt, "BigInt should be boxed by TestPolicy"); -#endif // Testing a constant. if (MConstant* constant = opd->maybeConstantValue()) { @@ -2112,9 +2110,7 @@ void LIRGenerator::visitToNumberInt32(MToNumberInt32* convert) { case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif case MIRType::Object: case MIRType::Undefined: // Objects might be effectful. Symbols and BigInts throw. Undefined @@ -2921,10 +2917,8 @@ void LIRGenerator::visitNot(MNot* ins) { // String is converted to length of string in the type analysis phase (see // TestPolicy). MOZ_ASSERT(op->type() != MIRType::String); -#ifdef ENABLE_BIGINT MOZ_ASSERT(op->type() != MIRType::BigInt, "BigInt should be boxed by TestPolicy"); -#endif // - boolean: x xor 1 // - int32: LCompare(x, 0) @@ -4720,11 +4714,9 @@ void LIRGenerator::visitConstant(MConstant* ins) { case MIRType::Symbol: define(new (alloc()) LPointer(ins->toSymbol()), ins); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: define(new (alloc()) LPointer(ins->toBigInt()), ins); break; -#endif case MIRType::Object: define(new (alloc()) LPointer(&ins->toObject()), ins); break; diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 1eb89c11c04b..80f379e7b7b3 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -2139,7 +2139,7 @@ IonBuilder::InliningResult IonBuilder::inlineStrFromCharCode( // don't try to inline String.fromCharCode() for these value types. if (codeUnit->mightBeType(MIRType::Object) || codeUnit->mightBeType(MIRType::Symbol) || - IF_BIGINT(codeUnit->mightBeType(MIRType::BigInt), false)) { + codeUnit->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } @@ -3627,7 +3627,7 @@ IonBuilder::InliningResult IonBuilder::inlineToInteger(CallInfo& callInfo) { if (input->mightBeType(MIRType::Object) || input->mightBeType(MIRType::String) || input->mightBeType(MIRType::Symbol) || - IF_BIGINT(input->mightBeType(MIRType::BigInt), false) || + input->mightBeType(MIRType::BigInt) || input->mightBeType(MIRType::Undefined) || input->mightBeMagicType()) { return InliningStatus_NotInlined; } @@ -3753,14 +3753,14 @@ IonBuilder::InliningResult IonBuilder::inlineAtomicsCompareExchange( MDefinition* oldval = callInfo.getArg(2); if (oldval->mightBeType(MIRType::Object) || oldval->mightBeType(MIRType::Symbol) || - IF_BIGINT(oldval->mightBeType(MIRType::BigInt), false)) { + oldval->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } MDefinition* newval = callInfo.getArg(3); if (newval->mightBeType(MIRType::Object) || newval->mightBeType(MIRType::Symbol) || - IF_BIGINT(newval->mightBeType(MIRType::BigInt), false)) { + newval->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } @@ -3801,7 +3801,7 @@ IonBuilder::InliningResult IonBuilder::inlineAtomicsExchange( MDefinition* value = callInfo.getArg(2); if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) || - IF_BIGINT(value->mightBeType(MIRType::BigInt), false)) { + value->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } @@ -3887,7 +3887,7 @@ IonBuilder::InliningResult IonBuilder::inlineAtomicsStore(CallInfo& callInfo) { if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) || - IF_BIGINT(value->mightBeType(MIRType::BigInt), false)) { + value->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } @@ -3933,7 +3933,7 @@ IonBuilder::InliningResult IonBuilder::inlineAtomicsBinop( MDefinition* value = callInfo.getArg(2); if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) || - IF_BIGINT(value->mightBeType(MIRType::BigInt), false)) { + value->mightBeType(MIRType::BigInt)) { return InliningStatus_NotInlined; } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index d127c75ce457..69e82bfa4af2 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -939,11 +939,9 @@ MConstant::MConstant(TempAllocator& alloc, const js::Value& vp, case MIRType::Symbol: payload_.sym = vp.toSymbol(); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: payload_.bi = vp.toBigInt(); break; -#endif case MIRType::Object: payload_.obj = &vp.toObject(); // Create a singleton type set for the object. This isn't necessary for @@ -1021,9 +1019,7 @@ void MConstant::assertInitializedPayload() const { case MIRType::String: case MIRType::Object: case MIRType::Symbol: -# ifdef ENABLE_BIGINT case MIRType::BigInt: -# endif # if MOZ_LITTLE_ENDIAN MOZ_ASSERT_IF(JS_BITS_PER_WORD == 32, (payload_.asBits >> 32) == 0); # else @@ -1115,11 +1111,9 @@ void MConstant::printOpcode(GenericPrinter& out) const { case MIRType::Symbol: out.printf("symbol at %p", (void*)toSymbol()); break; -# ifdef ENABLE_BIGINT case MIRType::BigInt: out.printf("BigInt at %p", (void*)toBigInt()); break; -# endif case MIRType::String: out.printf("string %p", (void*)toString()); break; @@ -1181,10 +1175,8 @@ Value MConstant::toJSValue() const { return StringValue(toString()); case MIRType::Symbol: return SymbolValue(toSymbol()); -#ifdef ENABLE_BIGINT case MIRType::BigInt: return BigIntValue(toBigInt()); -#endif case MIRType::Object: return ObjectValue(toObject()); case MIRType::MagicOptimizedArguments: @@ -1226,11 +1218,9 @@ bool MConstant::valueToBoolean(bool* res) const { case MIRType::Symbol: *res = true; return true; -#ifdef ENABLE_BIGINT case MIRType::BigInt: *res = !toBigInt()->isZero(); return true; -#endif case MIRType::String: *res = toString()->length() != 0; return true; @@ -1772,11 +1762,9 @@ void MUnbox::printOpcode(GenericPrinter& out) const { case MIRType::Symbol: out.printf("to Symbol"); break; -# ifdef ENABLE_BIGINT case MIRType::BigInt: out.printf("to BigInt"); break; -# endif case MIRType::Object: out.printf("to Object"); break; @@ -2255,9 +2243,7 @@ bool jit::TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes) { case MIRType::Float32: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif case MIRType::MagicOptimizedArguments: return types->hasType( TypeSet::PrimitiveType(ValueTypeFromMIRType(input))); @@ -2518,10 +2504,10 @@ MDefinition* MBinaryBitwiseInstruction::foldUnnecessaryBitop() { void MBinaryBitwiseInstruction::infer(BaselineInspector*, jsbytecode*) { if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(0)->mightBeType(MIRType::Symbol) || - IF_BIGINT(getOperand(0)->mightBeType(MIRType::BigInt), false) || + getOperand(0)->mightBeType(MIRType::BigInt) || getOperand(1)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Symbol) || - IF_BIGINT(getOperand(1)->mightBeType(MIRType::BigInt), false)) { + getOperand(1)->mightBeType(MIRType::BigInt)) { specialization_ = MIRType::None; setResultType(MIRType::Value); } else { @@ -2546,8 +2532,8 @@ void MShiftInstruction::infer(BaselineInspector*, jsbytecode*) { getOperand(1)->mightBeType(MIRType::Object) || getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol) || - IF_BIGINT(getOperand(0)->mightBeType(MIRType::BigInt), false) || - IF_BIGINT(getOperand(1)->mightBeType(MIRType::BigInt), false)) { + getOperand(0)->mightBeType(MIRType::BigInt) || + getOperand(1)->mightBeType(MIRType::BigInt)) { specialization_ = MIRType::None; setResultType(MIRType::Value); } else { @@ -2561,8 +2547,8 @@ void MUrsh::infer(BaselineInspector* inspector, jsbytecode* pc) { getOperand(1)->mightBeType(MIRType::Object) || getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol) || - IF_BIGINT(getOperand(0)->mightBeType(MIRType::BigInt), false) || - IF_BIGINT(getOperand(1)->mightBeType(MIRType::BigInt), false)) { + getOperand(0)->mightBeType(MIRType::BigInt) || + getOperand(1)->mightBeType(MIRType::BigInt)) { specialization_ = MIRType::None; setResultType(MIRType::Value); return; @@ -3603,11 +3589,9 @@ MDefinition* MTypeOf::foldsTo(TempAllocator& alloc) { case MIRType::Symbol: type = JSTYPE_SYMBOL; break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: type = JSTYPE_BIGINT; break; -#endif case MIRType::Null: type = JSTYPE_OBJECT; break; @@ -4225,16 +4209,12 @@ bool MCompare::tryFoldTypeOf(bool* result) { *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE); return true; } - } -#ifdef ENABLE_BIGINT - else if (constant->toString() == TypeName(JSTYPE_BIGINT, names)) { + } else if (constant->toString() == TypeName(JSTYPE_BIGINT, names)) { if (!typeOf->input()->mightBeType(MIRType::BigInt)) { *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE); return true; } - } -#endif - else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) { + } else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) { if (!typeOf->input()->mightBeType(MIRType::Object) && !typeOf->input()->mightBeType(MIRType::Null)) { *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE); @@ -5481,10 +5461,8 @@ bool MConstant::appendRoots(MRootList& roots) const { return roots.append(toString()); case MIRType::Symbol: return roots.append(toSymbol()); -#ifdef ENABLE_BIGINT case MIRType::BigInt: return roots.append(toBigInt()); -#endif case MIRType::Object: return roots.append(&toObject()); case MIRType::Undefined: @@ -6222,10 +6200,7 @@ static bool TryAddTypeBarrierForWrite(TempAllocator& alloc, case MIRType::Double: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT - case MIRType::BigInt: -#endif - { + case MIRType::BigInt: { // The property is a particular primitive type, guard by unboxing the // value before the write. if (!(*pvalue)->mightBeType(propertyType)) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 674f87c60e81..7d59c5370618 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -890,7 +890,7 @@ static inline bool SimpleArithOperand(MDefinition* op) { return !op->emptyResultTypeSet() && !op->mightBeType(MIRType::Object) && !op->mightBeType(MIRType::String) && !op->mightBeType(MIRType::Symbol) && - IF_BIGINT(!op->mightBeType(MIRType::BigInt), true) && + !op->mightBeType(MIRType::BigInt) && !op->mightBeType(MIRType::MagicOptimizedArguments) && !op->mightBeType(MIRType::MagicHole) && !op->mightBeType(MIRType::MagicIsConstructing); @@ -1390,9 +1390,7 @@ class MConstant : public MNullaryInstruction { double d; JSString* str; JS::Symbol* sym; -#ifdef ENABLE_BIGINT BigInt* bi; -#endif JSObject* obj; uint64_t asBits; }; @@ -1510,12 +1508,10 @@ class MConstant : public MNullaryInstruction { MOZ_ASSERT(type() == MIRType::Symbol); return payload_.sym; } -#ifdef ENABLE_BIGINT BigInt* toBigInt() const { MOZ_ASSERT(type() == MIRType::BigInt); return payload_.bi; } -#endif JSObject& toObject() const { MOZ_ASSERT(type() == MIRType::Object); return *payload_.obj; @@ -3353,8 +3349,7 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data { MOZ_ASSERT(type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || - type == MIRType::Symbol || - IF_BIGINT(type == MIRType::BigInt, false) || + type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object); TemporaryTypeSet* resultSet = ins->resultTypeSet(); @@ -3396,11 +3391,9 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data { case MIRType::Symbol: kind = Bailout_NonSymbolInput; break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: kind = Bailout_NonBigIntInput; break; -#endif case MIRType::Object: kind = Bailout_NonObjectInput; break; @@ -3717,7 +3710,7 @@ class MToDouble : public MToFPInstruction { // ToNumber(symbol) and ToNumber(bigint) throw. if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) || - IF_BIGINT(def->mightBeType(MIRType::BigInt), false)) { + def->mightBeType(MIRType::BigInt)) { setGuard(); } } @@ -3758,11 +3751,9 @@ class MToDouble : public MToFPInstruction { if (input()->type() == MIRType::Symbol) { return false; } -#ifdef ENABLE_BIGINT if (input()->type() == MIRType::BigInt) { return false; } -#endif return true; } @@ -3787,7 +3778,7 @@ class MToFloat32 : public MToFPInstruction { // ToNumber(symbol) and ToNumber(BigInt) throw. if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) || - IF_BIGINT(def->mightBeType(MIRType::BigInt), false)) { + def->mightBeType(MIRType::BigInt)) { setGuard(); } } @@ -4079,7 +4070,7 @@ class MToNumberInt32 : public MUnaryInstruction, public ToInt32Policy::Data { // ToNumber(symbol) and ToNumber(BigInt) throw. if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) || - IF_BIGINT(def->mightBeType(MIRType::BigInt), false)) { + def->mightBeType(MIRType::BigInt)) { setGuard(); } } @@ -4135,7 +4126,7 @@ class MTruncateToInt32 : public MUnaryInstruction, public ToInt32Policy::Data { // ToInt32(symbol) and ToInt32(BigInt) throw. if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) || - IF_BIGINT(def->mightBeType(MIRType::BigInt), false)) { + def->mightBeType(MIRType::BigInt)) { setGuard(); } } @@ -4178,7 +4169,7 @@ class MToString : public MUnaryInstruction, public ToStringPolicy::Data { // those cases and run side-effects in baseline instead. if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) || - IF_BIGINT(def->mightBeType(MIRType::BigInt), false)) { + def->mightBeType(MIRType::BigInt)) { setGuard(); } } diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 2c69d1c6ca9b..172c09716500 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -65,11 +65,9 @@ static void EmitTypeCheck(MacroAssembler& masm, Assembler::Condition cond, case JSVAL_TYPE_SYMBOL: masm.branchTestSymbol(cond, src, label); break; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: masm.branchTestBigInt(cond, src, label); break; -#endif case JSVAL_TYPE_NULL: masm.branchTestNull(cond, src, label); break; @@ -104,10 +102,7 @@ void MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, Label matched; TypeSet::Type tests[] = {TypeSet::Int32Type(), TypeSet::UndefinedType(), TypeSet::BooleanType(), TypeSet::StringType(), - TypeSet::SymbolType(), -#ifdef ENABLE_BIGINT - TypeSet::BigIntType(), -#endif + TypeSet::SymbolType(), TypeSet::BigIntType(), TypeSet::NullType(), TypeSet::MagicArgType(), TypeSet::AnyObjectType()}; @@ -3402,11 +3397,9 @@ void MacroAssembler::maybeBranchTestType(MIRType type, MDefinition* maybeDef, case MIRType::Symbol: branchTestSymbol(Equal, tag, label); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: branchTestBigInt(Equal, tag, label); break; -#endif case MIRType::Object: branchTestObject(Equal, tag, label); break; diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 6949317f05bb..07eeefccbc5e 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -1432,10 +1432,8 @@ class MacroAssembler : public MacroAssemblerSpecific { Label* label) PER_SHARED_ARCH; inline void branchTestSymbol(Condition cond, Register tag, Label* label) PER_SHARED_ARCH; -#ifdef ENABLE_BIGINT inline void branchTestBigInt(Condition cond, Register tag, Label* label) PER_SHARED_ARCH; -#endif inline void branchTestNull(Condition cond, Register tag, Label* label) PER_SHARED_ARCH; inline void branchTestObject(Condition cond, Register tag, @@ -1499,13 +1497,11 @@ class MacroAssembler : public MacroAssemblerSpecific { Label* label) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); -#ifdef ENABLE_BIGINT inline void branchTestBigInt(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH; inline void branchTestBigInt(Condition cond, const ValueOperand& value, Label* label) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); -#endif inline void branchTestNull(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH; @@ -1563,11 +1559,9 @@ class MacroAssembler : public MacroAssemblerSpecific { inline void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); -#ifdef ENABLE_BIGINT inline void branchTestBigIntTruthy(bool truthy, const ValueOperand& value, Label* label) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); -#endif // Create an unconditional branch to the address given as argument. inline void branchToComputedAddress(const BaseIndex& address) PER_ARCH; @@ -1605,11 +1599,9 @@ class MacroAssembler : public MacroAssemblerSpecific { template inline void branchTestSymbolImpl(Condition cond, const T& t, Label* label) DEFINED_ON(arm, arm64, x86_shared); -#ifdef ENABLE_BIGINT template inline void branchTestBigIntImpl(Condition cond, const T& t, Label* label) DEFINED_ON(arm, arm64, x86_shared); -#endif template inline void branchTestNullImpl(Condition cond, const T& t, Label* label) DEFINED_ON(arm, arm64, x86_shared); diff --git a/js/src/jit/Snapshots.cpp b/js/src/jit/Snapshots.cpp index aa05e4aa0533..afd2a49c317b 100644 --- a/js/src/jit/Snapshots.cpp +++ b/js/src/jit/Snapshots.cpp @@ -343,10 +343,8 @@ static const char* ValTypeToString(JSValueType type) { return "string"; case JSVAL_TYPE_SYMBOL: return "symbol"; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return "BigInt"; -#endif case JSVAL_TYPE_BOOLEAN: return "boolean"; case JSVAL_TYPE_OBJECT: diff --git a/js/src/jit/TypePolicy.cpp b/js/src/jit/TypePolicy.cpp index b4704962d0ab..f69a0ac0ff86 100644 --- a/js/src/jit/TypePolicy.cpp +++ b/js/src/jit/TypePolicy.cpp @@ -775,9 +775,7 @@ bool ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc, case MIRType::Object: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif // Objects might be effectful. Symbols and BigInts give TypeError. break; default: @@ -830,9 +828,7 @@ bool ToInt32Policy::staticAdjustInputs(TempAllocator& alloc, case MIRType::Object: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif // Objects might be effectful. Symbols and BigInts give TypeError. break; default: @@ -850,7 +846,7 @@ bool ToStringPolicy::staticAdjustInputs(TempAllocator& alloc, MIRType type = ins->getOperand(0)->type(); if (type == MIRType::Object || type == MIRType::Symbol || - IF_BIGINT(type == MIRType::BigInt, false)) { + type == MIRType::BigInt) { ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0))); return true; } @@ -969,9 +965,7 @@ bool StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc, case MIRType::Object: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif value = BoxAt(alloc, ins, value); break; default: diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index d141f553447c..b1a4510dea96 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -1263,7 +1263,6 @@ void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym) { MOZ_ASSERT(sym->getAllocKind() == gc::AllocKind::SYMBOL); } -#ifdef ENABLE_BIGINT void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi) { AutoUnsafeCallWithABI unsafe; // FIXME: check runtime? @@ -1272,7 +1271,6 @@ void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi) { MOZ_ASSERT(bi->isTenured()); MOZ_ASSERT(bi->getAllocKind() == gc::AllocKind::BIGINT); } -#endif void AssertValidValue(JSContext* cx, Value* v) { AutoUnsafeCallWithABI unsafe; @@ -1283,11 +1281,9 @@ void AssertValidValue(JSContext* cx, Value* v) { } else if (v->isSymbol()) { AssertValidSymbolPtr(cx, v->toSymbol()); } -#ifdef ENABLE_BIGINT else if (v->isBigInt()) { AssertValidBigIntPtr(cx, v->toBigInt()); } -#endif } bool ObjectIsCallable(JSObject* obj) { @@ -1873,27 +1869,23 @@ const VMFunction GetSparseElementHelperInfo = FunctionInfo(GetSparseElementHelper, "getSparseElementHelper"); -#ifdef ENABLE_BIGINT -template -#endif +static bool DoToNumber(JSContext* cx, HandleValue arg, + MutableHandleValue ret) { + ret.set(arg); + return ToNumber(cx, ret); +} + static bool DoToNumeric(JSContext* cx, HandleValue arg, MutableHandleValue ret) { ret.set(arg); -#ifdef ENABLE_BIGINT - if (allowBigInt) { - return ToNumeric(cx, ret); - } -#endif - return ToNumber(cx, ret); + return ToNumeric(cx, ret); } typedef bool (*ToNumericFn)(JSContext*, HandleValue, MutableHandleValue); const VMFunction ToNumberInfo = - FunctionInfo(DoToNumeric, "ToNumber"); -#ifdef ENABLE_BIGINT + FunctionInfo(DoToNumber, "ToNumber"); const VMFunction ToNumericInfo = - FunctionInfo(DoToNumeric, "ToNumeric"); -#endif + FunctionInfo(DoToNumeric, "ToNumeric"); } // namespace jit } // namespace js diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index 08efa4584589..9c66d023fa79 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -1092,9 +1092,7 @@ void AssertValidObjectPtr(JSContext* cx, JSObject* obj); void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj); void AssertValidStringPtr(JSContext* cx, JSString* str); void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym); -#ifdef ENABLE_BIGINT void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi); -#endif void AssertValidValue(JSContext* cx, Value* v); void MarkValueFromJit(JSRuntime* rt, Value* vp); @@ -1207,9 +1205,7 @@ extern const VMFunction AddOrUpdateSparseElementHelperInfo; extern const VMFunction GetSparseElementHelperInfo; extern const VMFunction ToNumberInfo; -#ifdef ENABLE_BIGINT extern const VMFunction ToNumericInfo; -#endif // TailCall VMFunctions extern const VMFunction DoConcatStringObjectInfo; diff --git a/js/src/jit/arm/MacroAssembler-arm-inl.h b/js/src/jit/arm/MacroAssembler-arm-inl.h index 01aa689efaa1..dbafa632b2a0 100644 --- a/js/src/jit/arm/MacroAssembler-arm-inl.h +++ b/js/src/jit/arm/MacroAssembler-arm-inl.h @@ -1701,7 +1701,6 @@ void MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, ma_b(label, c); } -#ifdef ENABLE_BIGINT void MacroAssembler::branchTestBigInt(Condition cond, Register tag, Label* label) { branchTestBigIntImpl(cond, tag, label); @@ -1730,7 +1729,6 @@ void MacroAssembler::branchTestBigIntTruthy(bool truthy, Condition c = testBigIntTruthy(truthy, value); ma_b(label, c); } -#endif void MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label) { diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 3969b7d561be..f0586208099f 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -2419,12 +2419,10 @@ Assembler::Condition MacroAssemblerARMCompat::testSymbol( return testSymbol(cond, value.typeReg()); } -#ifdef ENABLE_BIGINT Assembler::Condition MacroAssemblerARMCompat::testBigInt( Assembler::Condition cond, const ValueOperand& value) { return testBigInt(cond, value.typeReg()); } -#endif Assembler::Condition MacroAssemblerARMCompat::testObject( Assembler::Condition cond, const ValueOperand& value) { @@ -2489,14 +2487,12 @@ Assembler::Condition MacroAssemblerARMCompat::testSymbol( return cond; } -#ifdef ENABLE_BIGINT Assembler::Condition MacroAssemblerARMCompat::testBigInt( Assembler::Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); ma_cmp(tag, ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Assembler::Condition MacroAssemblerARMCompat::testObject( Assembler::Condition cond, Register tag) { @@ -2594,7 +2590,6 @@ Assembler::Condition MacroAssemblerARMCompat::testSymbol( return testSymbol(cond, tag); } -#ifdef ENABLE_BIGINT Assembler::Condition MacroAssemblerARMCompat::testBigInt( Condition cond, const Address& address) { MOZ_ASSERT(cond == Equal || cond == NotEqual); @@ -2602,7 +2597,6 @@ Assembler::Condition MacroAssemblerARMCompat::testBigInt( Register tag = extractTag(address, scratch); return testBigInt(cond, tag); } -#endif Assembler::Condition MacroAssemblerARMCompat::testObject( Condition cond, const Address& address) { @@ -2680,7 +2674,6 @@ Assembler::Condition MacroAssemblerARMCompat::testSymbol(Condition cond, return cond; } -#ifdef ENABLE_BIGINT Assembler::Condition MacroAssemblerARMCompat::testBigInt(Condition cond, const BaseIndex& src) { MOZ_ASSERT(cond == Equal || cond == NotEqual); @@ -2689,7 +2682,6 @@ Assembler::Condition MacroAssemblerARMCompat::testBigInt(Condition cond, ma_cmp(tag, ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Assembler::Condition MacroAssemblerARMCompat::testInt32(Condition cond, const BaseIndex& src) { @@ -3441,7 +3433,6 @@ Assembler::Condition MacroAssemblerARMCompat::testStringTruthy( return truthy ? Assembler::NotEqual : Assembler::Equal; } -#ifdef ENABLE_BIGINT Assembler::Condition MacroAssemblerARMCompat::testBigIntTruthy( bool truthy, const ValueOperand& value) { Register bi = value.payloadReg(); @@ -3453,7 +3444,6 @@ Assembler::Condition MacroAssemblerARMCompat::testBigIntTruthy( as_cmp(scratch, Imm8(0)); return truthy ? Assembler::NotEqual : Assembler::Equal; } -#endif void MacroAssemblerARMCompat::floor(FloatRegister input, Register output, Label* bail) { diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 56b52ab43010..2143ae1f67e1 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -766,9 +766,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { Condition testUndefined(Condition cond, const ValueOperand& value); Condition testString(Condition cond, const ValueOperand& value); Condition testSymbol(Condition cond, const ValueOperand& value); -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const ValueOperand& value); -#endif Condition testObject(Condition cond, const ValueOperand& value); Condition testNumber(Condition cond, const ValueOperand& value); Condition testMagic(Condition cond, const ValueOperand& value); @@ -782,9 +780,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { Condition testUndefined(Condition cond, Register tag); Condition testString(Condition cond, Register tag); Condition testSymbol(Condition cond, Register tag); -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, Register tag); -#endif Condition testObject(Condition cond, Register tag); Condition testDouble(Condition cond, Register tag); Condition testNumber(Condition cond, Register tag); @@ -800,9 +796,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { Condition testUndefined(Condition cond, const Address& address); Condition testString(Condition cond, const Address& address); Condition testSymbol(Condition cond, const Address& address); -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const Address& address); -#endif Condition testObject(Condition cond, const Address& address); Condition testNumber(Condition cond, const Address& address); @@ -811,9 +805,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { Condition testBoolean(Condition cond, const BaseIndex& src); Condition testString(Condition cond, const BaseIndex& src); Condition testSymbol(Condition cond, const BaseIndex& src); -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const BaseIndex& src); -#endif Condition testInt32(Condition cond, const BaseIndex& src); Condition testObject(Condition cond, const BaseIndex& src); Condition testDouble(Condition cond, const BaseIndex& src); @@ -849,14 +841,12 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } void unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } -#endif void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT); } @@ -925,9 +915,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM { Condition testBooleanTruthy(bool truthy, const ValueOperand& operand); Condition testDoubleTruthy(bool truthy, FloatRegister reg); Condition testStringTruthy(bool truthy, const ValueOperand& value); -#ifdef ENABLE_BIGINT Condition testBigIntTruthy(bool truthy, const ValueOperand& value); -#endif void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest); void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest); diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp index 0ca3aa45be6b..bf152db7cb20 100644 --- a/js/src/jit/arm64/CodeGenerator-arm64.cpp +++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp @@ -1252,11 +1252,9 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: cond = masm.testSymbol(Assembler::NotEqual, value); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: cond = masm.testBigInt(Assembler::NotEqual, value); break; -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } @@ -1294,11 +1292,9 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: masm.unboxSymbol(input, result); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: masm.unboxBigInt(input, result); break; -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } diff --git a/js/src/jit/arm64/MacroAssembler-arm64-inl.h b/js/src/jit/arm64/MacroAssembler-arm64-inl.h index 61cde27b4c69..462c2ec8e0a4 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h +++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h @@ -1410,7 +1410,6 @@ void MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, B(label, c); } -#ifdef ENABLE_BIGINT void MacroAssembler::branchTestBigInt(Condition cond, Register tag, Label* label) { branchTestBigIntImpl(cond, tag, label); @@ -1439,7 +1438,6 @@ void MacroAssembler::branchTestBigIntTruthy(bool truthy, Condition c = testBigIntTruthy(truthy, value); B(label, c); } -#endif void MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label) { diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index 5cfa4d40b9cc..0e812b0b6843 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -1394,14 +1394,12 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT void unboxBigInt(const ValueOperand& operand, Register dest) { unboxNonDouble(operand, dest, JSVAL_TYPE_BIGINT); } void unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } -#endif // These two functions use the low 32-bits of the full value register. void boolValueToDouble(const ValueOperand& operand, FloatRegister dest) { convertInt32ToDouble(operand.valueReg(), dest); @@ -1487,13 +1485,11 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { cmpTag(tag, ImmTag(JSVAL_TAG_SYMBOL)); return cond; } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmpTag(tag, ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Condition testObject(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmpTag(tag, ImmTag(JSVAL_TAG_OBJECT)); @@ -1584,7 +1580,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { splitSignExtTag(value, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const ValueOperand& value) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); @@ -1592,7 +1587,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { splitSignExtTag(value, scratch); return testBigInt(cond, scratch); } -#endif Condition testObject(Condition cond, const ValueOperand& value) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); @@ -1689,7 +1683,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { splitSignExtTag(address, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const Address& address) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); @@ -1697,7 +1690,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { splitSignExtTag(address, scratch); return testBigInt(cond, scratch); } -#endif Condition testObject(Condition cond, const Address& address) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); @@ -1754,7 +1746,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { splitSignExtTag(src, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const BaseIndex& src) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); @@ -1776,7 +1767,6 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { Cmp(scratch64, Operand(0)); return truthy ? Condition::NonZero : Condition::Zero; } -#endif Condition testInt32(Condition cond, const BaseIndex& src) { vixl::UseScratchRegisterScope temps(this); const Register scratch = temps.AcquireX().asUnsized(); diff --git a/js/src/jit/mips32/MacroAssembler-mips32-inl.h b/js/src/jit/mips32/MacroAssembler-mips32-inl.h index ab9a94d828bb..abc6b9187292 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32-inl.h +++ b/js/src/jit/mips32/MacroAssembler-mips32-inl.h @@ -814,7 +814,6 @@ void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, branchTestSymbol(cond, value.typeReg(), label); } -#ifdef ENABLE_BIGINT void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label) { branchTestBigInt(cond, value.typeReg(), label); @@ -827,7 +826,6 @@ void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, ma_lw(scratch2, Address(bi, BigInt::offsetOfLengthSignAndReservedBits())); ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal); } -#endif void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label) { diff --git a/js/src/jit/mips64/CodeGenerator-mips64.cpp b/js/src/jit/mips64/CodeGenerator-mips64.cpp index a5ad7b8a3b24..2f102a37b194 100644 --- a/js/src/jit/mips64/CodeGenerator-mips64.cpp +++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp @@ -78,10 +78,8 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: masm.unboxSymbol(inputReg, result); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: masm.unboxBigInt(inputReg, result); -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } @@ -105,10 +103,8 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: masm.unboxSymbol(inputAddr, result); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: masm.unboxBigInt(inputAddr, result); -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } diff --git a/js/src/jit/mips64/MacroAssembler-mips64-inl.h b/js/src/jit/mips64/MacroAssembler-mips64-inl.h index 30441d07e88c..4b77595365ab 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64-inl.h +++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h @@ -546,7 +546,6 @@ void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, branchTestSymbol(cond, scratch2, label); } -#ifdef ENABLE_BIGINT void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label) { SecondScratchRegisterScope scratch2(*this); @@ -562,7 +561,6 @@ void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, scratch2); ma_b(scratch2, ImmWord(0), label, b ? NotEqual : Equal); } -#endif void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label) { diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp index a78d196f0cdd..3236573e17ad 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.cpp +++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp @@ -1266,7 +1266,6 @@ void MacroAssemblerMIPS64Compat::unboxSymbol(const Address& src, unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT void MacroAssemblerMIPS64Compat::unboxBigInt(const ValueOperand& operand, Register dest) { unboxNonDouble(operand, dest, JSVAL_TYPE_BIGINT); @@ -1280,7 +1279,6 @@ void MacroAssemblerMIPS64Compat::unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } -#endif void MacroAssemblerMIPS64Compat::unboxObject(const ValueOperand& src, Register dest) { diff --git a/js/src/jit/mips64/MacroAssembler-mips64.h b/js/src/jit/mips64/MacroAssembler-mips64.h index 97efb8477e60..a4108883d195 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.h +++ b/js/src/jit/mips64/MacroAssembler-mips64.h @@ -398,11 +398,9 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64 { void unboxSymbol(const ValueOperand& src, Register dest); void unboxSymbol(Register src, Register dest); void unboxSymbol(const Address& src, Register dest); -#ifdef ENABLE_BIGINT void unboxBigInt(const ValueOperand& operand, Register dest); void unboxBigInt(Register src, Register dest); void unboxBigInt(const Address& src, Register dest); -#endif void unboxObject(const ValueOperand& src, Register dest); void unboxObject(Register src, Register dest); void unboxObject(const Address& src, Register dest); diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h index 3713b14c2fed..1bee3a789c0d 100644 --- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -463,12 +463,10 @@ class MacroAssemblerNone : public Assembler { void unboxSymbol(T, Register) { MOZ_CRASH(); } -#ifdef ENABLE_BIGINT template void unboxBigInt(T, Register) { MOZ_CRASH(); } -#endif template void unboxObject(T, Register) { MOZ_CRASH(); @@ -528,9 +526,7 @@ class MacroAssemblerNone : public Assembler { void loadConstantFloat32(float, FloatRegister) { MOZ_CRASH(); } Condition testInt32Truthy(bool, ValueOperand) { MOZ_CRASH(); } Condition testStringTruthy(bool, ValueOperand) { MOZ_CRASH(); } -#ifdef ENABLE_BIGINT Condition testBigIntTruthy(bool, ValueOperand) { MOZ_CRASH(); } -#endif template void loadUnboxedValue(T, MIRType, AnyRegister) { diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp index 54941a96d832..43b987753712 100644 --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -434,9 +434,7 @@ void CodeGeneratorShared::encodeAllocation(LSnapshot* snapshot, case MIRType::Int32: case MIRType::String: case MIRType::Symbol: -#ifdef ENABLE_BIGINT case MIRType::BigInt: -#endif case MIRType::Object: case MIRType::ObjectOrNull: case MIRType::Boolean: diff --git a/js/src/jit/shared/Lowering-shared-inl.h b/js/src/jit/shared/Lowering-shared-inl.h index 4e33519dca02..ca862eb88463 100644 --- a/js/src/jit/shared/Lowering-shared-inl.h +++ b/js/src/jit/shared/Lowering-shared-inl.h @@ -430,10 +430,7 @@ void LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as) { case MIRType::ObjectOrNull: case MIRType::String: case MIRType::Symbol: -# ifdef ENABLE_BIGINT - case MIRType::BigInt: -# endif - { + case MIRType::BigInt: { LAssertResultT* check = new (alloc()) LAssertResultT(useRegister(def)); add(check, def->toInstruction()); diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index 313aee5437f2..a42cda54c36d 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -85,11 +85,9 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: cond = masm.testSymbol(Assembler::NotEqual, value); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: cond = masm.testBigInt(Assembler::NotEqual, value); break; -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } @@ -124,11 +122,9 @@ void CodeGenerator::visitUnbox(LUnbox* unbox) { case MIRType::Symbol: masm.unboxSymbol(input, result); break; -#ifdef ENABLE_BIGINT case MIRType::BigInt: masm.unboxBigInt(input, result); break; -#endif default: MOZ_CRASH("Given MIRType cannot be unboxed."); } diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index e5ea85cb7cde..7ee00df4b2a8 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -255,13 +255,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL)); return cond; } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tag, ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Condition testObject(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tag, ImmTag(JSVAL_TAG_OBJECT)); @@ -337,13 +335,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { splitTag(src, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const ValueOperand& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); return testBigInt(cond, scratch); } -#endif Condition testObject(Condition cond, const ValueOperand& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); @@ -397,13 +393,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { splitTag(src, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const Address& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); return testBigInt(cond, scratch); } -#endif Condition testObject(Condition cond, const Address& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); @@ -450,13 +444,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { splitTag(src, scratch); return testSymbol(cond, scratch); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const BaseIndex& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); return testBigInt(cond, scratch); } -#endif Condition testInt32(Condition cond, const BaseIndex& src) { ScratchRegisterScope scratch(asMasm()); splitTag(src, scratch); @@ -828,14 +820,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } void unboxBigInt(const Operand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } -#endif void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT); @@ -957,7 +947,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { cmp32(Operand(scratch, JSString::offsetOfLength()), Imm32(0)); return truthy ? Assembler::NotEqual : Assembler::Equal; } -#ifdef ENABLE_BIGINT Condition testBigIntTruthy(bool truthy, const ValueOperand& value) { ScratchRegisterScope scratch(asMasm()); unboxBigInt(value, scratch); @@ -965,7 +954,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { ImmWord(0)); return truthy ? Assembler::NotEqual : Assembler::Equal; } -#endif template inline void loadInt32OrDouble(const T& src, FloatRegister dest); diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h b/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h index 63dc1163469b..51df81f1f787 100644 --- a/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h @@ -801,7 +801,6 @@ void MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, j(cond, label); } -#ifdef ENABLE_BIGINT void MacroAssembler::branchTestBigInt(Condition cond, Register tag, Label* label) { branchTestBigIntImpl(cond, tag, label); @@ -830,7 +829,6 @@ void MacroAssembler::branchTestBigIntTruthy(bool truthy, Condition cond = testBigIntTruthy(truthy, value); j(cond, label); } -#endif void MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label) { diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 3aa9309e4e66..79668043c47f 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -309,13 +309,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared { cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL)); return cond; } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tag, ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Condition testObject(Condition cond, Register tag) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tag, ImmTag(JSVAL_TAG_OBJECT)); @@ -431,11 +429,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared { Condition testSymbol(Condition cond, const ValueOperand& value) { return testSymbol(cond, value.typeReg()); } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const ValueOperand& value) { return testBigInt(cond, value.typeReg()); } -#endif Condition testObject(Condition cond, const ValueOperand& value) { return testObject(cond, value.typeReg()); } @@ -485,13 +481,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared { cmp32(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL)); return cond; } -#ifdef ENABLE_BIGINT Condition testBigInt(Condition cond, const BaseIndex& address) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tagOf(address), ImmTag(JSVAL_TAG_BIGINT)); return cond; } -#endif Condition testInt32(Condition cond, const BaseIndex& address) { MOZ_ASSERT(cond == Equal || cond == NotEqual); cmp32(tagOf(address), ImmTag(JSVAL_TAG_INT32)); @@ -766,14 +760,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared { void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } void unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT); } -#endif void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT); } @@ -890,14 +882,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared { cmp32(Operand(string, JSString::offsetOfLength()), Imm32(0)); return truthy ? Assembler::NotEqual : Assembler::Equal; } -#ifdef ENABLE_BIGINT Condition testBigIntTruthy(bool truthy, const ValueOperand& value) { Register bi = value.payloadReg(); cmpPtr(Operand(bi, BigInt::offsetOfLengthSignAndReservedBits()), ImmWord(0)); return truthy ? Assembler::NotEqual : Assembler::Equal; } -#endif template inline void loadInt32OrDouble(const T& src, FloatRegister dest); diff --git a/js/src/jsapi-tests/testJitRValueAlloc.cpp b/js/src/jsapi-tests/testJitRValueAlloc.cpp index eb3ccba9e39b..69b3063dfe11 100644 --- a/js/src/jsapi-tests/testJitRValueAlloc.cpp +++ b/js/src/jsapi-tests/testJitRValueAlloc.cpp @@ -68,7 +68,7 @@ BEGIN_TEST(testJitRValueAlloc_TypedReg) { /* _(JSVAL_TYPE_MAGIC) */ \ _(JSVAL_TYPE_STRING) \ _(JSVAL_TYPE_SYMBOL) \ - IF_BIGINT(_(JSVAL_TYPE_BIGINT),) \ + _(JSVAL_TYPE_BIGINT) \ /* _(JSVAL_TYPE_NULL) */ \ _(JSVAL_TYPE_OBJECT) @@ -96,7 +96,7 @@ BEGIN_TEST(testJitRValueAlloc_TypedStack) { /* _(JSVAL_TYPE_MAGIC) */ \ _(JSVAL_TYPE_STRING) \ _(JSVAL_TYPE_SYMBOL) \ - IF_BIGINT(_(JSVAL_TYPE_BIGINT),) \ + _(JSVAL_TYPE_BIGINT) \ /* _(JSVAL_TYPE_NULL) */ \ _(JSVAL_TYPE_OBJECT) diff --git a/js/src/jsapi-tests/tests.cpp b/js/src/jsapi-tests/tests.cpp index 70a691f307d5..96d1cd991c69 100644 --- a/js/src/jsapi-tests/tests.cpp +++ b/js/src/jsapi-tests/tests.cpp @@ -80,9 +80,7 @@ JSObject* JSAPITest::createGlobal(JSPrincipals* principals) { JS::RootedObject newGlobal(cx); JS::RealmOptions options; options.creationOptions().setStreamsEnabled(true); -#ifdef ENABLE_BIGINT options.creationOptions().setBigIntEnabled(true); -#endif newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook, options); if (!newGlobal) { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index f5a9df123679..dbf35192f6b5 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3424,9 +3424,7 @@ void JS::TransitiveCompileOptions::copyPODTransitiveOptions( hasIntroductionInfo = rhs.hasIntroductionInfo; isProbablySystemCode = rhs.isProbablySystemCode; hideScriptFromDebugger = rhs.hideScriptFromDebugger; -#ifdef ENABLE_BIGINT bigIntEnabledOption = rhs.bigIntEnabledOption; -#endif }; void JS::ReadOnlyCompileOptions::copyPODOptions( @@ -3553,9 +3551,7 @@ JS::CompileOptions::CompileOptions(JSContext* cx) } throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure(); -#ifdef ENABLE_BIGINT bigIntEnabledOption = cx->realm()->creationOptions().getBigIntEnabled(); -#endif } CompileOptions& CompileOptions::setIntroductionInfoToCaller( diff --git a/js/src/jsapi.h b/js/src/jsapi.h index f0afffd5e426..773b1963e0fc 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -963,9 +963,7 @@ class JS_PUBLIC_API RealmCreationOptions { cloneSingletons_(false), sharedMemoryAndAtomics_(false), streams_(false), -#ifdef ENABLE_BIGINT bigint_(false), -#endif secureContext_(false), clampAndJitterTime_(true) { } @@ -1042,13 +1040,11 @@ class JS_PUBLIC_API RealmCreationOptions { return *this; } -#ifdef ENABLE_BIGINT bool getBigIntEnabled() const { return bigint_; } RealmCreationOptions& setBigIntEnabled(bool flag) { bigint_ = flag; return *this; } -#endif // This flag doesn't affect JS engine behavior. It is used by Gecko to // mark whether content windows and workers are "Secure Context"s. See @@ -1079,9 +1075,7 @@ class JS_PUBLIC_API RealmCreationOptions { bool cloneSingletons_; bool sharedMemoryAndAtomics_; bool streams_; -#ifdef ENABLE_BIGINT bool bigint_; -#endif bool secureContext_; bool clampAndJitterTime_; }; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index e8b7fb9cce5e..89d96bb41a3e 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -1068,15 +1068,11 @@ const char* js::ValueToSourceForError(JSContext* cx, HandleValue val, if (!sb.append("the string ")) { return "<>"; } - } -#ifdef ENABLE_BIGINT - else if (val.isBigInt()) { + } else if (val.isBigInt()) { if (!sb.append("the BigInt ")) { return "<>"; } - } -#endif - else { + } else { MOZ_ASSERT(val.isBoolean() || val.isSymbol()); bytes = StringToNewUTF8CharsZ(cx, *str); return bytes.get(); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 90efb60a808a..d5e201b3bdcd 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -13,9 +13,7 @@ #include -#ifdef ENABLE_BIGINT -# include "builtin/BigInt.h" -#endif +#include "builtin/BigInt.h" #include "builtin/Promise.h" #include "builtin/TestingFunctions.h" #include "gc/GCInternals.h" @@ -306,10 +304,8 @@ JS_FRIEND_API bool js::GetBuiltinClass(JSContext* cx, HandleObject obj, *cls = ESClass::Arguments; } else if (obj->is()) { *cls = ESClass::Error; -#ifdef ENABLE_BIGINT } else if (obj->is()) { *cls = ESClass::BigInt; -#endif } else { *cls = ESClass::Other; } diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 6d761f4f76ef..d7c30b10a28a 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -35,9 +35,7 @@ #include "js/PropertySpec.h" #include "util/DoubleToString.h" #include "util/StringBuffer.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/GlobalObject.h" #include "vm/JSAtom.h" #include "vm/JSContext.h" @@ -545,11 +543,9 @@ static bool Number(JSContext* cx, unsigned argc, Value* vp) { if (!ToNumeric(cx, args[0])) { return false; } -#ifdef ENABLE_BIGINT if (args[0].isBigInt()) { args[0].setNumber(BigInt::numberValue(args[0].toBigInt())); } -#endif MOZ_ASSERT(args[0].isNumber()); } @@ -1688,14 +1684,12 @@ JS_PUBLIC_API bool js::ToNumberSlow(JSContext* cx, HandleValue v_, return true; } - MOZ_ASSERT(v.isSymbol() || IF_BIGINT(v.isBigInt(), false)); + MOZ_ASSERT(v.isSymbol() || v.isBigInt()); if (!cx->helperThread()) { unsigned errnum = JSMSG_SYMBOL_TO_NUMBER; -#ifdef ENABLE_BIGINT if (v.isBigInt()) { errnum = JSMSG_BIGINT_TO_NUMBER; } -#endif JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, errnum); } return false; @@ -1704,9 +1698,7 @@ JS_PUBLIC_API bool js::ToNumberSlow(JSContext* cx, HandleValue v_, // BigInt proposal section 3.1.6 bool js::ToNumericSlow(JSContext* cx, MutableHandleValue vp) { MOZ_ASSERT(!vp.isNumber()); -#ifdef ENABLE_BIGINT MOZ_ASSERT(!vp.isBigInt()); -#endif // Step 1. if (!vp.isPrimitive()) { @@ -1719,11 +1711,9 @@ bool js::ToNumericSlow(JSContext* cx, MutableHandleValue vp) { } // Step 2. -#ifdef ENABLE_BIGINT if (vp.isBigInt()) { return true; } -#endif // Step 3. return ToNumber(cx, vp); @@ -1852,11 +1842,9 @@ bool js::ToInt32OrBigIntSlow(JSContext* cx, MutableHandleValue vp) { return false; } -#ifdef ENABLE_BIGINT if (vp.isBigInt()) { return true; } -#endif vp.setInt32(ToInt32(vp.toNumber())); return true; diff --git a/js/src/jsnum.h b/js/src/jsnum.h index 593dae518729..2e5f3bc43598 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -205,11 +205,9 @@ MOZ_ALWAYS_INLINE MOZ_MUST_USE bool ToNumeric(JSContext* cx, if (vp.isNumber()) { return true; } -#ifdef ENABLE_BIGINT if (vp.isBigInt()) { return true; } -#endif return ToNumericSlow(cx, vp); } diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 7df06d090e0a..53ec6433fd25 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -46,9 +46,7 @@ enum JSType { JSTYPE_BOOLEAN, /* boolean */ JSTYPE_NULL, /* null */ JSTYPE_SYMBOL, /* symbol */ -#ifdef ENABLE_BIGINT JSTYPE_BIGINT, /* BigInt */ -#endif JSTYPE_LIMIT }; diff --git a/js/src/moz.build b/js/src/moz.build index 265275d1e36b..1ab4a0380fa4 100755 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -191,6 +191,7 @@ EXPORTS.js += [ UNIFIED_SOURCES += [ 'builtin/Array.cpp', 'builtin/AtomicsObject.cpp', + 'builtin/BigInt.cpp', 'builtin/Boolean.cpp', 'builtin/DataViewObject.cpp', 'builtin/Eval.cpp', @@ -258,6 +259,7 @@ UNIFIED_SOURCES += [ 'vm/ArrayBufferViewObject.cpp', 'vm/AsyncFunction.cpp', 'vm/AsyncIteration.cpp', + 'vm/BigIntType.cpp', 'vm/BuildId.cpp', 'vm/BytecodeUtil.cpp', 'vm/Caches.cpp', @@ -346,12 +348,6 @@ SOURCES += [ 'vm/ProfilingStack.cpp', ] -if CONFIG['ENABLE_BIGINT']: - SOURCES += [ - 'builtin/BigInt.cpp', - 'vm/BigIntType.cpp', - ] - if CONFIG['JS_POSIX_NSPR']: UNIFIED_SOURCES += [ 'vm/PosixNSPR.cpp', diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 07c441120816..3fa401f61c6b 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -500,9 +500,7 @@ static bool enableWasmVerbose = false; static bool enableTestWasmAwaitTier2 = false; static bool enableAsyncStacks = false; static bool enableStreams = false; -#ifdef ENABLE_BIGINT static bool enableBigInt = false; -#endif #ifdef JS_GC_ZEAL static uint32_t gZealBits = 0; static uint32_t gZealFrequency = 0; @@ -3773,9 +3771,7 @@ static const JSClass sandbox_class = {"sandbox", JSCLASS_GLOBAL_FLAGS, static void SetStandardRealmOptions(JS::RealmOptions& options) { options.creationOptions() .setSharedMemoryAndAtomicsEnabled(enableSharedMemory) -#ifdef ENABLE_BIGINT .setBigIntEnabled(enableBigInt) -#endif .setStreamsEnabled(enableStreams); } @@ -9895,9 +9891,7 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) { enableTestWasmAwaitTier2 = op.getBoolOption("test-wasm-await-tier2"); enableAsyncStacks = !op.getBoolOption("no-async-stacks"); enableStreams = !op.getBoolOption("no-streams"); -#ifdef ENABLE_BIGINT enableBigInt = !op.getBoolOption("no-bigint"); -#endif JS::ContextOptionsRef(cx) .setBaseline(enableBaseline) @@ -10603,19 +10597,17 @@ int main(int argc, char** argv, char** envp) { "Disable creating unboxed plain objects") || !op.addBoolOption('\0', "enable-streams", "Enable WHATWG Streams (default)") || - !op.addBoolOption('\0', "no-streams", "Disable WHATWG Streams") -#ifdef ENABLE_BIGINT - || !op.addBoolOption('\0', "no-bigint", - "Disable experimental BigInt support") -#endif - || !op.addStringOption('\0', "shared-memory", "on/off", - "SharedArrayBuffer and Atomics " + !op.addBoolOption('\0', "no-streams", "Disable WHATWG Streams") || + !op.addBoolOption('\0', "no-bigint", + "Disable experimental BigInt support") || + !op.addStringOption('\0', "shared-memory", "on/off", + "SharedArrayBuffer and Atomics " #if SHARED_MEMORY_DEFAULT - "(default: on, off to disable)" + "(default: on, off to disable)" #else - "(default: off, on to enable)" + "(default: off, on to enable)" #endif - ) || + ) || !op.addStringOption('\0', "spectre-mitigations", "on/off", "Whether Spectre mitigations are enabled (default: " "off, on to enable)") || diff --git a/js/src/util/StringBuffer.cpp b/js/src/util/StringBuffer.cpp index 03fb56248860..50b23f9e3d59 100644 --- a/js/src/util/StringBuffer.cpp +++ b/js/src/util/StringBuffer.cpp @@ -167,7 +167,6 @@ bool js::ValueToStringBufferSlow(JSContext* cx, const Value& arg, JSMSG_SYMBOL_TO_STRING); return false; } -#ifdef ENABLE_BIGINT if (v.isBigInt()) { RootedBigInt i(cx, v.toBigInt()); JSLinearString* str = BigInt::toString(cx, i, 10); @@ -176,7 +175,6 @@ bool js::ValueToStringBufferSlow(JSContext* cx, const Value& arg, } return sb.append(str); } -#endif MOZ_ASSERT(v.isUndefined()); return sb.append(cx->names().undefined); } diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp index aa6ea7b5a255..307d0b92f2d8 100644 --- a/js/src/vm/BytecodeUtil.cpp +++ b/js/src/vm/BytecodeUtil.cpp @@ -1478,10 +1478,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc, break; } -# ifdef ENABLE_BIGINT case JOF_BIGINT: - // Fallthrough. -# endif case JOF_DOUBLE: { RootedValue v(cx, script->getConst(GET_UINT32_INDEX(pc))); UniqueChars bytes = ToDisassemblySource(cx, v); diff --git a/js/src/vm/BytecodeUtil.h b/js/src/vm/BytecodeUtil.h index bdab60f8a886..7ffd13e6137e 100644 --- a/js/src/vm/BytecodeUtil.h +++ b/js/src/vm/BytecodeUtil.h @@ -62,9 +62,7 @@ enum { JOF_CODE_OFFSET = 19, /* int32_t bytecode offset */ JOF_ICINDEX = 20, /* uint32_t IC index */ JOF_LOOPENTRY = 21, /* JSOP_LOOPENTRY, combines JOF_ICINDEX and JOF_UINT8 */ -#ifdef ENABLE_BIGINT - JOF_BIGINT = 22, /* uint32_t index for BigInt value */ -#endif + JOF_BIGINT = 22, /* uint32_t index for BigInt value */ JOF_TYPEMASK = 0x001f, /* mask for above immediate types */ JOF_NAME = 1 << 5, /* name operation */ diff --git a/js/src/vm/Compartment-inl.h b/js/src/vm/Compartment-inl.h index 92a534cf710d..1e80897e62ac 100644 --- a/js/src/vm/Compartment-inl.h +++ b/js/src/vm/Compartment-inl.h @@ -49,7 +49,6 @@ inline bool JS::Compartment::wrap(JSContext* cx, JS::MutableHandleValue vp) { return true; } -#ifdef ENABLE_BIGINT if (vp.isBigInt()) { JS::RootedBigInt bi(cx, vp.toBigInt()); if (!wrap(cx, &bi)) { @@ -58,7 +57,6 @@ inline bool JS::Compartment::wrap(JSContext* cx, JS::MutableHandleValue vp) { vp.setBigInt(bi); return true; } -#endif MOZ_ASSERT(vp.isObject()); diff --git a/js/src/vm/Compartment.cpp b/js/src/vm/Compartment.cpp index 519b37abcb78..f11f52578799 100644 --- a/js/src/vm/Compartment.cpp +++ b/js/src/vm/Compartment.cpp @@ -168,7 +168,6 @@ bool Compartment::wrap(JSContext* cx, MutableHandleString strp) { return true; } -#ifdef ENABLE_BIGINT bool Compartment::wrap(JSContext* cx, MutableHandleBigInt bi) { MOZ_ASSERT(cx->compartment() == this); @@ -183,7 +182,6 @@ bool Compartment::wrap(JSContext* cx, MutableHandleBigInt bi) { bi.set(copy); return true; } -#endif bool Compartment::getNonWrapperObjectForCurrentCompartment( JSContext* cx, MutableHandleObject obj) { diff --git a/js/src/vm/Compartment.h b/js/src/vm/Compartment.h index c4cf2be5f630..103f5f7abc75 100644 --- a/js/src/vm/Compartment.h +++ b/js/src/vm/Compartment.h @@ -483,9 +483,7 @@ class JS::Compartment { MOZ_MUST_USE inline bool wrap(JSContext* cx, JS::MutableHandleValue vp); MOZ_MUST_USE bool wrap(JSContext* cx, js::MutableHandleString strp); -#ifdef ENABLE_BIGINT MOZ_MUST_USE bool wrap(JSContext* cx, js::MutableHandle bi); -#endif MOZ_MUST_USE bool wrap(JSContext* cx, JS::MutableHandleObject obj); MOZ_MUST_USE bool wrap(JSContext* cx, JS::MutableHandle desc); diff --git a/js/src/vm/EqualityOperations.cpp b/js/src/vm/EqualityOperations.cpp index 7a4e595d8d40..2910a7f02088 100644 --- a/js/src/vm/EqualityOperations.cpp +++ b/js/src/vm/EqualityOperations.cpp @@ -16,9 +16,7 @@ #include "js/Result.h" // JS_TRY_VAR_OR_RETURN_FALSE #include "js/RootingAPI.h" // JS::Rooted #include "js/Value.h" // JS::Int32Value, JS::SameType, JS::Value -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" // JS::BigInt -#endif // ENABLE_BIGINT +#include "vm/BigIntType.h" // JS::BigInt #include "vm/JSContext.h" // CHECK_THREAD #include "vm/JSObject.h" // js::ToPrimitive #include "vm/StringType.h" // js::EqualStrings @@ -39,12 +37,10 @@ static bool EqualGivenSameType(JSContext* cx, JS::Handle lval, return true; } -#ifdef ENABLE_BIGINT if (lval.isBigInt()) { *equal = JS::BigInt::equal(lval.toBigInt(), rval.toBigInt()); return true; } -#endif if (lval.isGCThing()) { // objects or symbols *equal = (lval.toGCThing() == rval.toGCThing()); @@ -162,7 +158,6 @@ bool js::LooselyEqual(JSContext* cx, JS::Handle lval, return js::LooselyEqual(cx, lvalue, rval, result); } -#ifdef ENABLE_BIGINT if (lval.isBigInt()) { JS::Rooted lbi(cx, lval.toBigInt()); bool tmpResult; @@ -180,7 +175,6 @@ bool js::LooselyEqual(JSContext* cx, JS::Handle lval, *result = tmpResult; return true; } -#endif // Step 12. *result = false; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 2581b084e4e1..27e1f5006e34 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -11,9 +11,7 @@ #include "jsfriendapi.h" #include "builtin/AtomicsObject.h" -#ifdef ENABLE_BIGINT -# include "builtin/BigInt.h" -#endif +#include "builtin/BigInt.h" #include "builtin/DataViewObject.h" #include "builtin/Eval.h" #include "builtin/MapObject.h" @@ -104,10 +102,8 @@ TypedObjectModuleObject& js::GlobalObject::getTypedObjectModule() const { case JSProto_CountQueuingStrategy: return !cx->realm()->creationOptions().getStreamsEnabled(); -#ifdef ENABLE_BIGINT case JSProto_BigInt: return !cx->realm()->creationOptions().getBigIntEnabled(); -#endif // Return true if the given constructor has been disabled at run-time. case JSProto_Atomics: diff --git a/js/src/vm/Initialization.cpp b/js/src/vm/Initialization.cpp index a178c3db55dc..e360924b5629 100644 --- a/js/src/vm/Initialization.cpp +++ b/js/src/vm/Initialization.cpp @@ -26,9 +26,7 @@ # include "unicode/uclean.h" # include "unicode/utypes.h" #endif // ENABLE_INTL_API -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/DateTime.h" #include "vm/HelperThreads.h" #include "vm/Runtime.h" diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index 0c3d0d77ea38..3f291aa8e118 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -390,11 +390,9 @@ static MOZ_ALWAYS_INLINE bool NegOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (val.isBigInt()) { return BigInt::neg(cx, val, res); } -#endif res.setNumber(-val.toNumber()); return true; @@ -723,7 +721,6 @@ static MOZ_ALWAYS_INLINE bool LessThanImpl(JSContext* cx, return true; } -#ifdef ENABLE_BIGINT // Step 4a. if (lhs.isBigInt() && rhs.isString()) { return BigInt::lessThan(cx, lhs, rhs, res); @@ -733,19 +730,16 @@ static MOZ_ALWAYS_INLINE bool LessThanImpl(JSContext* cx, if (lhs.isString() && rhs.isBigInt()) { return BigInt::lessThan(cx, lhs, rhs, res); } -#endif // Steps 4c and 4d. if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs)) { return false; } -#ifdef ENABLE_BIGINT // Steps 4e-j. if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::lessThan(cx, lhs, rhs, res); } -#endif // Step 4e for Number operands. MOZ_ASSERT(lhs.isNumber() && rhs.isNumber()); @@ -865,11 +859,9 @@ static MOZ_ALWAYS_INLINE bool BitNot(JSContext* cx, MutableHandleValue in, return false; } -#ifdef ENABLE_BIGINT if (in.isBigInt()) { return BigInt::bitNot(cx, in, out); } -#endif out.setInt32(~in.toInt32()); return true; @@ -882,11 +874,9 @@ static MOZ_ALWAYS_INLINE bool BitXor(JSContext* cx, MutableHandleValue lhs, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::bitXor(cx, lhs, rhs, out); } -#endif out.setInt32(lhs.toInt32() ^ rhs.toInt32()); return true; @@ -899,11 +889,9 @@ static MOZ_ALWAYS_INLINE bool BitOr(JSContext* cx, MutableHandleValue lhs, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::bitOr(cx, lhs, rhs, out); } -#endif out.setInt32(lhs.toInt32() | rhs.toInt32()); return true; @@ -916,11 +904,9 @@ static MOZ_ALWAYS_INLINE bool BitAnd(JSContext* cx, MutableHandleValue lhs, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::bitAnd(cx, lhs, rhs, out); } -#endif out.setInt32(lhs.toInt32() & rhs.toInt32()); return true; @@ -933,11 +919,9 @@ static MOZ_ALWAYS_INLINE bool BitLsh(JSContext* cx, MutableHandleValue lhs, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::lsh(cx, lhs, rhs, out); } -#endif out.setInt32(lhs.toInt32() << (rhs.toInt32() & 31)); return true; @@ -950,11 +934,9 @@ static MOZ_ALWAYS_INLINE bool BitRsh(JSContext* cx, MutableHandleValue lhs, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::rsh(cx, lhs, rhs, out); } -#endif out.setInt32(lhs.toInt32() >> (rhs.toInt32() & 31)); return true; @@ -964,7 +946,6 @@ static MOZ_ALWAYS_INLINE bool UrshOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out) { -#ifdef ENABLE_BIGINT if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs)) { return false; } @@ -974,7 +955,6 @@ static MOZ_ALWAYS_INLINE bool UrshOperation(JSContext* cx, JSMSG_BIGINT_TO_NUMBER); return false; } -#endif uint32_t left; int32_t right; diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index dcab01c6678f..1382de3c9ed0 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -35,9 +35,7 @@ #include "util/StringBuffer.h" #include "vm/AsyncFunction.h" #include "vm/AsyncIteration.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/BytecodeUtil.h" #include "vm/Debugger.h" #include "vm/EqualityOperations.h" // js::StrictlyEqual @@ -891,11 +889,9 @@ JSType js::TypeOfValue(const Value& v) { if (v.isBoolean()) { return JSTYPE_BOOLEAN; } -#ifdef ENABLE_BIGINT if (v.isBigInt()) { return JSTYPE_BIGINT; } -#endif MOZ_ASSERT(v.isSymbol()); return JSTYPE_SYMBOL; } @@ -1440,11 +1436,9 @@ static MOZ_ALWAYS_INLINE bool AddOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::add(cx, lhs, rhs, res); } -#endif res.setNumber(lhs.toNumber() + rhs.toNumber()); return true; @@ -1458,11 +1452,9 @@ static MOZ_ALWAYS_INLINE bool SubOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::sub(cx, lhs, rhs, res); } -#endif res.setNumber(lhs.toNumber() - rhs.toNumber()); return true; @@ -1476,11 +1468,9 @@ static MOZ_ALWAYS_INLINE bool MulOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::mul(cx, lhs, rhs, res); } -#endif res.setNumber(lhs.toNumber() * rhs.toNumber()); return true; @@ -1494,11 +1484,9 @@ static MOZ_ALWAYS_INLINE bool DivOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::div(cx, lhs, rhs, res); } -#endif res.setNumber(NumberDiv(lhs.toNumber(), rhs.toNumber())); return true; @@ -1520,11 +1508,9 @@ static MOZ_ALWAYS_INLINE bool ModOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::mod(cx, lhs, rhs, res); } -#endif res.setNumber(NumberMod(lhs.toNumber(), rhs.toNumber())); return true; @@ -1538,11 +1524,9 @@ static MOZ_ALWAYS_INLINE bool PowOperation(JSContext* cx, return false; } -#ifdef ENABLE_BIGINT if (lhs.isBigInt() || rhs.isBigInt()) { return BigInt::pow(cx, lhs, rhs, res); } -#endif res.setNumber(ecmaPow(lhs.toNumber(), rhs.toNumber())); return true; @@ -4326,13 +4310,11 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx, } END_CASE(JSOP_TONUMERIC) -#ifdef ENABLE_BIGINT CASE(JSOP_BIGINT) { PUSH_COPY(script->getConst(GET_UINT32_INDEX(REGS.pc))); MOZ_ASSERT(REGS.sp[-1].isBigInt()); } END_CASE(JSOP_BIGINT) -#endif DEFAULT() { char numBuf[12]; @@ -4425,8 +4407,7 @@ bool js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, // Optimize common cases like (2).toString() or "foo".valueOf() to not // create a wrapper object. - if (v.isPrimitive() && !v.isNullOrUndefined() && - IF_BIGINT(!v.isBigInt(), true)) { + if (v.isPrimitive() && !v.isNullOrUndefined() && !v.isBigInt()) { NativeObject* proto; if (v.isNumber()) { proto = GlobalObject::getOrCreateNumberPrototype(cx, cx->global()); diff --git a/js/src/vm/JSAtom.cpp b/js/src/vm/JSAtom.cpp index 84f9b8f3ccdd..295a9f0f1bcc 100644 --- a/js/src/vm/JSAtom.cpp +++ b/js/src/vm/JSAtom.cpp @@ -1090,7 +1090,6 @@ static JSAtom* ToAtomSlow( } return nullptr; } -#ifdef ENABLE_BIGINT if (v.isBigInt()) { RootedBigInt i(cx, v.toBigInt()); JSAtom* atom = BigIntToAtom(cx, i); @@ -1099,7 +1098,6 @@ static JSAtom* ToAtomSlow( } return atom; } -#endif MOZ_ASSERT(v.isUndefined()); return cx->names().undefined; } diff --git a/js/src/vm/JSContext-inl.h b/js/src/vm/JSContext-inl.h index c960b5405335..10b091685576 100644 --- a/js/src/vm/JSContext-inl.h +++ b/js/src/vm/JSContext-inl.h @@ -12,9 +12,7 @@ #include "builtin/Object.h" #include "jit/JitFrames.h" #include "proxy/Proxy.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/HelperThreads.h" #include "vm/Interpreter.h" #include "vm/Iteration.h" @@ -105,9 +103,7 @@ class ContextChecks { void check(JS::Symbol* symbol, int argIndex) { checkAtom(symbol, argIndex); } -#ifdef ENABLE_BIGINT void check(JS::BigInt* bi, int argIndex) { check(bi->zone(), argIndex); } -#endif void check(const js::Value& v, int argIndex) { if (v.isObject()) { @@ -116,12 +112,9 @@ class ContextChecks { check(v.toString(), argIndex); } else if (v.isSymbol()) { check(v.toSymbol(), argIndex); - } -#ifdef ENABLE_BIGINT - else if (v.isBigInt()) { + } else if (v.isBigInt()) { check(v.toBigInt(), argIndex); } -#endif } // Check the contents of any container class that supports the C++ diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp index 9a0810829e72..ece680001f21 100644 --- a/js/src/vm/JSObject.cpp +++ b/js/src/vm/JSObject.cpp @@ -25,9 +25,7 @@ #include "jsutil.h" #include "builtin/Array.h" -#ifdef ENABLE_BIGINT -# include "builtin/BigInt.h" -#endif +#include "builtin/BigInt.h" #include "builtin/Eval.h" #include "builtin/Object.h" #include "builtin/String.h" @@ -3310,7 +3308,6 @@ JSObject* js::PrimitiveToObject(JSContext* cx, const Value& v) { if (v.isBoolean()) { return BooleanObject::create(cx, v.toBoolean()); } -#ifdef ENABLE_BIGINT if (v.isSymbol()) { RootedSymbol symbol(cx, v.toSymbol()); return SymbolObject::create(cx, symbol); @@ -3318,11 +3315,6 @@ JSObject* js::PrimitiveToObject(JSContext* cx, const Value& v) { MOZ_ASSERT(v.isBigInt()); RootedBigInt bigInt(cx, v.toBigInt()); return BigIntObject::create(cx, bigInt); -#else - MOZ_ASSERT(v.isSymbol()); - RootedSymbol symbol(cx, v.toSymbol()); - return SymbolObject::create(cx, symbol); -#endif } /* @@ -4215,10 +4207,8 @@ bool js::Unbox(JSContext* cx, HandleObject obj, MutableHandleValue vp) { vp.set(obj->as().UTCTime()); } else if (obj->is()) { vp.setSymbol(obj->as().unbox()); -#ifdef ENABLE_BIGINT } else if (obj->is()) { vp.setBigInt(obj->as().unbox()); -#endif } else { vp.setUndefined(); } diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp index 80515a226e4f..56f70954880b 100644 --- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -100,9 +100,7 @@ XDRResult js::XDRScriptConst(XDRState* xdr, MutableHandleValue vp) { SCRIPT_OBJECT, SCRIPT_VOID, SCRIPT_HOLE, -#ifdef ENABLE_BIGINT SCRIPT_BIGINT -#endif }; ConstTag tag; @@ -123,13 +121,9 @@ XDRResult js::XDRScriptConst(XDRState* xdr, MutableHandleValue vp) { tag = SCRIPT_OBJECT; } else if (vp.isMagic(JS_ELEMENTS_HOLE)) { tag = SCRIPT_HOLE; - } -#ifdef ENABLE_BIGINT - else if (vp.isBigInt()) { + } else if (vp.isBigInt()) { tag = SCRIPT_BIGINT; - } -#endif - else { + } else { MOZ_ASSERT(vp.isUndefined()); tag = SCRIPT_VOID; } @@ -209,7 +203,6 @@ XDRResult js::XDRScriptConst(XDRState* xdr, MutableHandleValue vp) { vp.setMagic(JS_ELEMENTS_HOLE); } break; -#ifdef ENABLE_BIGINT case SCRIPT_BIGINT: { RootedBigInt bi(cx); if (mode == XDR_ENCODE) { @@ -223,7 +216,6 @@ XDRResult js::XDRScriptConst(XDRState* xdr, MutableHandleValue vp) { } break; } -#endif default: // Fail in debug, but only soft-fail in release MOZ_ASSERT(false, "Bad XDR value kind"); @@ -4064,9 +4056,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst, val = elem.get(); if (val.isDouble()) { clone = val; - } -#ifdef ENABLE_BIGINT - else if (val.isBigInt()) { + } else if (val.isBigInt()) { if (cx->zone() == val.toBigInt()->zone()) { clone.setBigInt(val.toBigInt()); } else { @@ -4077,9 +4067,7 @@ bool js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst, } clone.setBigInt(copy); } - } -#endif - else { + } else { MOZ_ASSERT_UNREACHABLE("bad script consts() element"); } diff --git a/js/src/vm/MemoryMetrics.cpp b/js/src/vm/MemoryMetrics.cpp index 8b9226fcc4c2..39a7be785d8e 100644 --- a/js/src/vm/MemoryMetrics.cpp +++ b/js/src/vm/MemoryMetrics.cpp @@ -13,9 +13,7 @@ #include "jit/BaselineJIT.h" #include "jit/Ion.h" #include "vm/ArrayObject.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/HelperThreads.h" #include "vm/JSObject.h" #include "vm/JSScript.h" @@ -495,7 +493,6 @@ static void StatsCellCallback(JSRuntime* rt, void* data, void* thing, zStats->symbolsGCHeap += thingSize; break; -#ifdef ENABLE_BIGINT case JS::TraceKind::BigInt: { JS::BigInt* bi = static_cast(thing); zStats->bigIntsGCHeap += thingSize; @@ -503,7 +500,6 @@ static void StatsCellCallback(JSRuntime* rt, void* data, void* thing, bi->sizeOfExcludingThis(rtStats->mallocSizeOf_); break; } -#endif case JS::TraceKind::BaseShape: { JS::ShapeInfo info; // This zeroes all the sizes. diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 6b0625e4497e..3613a66bf809 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -2537,7 +2537,7 @@ * Operands: uint32_t constIndex * Stack: => val */ \ - IF_BIGINT(MACRO(JSOP_BIGINT, 237, "bigint", NULL, 5, 0, 1, JOF_BIGINT),) + MACRO(JSOP_BIGINT, 237, "bigint", NULL, 5, 0, 1, JOF_BIGINT) // clang-format on /* @@ -2545,7 +2545,6 @@ * a power of two. Use this macro to do so. */ #define FOR_EACH_TRAILING_UNUSED_OPCODE(MACRO) \ - IF_BIGINT(, MACRO(237)) \ MACRO(238) \ MACRO(239) \ MACRO(240) \ diff --git a/js/src/vm/StringType.cpp b/js/src/vm/StringType.cpp index 86e9f7372873..05d6e369b562 100644 --- a/js/src/vm/StringType.cpp +++ b/js/src/vm/StringType.cpp @@ -2163,17 +2163,13 @@ JSString* js::ToStringSlow( JSMSG_SYMBOL_TO_STRING); } return nullptr; - } -#ifdef ENABLE_BIGINT - else if (v.isBigInt()) { + } else if (v.isBigInt()) { if (!allowGC) { return nullptr; } RootedBigInt i(cx, v.toBigInt()); str = BigInt::toString(cx, i, 10); - } -#endif - else { + } else { MOZ_ASSERT(v.isUndefined()); str = cx->names().undefined; } diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index ec0c8769c0f4..562f5b0fdb69 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -46,9 +46,7 @@ #include "js/Date.h" #include "js/GCHashTable.h" #include "js/Wrapper.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/JSContext.h" #include "vm/RegExpObject.h" #include "vm/SavedFrame.h" @@ -402,9 +400,7 @@ struct JSStructuredCloneReader { JSString* readStringImpl(uint32_t nchars); JSString* readString(uint32_t data); -#ifdef ENABLE_BIGINT BigInt* readBigInt(uint32_t data); -#endif bool checkDouble(double d); MOZ_MUST_USE bool readTypedArray(uint32_t arrayType, uint32_t nelems, @@ -496,6 +492,7 @@ struct JSStructuredCloneWriter { bool writeTransferMap(); bool writeString(uint32_t tag, JSString* str); + bool writeBigInt(uint32_t tag, BigInt* bi); bool writeArrayBuffer(HandleObject obj); bool writeTypedArray(HandleObject obj); bool writeDataView(HandleObject obj); @@ -508,10 +505,6 @@ struct JSStructuredCloneWriter { bool traverseSet(HandleObject obj); bool traverseSavedFrame(HandleObject obj); -#ifdef ENABLE_BIGINT - bool writeBigInt(uint32_t tag, BigInt* bi); -#endif - bool reportDataCloneError(uint32_t errorId); bool parseTransferable(); @@ -1145,7 +1138,6 @@ bool JSStructuredCloneWriter::writeString(uint32_t tag, JSString* str) { : out.writeChars(linear->twoByteChars(nogc), length); } -#ifdef ENABLE_BIGINT bool JSStructuredCloneWriter::writeBigInt(uint32_t tag, BigInt* bi) { bool signBit = bi->isNegative(); size_t length = bi->digitLength(); @@ -1160,7 +1152,6 @@ bool JSStructuredCloneWriter::writeBigInt(uint32_t tag, BigInt* bi) { } return out.writeArray(bi->digits().data(), length); } -#endif inline void JSStructuredCloneWriter::checkStack() { #ifdef DEBUG @@ -1626,13 +1617,9 @@ bool JSStructuredCloneWriter::startWrite(HandleValue v) { return out.writePair(SCTAG_NULL, 0); } else if (v.isUndefined()) { return out.writePair(SCTAG_UNDEFINED, 0); - } -#ifdef ENABLE_BIGINT - else if (v.isBigInt()) { + } else if (v.isBigInt()) { return writeBigInt(SCTAG_BIGINT, v.toBigInt()); - } -#endif - else if (v.isObject()) { + } else if (v.isObject()) { RootedObject obj(context(), &v.toObject()); bool backref; @@ -1705,7 +1692,6 @@ bool JSStructuredCloneWriter::startWrite(HandleValue v) { return traverseSet(obj); case ESClass::Map: return traverseMap(obj); -#ifdef ENABLE_BIGINT case ESClass::BigInt: { RootedValue unboxed(context()); if (!Unbox(context(), obj, &unboxed)) { @@ -1713,7 +1699,6 @@ bool JSStructuredCloneWriter::startWrite(HandleValue v) { } return writeBigInt(SCTAG_BIGINT_OBJECT, unboxed.toBigInt()); } -#endif case ESClass::Promise: case ESClass::MapIterator: case ESClass::SetIterator: @@ -2062,7 +2047,6 @@ JSString* JSStructuredCloneReader::readString(uint32_t data) { : readStringImpl(nchars); } -#ifdef ENABLE_BIGINT BigInt* JSStructuredCloneReader::readBigInt(uint32_t data) { size_t length = data & JS_BITMASK(31); bool isNegative = data & (1 << 31); @@ -2079,7 +2063,6 @@ BigInt* JSStructuredCloneReader::readBigInt(uint32_t data) { } return result; } -#endif static uint32_t TagToV1ArrayType(uint32_t tag) { MOZ_ASSERT(tag >= SCTAG_TYPED_ARRAY_V1_MIN && @@ -2429,7 +2412,6 @@ bool JSStructuredCloneReader::startRead(MutableHandleValue vp) { case SCTAG_BIGINT: case SCTAG_BIGINT_OBJECT: { -#ifdef ENABLE_BIGINT RootedBigInt bi(context(), readBigInt(data)); if (!bi) { return false; @@ -2439,12 +2421,6 @@ bool JSStructuredCloneReader::startRead(MutableHandleValue vp) { return false; } break; -#else - JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, - JSMSG_SC_BAD_SERIALIZED_DATA, - "BigInt unsupported"); - return false; -#endif } case SCTAG_DATE_OBJECT: { diff --git a/js/src/vm/TypeInference-inl.h b/js/src/vm/TypeInference-inl.h index d786a77c7c0b..2a5587aed1ce 100644 --- a/js/src/vm/TypeInference-inl.h +++ b/js/src/vm/TypeInference-inl.h @@ -180,10 +180,8 @@ inline TypeFlags PrimitiveTypeFlag(JSValueType type) { return TYPE_FLAG_STRING; case JSVAL_TYPE_SYMBOL: return TYPE_FLAG_SYMBOL; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return TYPE_FLAG_BIGINT; -#endif case JSVAL_TYPE_MAGIC: return TYPE_FLAG_LAZYARGS; default: @@ -207,10 +205,8 @@ inline JSValueType TypeFlagPrimitive(TypeFlags flags) { return JSVAL_TYPE_STRING; case TYPE_FLAG_SYMBOL: return JSVAL_TYPE_SYMBOL; -#ifdef ENABLE_BIGINT case TYPE_FLAG_BIGINT: return JSVAL_TYPE_BIGINT; -#endif case TYPE_FLAG_LAZYARGS: return JSVAL_TYPE_MAGIC; default: diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index a42eea8f7a00..ee127a6850b4 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -107,10 +107,8 @@ const char* js::TypeIdStringImpl(jsid id) { return "string"; case JSVAL_TYPE_SYMBOL: return "symbol"; -#ifdef ENABLE_BIGINT case JSVAL_TYPE_BIGINT: return "BigInt"; -#endif case JSVAL_TYPE_MAGIC: return "lazyargs"; default: @@ -391,10 +389,8 @@ bool TypeSet::mightBeMIRType(jit::MIRType type) const { return baseFlags() & TYPE_FLAG_STRING; case jit::MIRType::Symbol: return baseFlags() & TYPE_FLAG_SYMBOL; -#ifdef ENABLE_BIGINT case jit::MIRType::BigInt: return baseFlags() & TYPE_FLAG_BIGINT; -#endif case jit::MIRType::MagicOptimizedArguments: return baseFlags() & TYPE_FLAG_LAZYARGS; case jit::MIRType::MagicHole: @@ -826,11 +822,9 @@ void TypeSet::print(FILE* fp) { if (flags & TYPE_FLAG_SYMBOL) { fprintf(fp, " symbol"); } -#ifdef ENABLE_BIGINT if (flags & TYPE_FLAG_BIGINT) { fprintf(fp, " BigInt"); } -#endif if (flags & TYPE_FLAG_LAZYARGS) { fprintf(fp, " lazyargs"); } @@ -1713,10 +1707,8 @@ static inline jit::MIRType GetMIRTypeFromTypeFlags(TypeFlags flags) { return jit::MIRType::String; case TYPE_FLAG_SYMBOL: return jit::MIRType::Symbol; -#ifdef ENABLE_BIGINT case TYPE_FLAG_BIGINT: return jit::MIRType::BigInt; -#endif case TYPE_FLAG_LAZYARGS: return jit::MIRType::MagicOptimizedArguments; case TYPE_FLAG_ANYOBJECT: diff --git a/js/src/vm/TypeSet.h b/js/src/vm/TypeSet.h index ff6b2bb602cb..4216267cdac6 100644 --- a/js/src/vm/TypeSet.h +++ b/js/src/vm/TypeSet.h @@ -83,29 +83,19 @@ enum : uint32_t { TYPE_FLAG_DOUBLE = 0x10, TYPE_FLAG_STRING = 0x20, TYPE_FLAG_SYMBOL = 0x40, -#ifdef ENABLE_BIGINT TYPE_FLAG_BIGINT = 0x80, TYPE_FLAG_LAZYARGS = 0x100, TYPE_FLAG_ANYOBJECT = 0x200, -#else - TYPE_FLAG_LAZYARGS = 0x80, - TYPE_FLAG_ANYOBJECT = 0x100, -#endif /* Mask containing all primitives */ TYPE_FLAG_PRIMITIVE = TYPE_FLAG_UNDEFINED | TYPE_FLAG_NULL | TYPE_FLAG_BOOLEAN | TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE | TYPE_FLAG_STRING | TYPE_FLAG_SYMBOL | - IF_BIGINT(TYPE_FLAG_BIGINT, 0), + TYPE_FLAG_BIGINT, /* Mask/shift for the number of objects in objectSet */ -#ifdef ENABLE_BIGINT TYPE_FLAG_OBJECT_COUNT_MASK = 0x3c00, TYPE_FLAG_OBJECT_COUNT_SHIFT = 10, -#else - TYPE_FLAG_OBJECT_COUNT_MASK = 0x3e00, - TYPE_FLAG_OBJECT_COUNT_SHIFT = 9, -#endif TYPE_FLAG_OBJECT_COUNT_LIMIT = 7, TYPE_FLAG_DOMOBJECT_COUNT_LIMIT = TYPE_FLAG_OBJECT_COUNT_MASK >> TYPE_FLAG_OBJECT_COUNT_SHIFT, @@ -396,9 +386,7 @@ class TypeSet { static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); } static inline Type StringType() { return Type(JSVAL_TYPE_STRING); } static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); } -#ifdef ENABLE_BIGINT static inline Type BigIntType() { return Type(JSVAL_TYPE_BIGINT); } -#endif static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); } static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); } static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); } diff --git a/js/src/vm/TypedArrayObject-inl.h b/js/src/vm/TypedArrayObject-inl.h index 24197c176ca8..476298d6b70a 100644 --- a/js/src/vm/TypedArrayObject-inl.h +++ b/js/src/vm/TypedArrayObject-inl.h @@ -614,7 +614,7 @@ class ElementSpecific { } double d; - MOZ_ASSERT(v.isString() || v.isObject() || v.isSymbol() || IF_BIGINT(v.isBigInt(), false)); + MOZ_ASSERT(v.isString() || v.isObject() || v.isSymbol() || v.isBigInt()); if (!(v.isString() ? StringToNumber(cx, v.toString(), &d) : ToNumber(cx, v, &d))) { return false; diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index 5b8befeae028..8bab8c0f4b01 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -23,9 +23,7 @@ #include "js/Utility.h" #include "js/Vector.h" #include "util/Text.h" -#ifdef ENABLE_BIGINT -# include "vm/BigIntType.h" -#endif +#include "vm/BigIntType.h" #include "vm/Debugger.h" #include "vm/EnvironmentObject.h" #include "vm/GlobalObject.h" @@ -179,13 +177,9 @@ Value Node::exposeToJS() const { v.setString(as()); } else if (is()) { v.setSymbol(as()); - } -#ifdef ENABLE_BIGINT - else if (is()) { + } else if (is()) { v.setBigInt(as()); - } -#endif - else { + } else { v.setUndefined(); } @@ -269,9 +263,7 @@ template JS::Zone* TracerConcrete::zone() const; template JS::Zone* TracerConcrete::zone() const; template JS::Zone* TracerConcrete::zone() const; template JS::Zone* TracerConcrete::zone() const; -#ifdef ENABLE_BIGINT template JS::Zone* TracerConcrete::zone() const; -#endif template JS::Zone* TracerConcrete::zone() const; template @@ -310,10 +302,8 @@ template UniquePtr TracerConcrete::edges( JSContext* cx, bool wantNames) const; template UniquePtr TracerConcrete::edges( JSContext* cx, bool wantNames) const; -#ifdef ENABLE_BIGINT template UniquePtr TracerConcrete::edges( JSContext* cx, bool wantNames) const; -#endif template UniquePtr TracerConcrete::edges( JSContext* cx, bool wantNames) const; @@ -380,9 +370,7 @@ Realm* Concrete::realm() const { } const char16_t Concrete::concreteTypeName[] = u"JS::Symbol"; -#ifdef ENABLE_BIGINT const char16_t Concrete::concreteTypeName[] = u"JS::BigInt"; -#endif const char16_t Concrete::concreteTypeName[] = u"JSScript"; const char16_t Concrete::concreteTypeName[] = u"js::LazyScript"; const char16_t Concrete::concreteTypeName[] = diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 13118b6322c4..ed683153a31f 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -749,16 +749,12 @@ bool xpc::ExtraWarningsForSystemJS() { return false; } static mozilla::Atomic sSharedMemoryEnabled(false); static mozilla::Atomic sStreamsEnabled(false); -#ifdef ENABLE_BIGINT static mozilla::Atomic sBigIntEnabled(false); -#endif void xpc::SetPrefableRealmOptions(JS::RealmOptions& options) { options.creationOptions() .setSharedMemoryAndAtomicsEnabled(sSharedMemoryEnabled) -#ifdef ENABLE_BIGINT .setBigIntEnabled(sBigIntEnabled) -#endif .setStreamsEnabled(sStreamsEnabled); } @@ -810,9 +806,7 @@ static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) { bool useAsyncStack = Preferences::GetBool(JS_OPTIONS_DOT_STR "asyncstack"); -#ifdef ENABLE_BIGINT sBigIntEnabled = Preferences::GetBool(JS_OPTIONS_DOT_STR "bigint"); -#endif bool throwOnDebuggeeWouldRun = Preferences::GetBool(JS_OPTIONS_DOT_STR "throw_on_debuggee_would_run"); diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h index ca3cc3f17850..9ee7cc1e46d1 100644 --- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -1018,14 +1018,12 @@ VARCACHE_PREF( RelaxedAtomicBool, false ) -#ifdef ENABLE_BIGINT // BigInt API VARCACHE_PREF( "javascript.options.bigint", javascript_options_bigint, RelaxedAtomicBool, false ) -#endif //--------------------------------------------------------------------------- From ae065c75a2cd37323c85f0e7339ab952a565d0dd Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Thu, 14 Feb 2019 15:22:24 +0000 Subject: [PATCH 24/84] Bug 1523272 - Use ClearDataService to clear site data in SiteDataManager.jsm. r=baku Differential Revision: https://phabricator.services.mozilla.com/D17870 --HG-- extra : moz-landing-system : lando --- browser/modules/SiteDataManager.jsm | 116 +++++++++++++--------------- 1 file changed, 54 insertions(+), 62 deletions(-) diff --git a/browser/modules/SiteDataManager.jsm b/browser/modules/SiteDataManager.jsm index 49ace509a68a..bb6305f6ab99 100644 --- a/browser/modules/SiteDataManager.jsm +++ b/browser/modules/SiteDataManager.jsm @@ -3,11 +3,6 @@ const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); -ChromeUtils.defineModuleGetter(this, "OfflineAppCacheHelper", - "resource://gre/modules/offlineAppCache.jsm"); -ChromeUtils.defineModuleGetter(this, "ServiceWorkerCleanUp", - "resource://gre/modules/ServiceWorkerCleanUp.jsm"); - var EXPORTED_SYMBOLS = [ "SiteDataManager", ]; @@ -325,6 +320,23 @@ var SiteDataManager = { site.cookies = []; }, + // Returns a list of permissions from the permission manager that + // we consider part of "site data and cookies". + _getDeletablePermissions() { + let perms = []; + let enumerator = Services.perms.enumerator; + + while (enumerator.hasMoreElements()) { + let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); + if (permission.type == "persistent-storage" || + permission.type == "storage-access") { + perms.push(permission); + } + } + + return perms; + }, + /** * Removes all site data for the specified list of hosts. * @@ -333,35 +345,28 @@ var SiteDataManager = { * manager has been updated. */ async remove(hosts) { - // Make sure we have up-to-date information. - await this._getQuotaUsage(); - this._updateAppCache(); - - let unknownHost = ""; + let perms = this._getDeletablePermissions(); let promises = []; for (let host of hosts) { - let site = this._sites.get(host); - if (site) { - // Clear localStorage & sessionStorage - Services.obs.notifyObservers(null, "extension:purge-localStorage", host); - Services.obs.notifyObservers(null, "browser:purge-sessionStorage", host); - this._removePermission(site); - this._removeAppCache(site); - this._removeCookies(site); - promises.push(ServiceWorkerCleanUp.removeFromHost(host)); - promises.push(this._removeQuotaUsage(site)); - } else { - unknownHost = host; - break; + promises.push(new Promise(function(resolve) { + Services.clearData.deleteDataFromHost(host, true, + Ci.nsIClearDataService.CLEAR_COOKIES | + Ci.nsIClearDataService.CLEAR_DOM_STORAGES | + Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS | + Ci.nsIClearDataService.CLEAR_PLUGIN_DATA | + Ci.nsIClearDataService.CLEAR_EME | + Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve); + })); + + for (let perm of perms) { + if (Services.eTLD.hasRootDomain(perm.principal.URI.host, host)) { + Services.perms.removePermission(perm); + } } } await Promise.all(promises); - if (unknownHost) { - throw `SiteDataManager: removing unknown site of ${unknownHost}`; - } - return this.updateSites(); }, @@ -405,54 +410,41 @@ var SiteDataManager = { * @returns a Promise that resolves when the data is cleared. */ async removeAll() { - this.removeCache(); + await this.removeCache(); return this.removeSiteData(); }, /** - * Clears the entire network cache. + * Clears all caches. + * + * @returns a Promise that resolves when the data is cleared. */ removeCache() { - Services.cache2.clear(); + return new Promise(function(resolve) { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve); + }); }, /** - * Clears all site data, which currently means - * - Cookies - * - AppCache - * - LocalStorage - * - ServiceWorkers - * - Quota Managed Storage - * - persistent-storage permissions + * Clears all site data, but not cache, because the UI offers + * that functionality separately. * - * @returns a Promise that resolves with the cache size on disk in bytes + * @returns a Promise that resolves when the data is cleared. */ async removeSiteData() { - // LocalStorage - Services.obs.notifyObservers(null, "extension:purge-localStorage"); + await new Promise(function(resolve) { + Services.clearData.deleteData( + Ci.nsIClearDataService.CLEAR_COOKIES | + Ci.nsIClearDataService.CLEAR_DOM_STORAGES | + Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS | + Ci.nsIClearDataService.CLEAR_EME | + Ci.nsIClearDataService.CLEAR_PLUGIN_DATA, resolve); + }); - Services.cookies.removeAll(); - OfflineAppCacheHelper.clear(); - - await ServiceWorkerCleanUp.removeAll(); - - // Refresh sites using quota usage again. - // This is for the case: - // 1. User goes to the about:preferences Site Data section. - // 2. With the about:preferences opened, user visits another website. - // 3. The website saves to quota usage, like indexedDB. - // 4. User goes back to the Site Data section and commands to clear all site data. - // For this case, we should refresh the site list so not to miss the website in the step 3. - // We don't do "Clear All" on the quota manager like the cookie, appcache, http cache above - // because that would clear browser data as well too, - // see https://bugzilla.mozilla.org/show_bug.cgi?id=1312361#c9 - this._sites.clear(); - await this._getQuotaUsage(); - let promises = []; - for (let site of this._sites.values()) { - this._removePermission(site); - promises.push(this._removeQuotaUsage(site)); + for (let permission of this._getDeletablePermissions()) { + Services.perms.removePermission(permission); } - return Promise.all(promises).then(() => this.updateSites()); + + return this.updateSites(); }, }; From 62dfb471d31e89e0a4d95e0eab88bc779ebc0878 Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Thu, 14 Feb 2019 15:22:37 +0000 Subject: [PATCH 25/84] Bug 1523272 - Add unit tests for the SiteDataManager. r=baku Differential Revision: https://phabricator.services.mozilla.com/D17871 --HG-- extra : moz-landing-system : lando --- .../test/sanitize/SiteDataTestUtils.jsm | 42 +++-- .../test/sanitize/browser_cookiePermission.js | 5 +- .../modules/test/unit/test_SiteDataManager.js | 148 ++++++++++++++++++ browser/modules/test/unit/xpcshell.ini | 1 + 4 files changed, 180 insertions(+), 16 deletions(-) create mode 100644 browser/modules/test/unit/test_SiteDataManager.js diff --git a/browser/base/content/test/sanitize/SiteDataTestUtils.jsm b/browser/base/content/test/sanitize/SiteDataTestUtils.jsm index af50a049b221..3e24dcb756ca 100644 --- a/browser/base/content/test/sanitize/SiteDataTestUtils.jsm +++ b/browser/base/content/test/sanitize/SiteDataTestUtils.jsm @@ -15,6 +15,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "swm", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager"); +XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]); + /** * This module assists with tasks around testing functionality that shows * or clears site data. @@ -25,31 +27,44 @@ XPCOMUtils.defineLazyServiceGetter(this, "swm", var SiteDataTestUtils = { /** - * Adds a new entry to a dummy indexedDB database for the specified origin. + * Makes an origin have persistent data storage. + * + * @param {String} origin - the origin of the site to give persistent storage + * + * @returns a Promise that resolves when storage was persisted + */ + persist(origin, value = Services.perms.ALLOW_ACTION) { + return new Promise(resolve => { + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + Services.perms.addFromPrincipal(principal, "persistent-storage", value); + Services.qms.persist(principal).callback = () => resolve(); + }); + }, + + /** + * Adds a new blob entry to a dummy indexedDB database for the specified origin. * * @param {String} origin - the origin of the site to add test data for - * @param {String} name [optional] - the entry key - * @param {String} value [optional] - the entry value - * @param {Object} originAttributes [optional] - the originAttributes + * @param {Number} size [optional] - the size of the entry in bytes * * @returns a Promise that resolves when the data was added successfully. */ - addToIndexedDB(origin, key = "foo", value = "bar", originAttributes = {}) { + addToIndexedDB(origin, size = 1024) { return new Promise(resolve => { - let uri = Services.io.newURI(origin); - let principal = - Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes); + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); let request = indexedDB.openForPrincipal(principal, "TestDatabase", 1); request.onupgradeneeded = function(e) { let db = e.target.result; - db.createObjectStore("TestStore", { keyPath: "id" }); + db.createObjectStore("TestStore"); }; request.onsuccess = function(e) { let db = e.target.result; let tx = db.transaction("TestStore", "readwrite"); let store = tx.objectStore("TestStore"); tx.oncomplete = resolve; - store.put({ id: key, description: value}); + let buffer = new ArrayBuffer(size); + let blob = new Blob([buffer]); + store.add(blob, Cu.now()); }; }); }, @@ -63,8 +78,8 @@ var SiteDataTestUtils = { * @param {String} value [optional] - the cookie value */ addToCookies(origin, name = "foo", value = "bar") { - let uri = Services.io.newURI(origin); - Services.cookies.add(uri.host, uri.pathQueryRef, name, value, + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + Services.cookies.add(principal.URI.host, principal.URI.pathQueryRef, name, value, false, false, false, Date.now() + 24000 * 60 * 60, {}, Ci.nsICookie2.SAMESITE_UNSET); }, @@ -121,8 +136,7 @@ var SiteDataTestUtils = { */ getQuotaUsage(origin) { return new Promise(resolve => { - let uri = Services.io.newURI(origin); - let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage)); }); }, diff --git a/browser/base/content/test/sanitize/browser_cookiePermission.js b/browser/base/content/test/sanitize/browser_cookiePermission.js index 74745dc07696..897c2e91b1fb 100644 --- a/browser/base/content/test/sanitize/browser_cookiePermission.js +++ b/browser/base/content/test/sanitize/browser_cookiePermission.js @@ -18,8 +18,9 @@ function checkDataForAboutURL() { } function createIndexedDB(host, originAttributes) { - return SiteDataTestUtils.addToIndexedDB("https://" + host, "foo", "bar", - originAttributes); + let uri = Services.io.newURI("https://" + host); + let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes); + return SiteDataTestUtils.addToIndexedDB(principal.origin); } function checkIndexedDB(host, originAttributes) { diff --git a/browser/modules/test/unit/test_SiteDataManager.js b/browser/modules/test/unit/test_SiteDataManager.js new file mode 100644 index 000000000000..d181b3eb9e59 --- /dev/null +++ b/browser/modules/test/unit/test_SiteDataManager.js @@ -0,0 +1,148 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +"use strict"; + +const EXAMPLE_ORIGIN = "https://www.example.com"; +const EXAMPLE_ORIGIN_2 = "https://example.org"; + +const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +const {SiteDataManager} = ChromeUtils.import("resource:///modules/SiteDataManager.jsm"); +const {SiteDataTestUtils} = ChromeUtils.import("resource://testing-common/SiteDataTestUtils.jsm"); +ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm"); +ChromeUtils.defineModuleGetter(this, "TestUtils", "resource://testing-common/TestUtils.jsm"); + +add_task(function setup() { + do_get_profile(); +}); + +add_task(async function testGetSites() { + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); + await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); + + await SiteDataManager.updateSites(); + + let sites = await SiteDataManager.getSites(); + + let site1 = sites.find((site) => site.baseDomain == "example.com"); + let site2 = sites.find((site) => site.baseDomain == "example.org"); + + Assert.equal(site1.baseDomain, "example.com", "Has the correct base domain for example.com"); + Assert.equal(site1.host, "www.example.com", "Has the correct host for example.com"); + Assert.greater(site1.usage, 4096, "Has correct usage for example.com"); + Assert.equal(site1.persisted, false, "example.com is not persisted"); + Assert.equal(site1.cookies.length, 2, "Has correct number of cookies for example.com"); + Assert.ok(typeof site1.lastAccessed.getDate == "function", "lastAccessed for example.com is a Date"); + Assert.ok(site1.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.com happened recently"); + + Assert.equal(site2.baseDomain, "example.org", "Has the correct base domain for example.org"); + Assert.equal(site2.host, "example.org", "Has the correct host for example.org"); + Assert.greater(site2.usage, 2048, "Has correct usage for example.org"); + Assert.equal(site2.persisted, true, "example.org is persisted"); + Assert.equal(site2.cookies.length, 1, "Has correct number of cookies for example.org"); + Assert.ok(typeof site2.lastAccessed.getDate == "function", "lastAccessed for example.org is a Date"); + Assert.ok(site2.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.org happened recently"); + + await SiteDataTestUtils.clear(); +}); + +add_task(async function testGetTotalUsage() { + await SiteDataManager.updateSites(); + let sites = await SiteDataManager.getSites(); + Assert.equal(sites.length, 0, "SiteDataManager is empty"); + + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); + + await SiteDataManager.updateSites(); + + let usage = await SiteDataManager.getTotalUsage(); + + Assert.greater(usage, 4096 + 2048, "Has the correct total usage."); + + await SiteDataTestUtils.clear(); +}); + +add_task(async function testRemove() { + await SiteDataManager.updateSites(); + + let uri = Services.io.newURI(EXAMPLE_ORIGIN); + Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION); + + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); + await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); + + await SiteDataManager.updateSites(); + + let sites = await SiteDataManager.getSites(); + + Assert.equal(sites.length, 2, "Has two sites."); + + await SiteDataManager.remove(["www.example.com"]); + + sites = await SiteDataManager.getSites(); + + Assert.equal(sites.length, 1, "Has one site."); + Assert.equal(sites[0].host, "example.org", "Has not cleared data for example.org"); + + let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN); + Assert.equal(usage, 0, "Has cleared quota usage for example.com"); + + let cookies = Services.cookies.countCookiesFromHost("example.com"); + Assert.equal(cookies, 0, "Has cleared cookies for example.com"); + + let perm = Services.perms.testPermission(uri, "persistent-storage"); + Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission."); + perm = Services.perms.testPermission(uri, "camera"); + Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions."); + + Services.perms.remove(uri, "camera"); +}); + +add_task(async function testRemoveSiteData() { + let uri = Services.io.newURI(EXAMPLE_ORIGIN); + Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION); + + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); + SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); + await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); + await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); + + await SiteDataManager.updateSites(); + + let sites = await SiteDataManager.getSites(); + + Assert.equal(sites.length, 2, "Has two sites."); + + await SiteDataManager.removeSiteData(); + + sites = await SiteDataManager.getSites(); + + Assert.equal(sites.length, 0, "Has no sites."); + + let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN); + Assert.equal(usage, 0, "Has cleared quota usage for example.com"); + + usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN_2); + Assert.equal(usage, 0, "Has cleared quota usage for example.org"); + + let cookies = Services.cookies.countCookiesFromHost("example.org"); + Assert.equal(cookies, 0, "Has cleared cookies for example.org"); + + let perm = Services.perms.testPermission(uri, "persistent-storage"); + Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission."); + perm = Services.perms.testPermission(uri, "camera"); + Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions."); + + Services.perms.remove(uri, "camera"); +}); diff --git a/browser/modules/test/unit/xpcshell.ini b/browser/modules/test/unit/xpcshell.ini index e934e2613ec9..75957a037d1c 100644 --- a/browser/modules/test/unit/xpcshell.ini +++ b/browser/modules/test/unit/xpcshell.ini @@ -8,5 +8,6 @@ skip-if = toolkit == 'android' [test_LiveBookmarkMigrator.js] [test_Sanitizer_interrupted.js] [test_SitePermissions.js] +[test_SiteDataManager.js] [test_LaterRun.js] [test_discovery.js] From f5219412e9f1fe7b7f61dab3f306747cc3ff3b89 Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Thu, 14 Feb 2019 15:22:49 +0000 Subject: [PATCH 26/84] Bug 1523272 - Remove mock code from about:preferences siteData tests. r=baku These tests used to mock out the SiteDataManager to test only the UI for things like removing site data or sorting. This bug breaks that possibility, because the SiteDataManager no longer uses its internal data to remove site data but delegates the logic to ClearSiteDataService. I don't think it's a loss, that mocking was always a little weird. Differential Revision: https://phabricator.services.mozilla.com/D18283 --HG-- extra : moz-landing-system : lando --- .../tests/siteData/browser_siteData2.js | 104 +++++---- .../tests/siteData/browser_siteData3.js | 212 +++++------------- .../siteData/browser_siteData_multi_select.js | 75 ++++--- .../in-content/tests/siteData/head.js | 77 ++----- 4 files changed, 169 insertions(+), 299 deletions(-) diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js index d8aed9b70131..e929c9c9d00c 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js @@ -12,8 +12,8 @@ function assertAllSitesNotListed(win) { } // Test selecting and removing all sites one by one -add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ +add_task(async function test_selectRemove() { + let hosts = await addTestData([ { usage: 1024, origin: "https://account.xyz.com", @@ -22,7 +22,6 @@ add_task(async function() { { usage: 1024, origin: "https://shopping.xyz.com", - persisted: false, }, { usage: 1024, @@ -32,12 +31,11 @@ add_task(async function() { { usage: 1024, origin: "http://email.bar.com", - persisted: false, }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -50,7 +48,7 @@ add_task(async function() { let settingsDialogClosePromise = null; // Test the initial state - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Cancel" button settingsDialogClosePromise = promiseSettingsDialogClose(); @@ -61,7 +59,7 @@ add_task(async function() { cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Save Changes" button but cancelling save let cancelPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel"); @@ -76,7 +74,7 @@ add_task(async function() { cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Save Changes" button and accepting save let acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept"); @@ -93,7 +91,7 @@ add_task(async function() { await openSiteDataSettingsDialog(); assertAllSitesNotListed(win); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); function removeAllSitesOneByOne() { @@ -109,8 +107,8 @@ add_task(async function() { }); // Test selecting and removing partial sites -add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ +add_task(async function test_removePartialSites() { + let hosts = await addTestData([ { usage: 1024, origin: "https://account.xyz.com", @@ -141,15 +139,10 @@ add_task(async function() { origin: "https://127.0.0.1", persisted: false, }, - { - usage: 1024, - origin: "https://[0:0:0:0:0:0:0:1]", - persisted: true, - }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -163,18 +156,18 @@ add_task(async function() { let settingsDialogClosePromise = null; // Test the initial state - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Cancel" button settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; cancelBtn = frameDoc.getElementById("cancel"); - removeSelectedSite(fakeHosts.slice(0, 2)); - assertSitesListed(doc, fakeHosts.slice(2)); + await removeSelectedSite(hosts.slice(0, 2)); + assertSitesListed(doc, hosts.slice(2)); cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Save Changes" button but canceling save removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel", REMOVE_DIALOG_URL); @@ -182,44 +175,49 @@ add_task(async function() { frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); cancelBtn = frameDoc.getElementById("cancel"); - removeSelectedSite(fakeHosts.slice(0, 2)); - assertSitesListed(doc, fakeHosts.slice(2)); + await removeSelectedSite(hosts.slice(0, 2)); + assertSitesListed(doc, hosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); // Test the "Save Changes" button and accepting save removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); - removeSelectedSite(fakeHosts.slice(0, 2)); - assertSitesListed(doc, fakeHosts.slice(2)); + await removeSelectedSite(hosts.slice(0, 2)); + assertSitesListed(doc, hosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts.slice(2)); + assertSitesListed(doc, hosts.slice(2)); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); - function removeSelectedSite(hosts) { + function removeSelectedSite(removeHosts) { frameDoc = win.gSubDialog._topDialog._frame.contentDocument; let removeBtn = frameDoc.getElementById("removeSelected"); is(removeBtn.disabled, true, "Should start with disabled removeSelected button"); let sitesList = frameDoc.getElementById("sitesList"); - hosts.forEach(host => { + removeHosts.forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); if (site) { site.click(); let currentSelectedIndex = sitesList.selectedIndex; is(removeBtn.disabled, false, "Should enable the removeSelected button"); removeBtn.doCommand(); - is(sitesList.selectedIndex, currentSelectedIndex); + let newSelectedIndex = sitesList.selectedIndex; + if (currentSelectedIndex >= sitesList.itemCount) { + is(newSelectedIndex, currentSelectedIndex - 1); + } else { + is(newSelectedIndex, currentSelectedIndex); + } } else { ok(false, `Should not select and remove inexistent site of ${host}`); } @@ -229,7 +227,7 @@ add_task(async function() { // Test searching and then removing only visible sites add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ + let hosts = await addTestData([ { usage: 1024, origin: "https://account.xyz.com", @@ -251,9 +249,9 @@ add_task(async function() { persisted: false, }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -265,7 +263,7 @@ add_task(async function() { let searchBox = frameDoc.getElementById("searchBox"); searchBox.value = "xyz"; searchBox.doCommand(); - assertSitesListed(doc, fakeHosts.filter(host => host.includes("xyz"))); + assertSitesListed(doc, hosts.filter(host => host.includes("xyz"))); // Test only removing all visible sites listed updatePromise = promiseSiteDataManagerSitesUpdated(); @@ -279,15 +277,15 @@ add_task(async function() { await settingsDialogClosePromise; await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts.filter(host => !host.includes("xyz"))); + assertSitesListed(doc, hosts.filter(host => !host.includes("xyz"))); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test dynamically clearing all site data add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ + let hosts = await addTestData([ { usage: 1024, origin: "https://account.xyz.com", @@ -299,28 +297,28 @@ add_task(async function() { persisted: false, }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); + + let updatePromise = promiseSiteDataManagerSitesUpdated(); // Test the initial state - let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let doc = gBrowser.selectedBrowser.contentDocument; - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); - // Add more sites dynamically - mockSiteDataManager.fakeSites.push({ - usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), - persisted: true, - }, { - usage: 1024, - principal: Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin("http://email.bar.com"), - persisted: false, - }); + await addTestData([ + { + usage: 1024, + origin: "http://cinema.bar.com", + persisted: true, + }, + { + usage: 1024, + origin: "http://email.bar.com", + persisted: false, + }, + ]); // Test clearing all site data dynamically let win = gBrowser.selectedBrowser.contentWindow; @@ -338,6 +336,6 @@ add_task(async function() { await openSiteDataSettingsDialog(); assertAllSitesNotListed(win); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js index 1fa44d79ef05..a0ca9dac28ff 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js @@ -1,8 +1,8 @@ "use strict"; // Test not displaying sites which store 0 byte and don't have persistent storage. -add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ +add_task(async function test_exclusions() { + let hosts = await addTestData([ { usage: 0, origin: "https://account.xyz.com", @@ -30,23 +30,22 @@ add_task(async function() { persisted: false, }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); let doc = gBrowser.selectedBrowser.contentDocument; await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com")); + assertSitesListed(doc, hosts.filter(host => host != "shopping.xyz.com")); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test grouping and listing sites across scheme, port and origin attributes by host -add_task(async function() { - const quotaUsage = 1024; - mockSiteDataManager.register(SiteDataManager, [ +add_task(async function test_grouping() { + let quotaUsage = 7000000; + await addTestData([ { usage: quotaUsage, origin: "https://account.xyz.com^userContextId=1", @@ -91,40 +90,51 @@ add_task(async function() { is(columns[1].value, "5", "Should group cookies across scheme, port and origin attributes"); - let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length); - Assert.deepEqual(frameDoc.l10n.getAttributes(columns[2]), { - id: "site-usage-persistent", - args: { value, unit }, - }, "Should sum up usages across scheme, port, origin attributes and persistent status"); + let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * 4); + let l10nAttributes = frameDoc.l10n.getAttributes(columns[2]); + is(l10nAttributes.id, "site-usage-persistent", + "Should show the site as persistent if one origin is persistent."); + // The shown quota can be slightly larger than the raw data we put in (though it should + // never be smaller), but that doesn't really matter to us since we only want to test that + // the site data dialog accumulates this into a single column. + ok(parseFloat(l10nAttributes.args.value) >= parseFloat(value), + "Should show the correct accumulated quota size."); + is(l10nAttributes.args.unit, unit, "Should show the correct quota size unit."); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test sorting -add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ +add_task(async function test_sorting() { + let testData = [ { + baseDomain: "xyz.com", usage: 1024, origin: "https://account.xyz.com", cookies: 6, persisted: true, }, { + baseDomain: "foo.com", usage: 1024 * 2, origin: "https://books.foo.com", cookies: 0, persisted: false, }, { + baseDomain: "bar.com", usage: 1024 * 3, origin: "http://cinema.bar.com", cookies: 3, persisted: true, }, - ]); + ]; + + await addTestData(testData); let updatePromise = promiseSiteDataManagerSitesUpdated(); + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -135,146 +145,42 @@ add_task(async function() { let hostCol = frameDoc.getElementById("hostCol"); let usageCol = frameDoc.getElementById("usageCol"); let cookiesCol = frameDoc.getElementById("cookiesCol"); - let sitesList = frameDoc.getElementById("sitesList"); - - // Test default sorting - assertSortByUsage("descending"); - - // Test sorting on the usage column - usageCol.click(); - assertSortByUsage("ascending"); - usageCol.click(); - assertSortByUsage("descending"); - - // Test sorting on the host column - hostCol.click(); - assertSortByBaseDomain("ascending"); - hostCol.click(); - assertSortByBaseDomain("descending"); - - // Test sorting on the cookies column - cookiesCol.click(); - assertSortByCookies("ascending"); - cookiesCol.click(); - assertSortByCookies("descending"); - - await mockSiteDataManager.unregister(); - BrowserTestUtils.removeTab(gBrowser.selectedTab); - - function assertSortByBaseDomain(order) { - let siteItems = sitesList.getElementsByTagName("richlistitem"); - for (let i = 0; i < siteItems.length - 1; ++i) { - let aHost = siteItems[i].getAttribute("host"); - let bHost = siteItems[i + 1].getAttribute("host"); - let a = findSiteByHost(aHost); - let b = findSiteByHost(bHost); - let result = a.baseDomain.localeCompare(b.baseDomain); - if (order == "ascending") { - Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host"); - } else { - Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host"); - } - } - } - - function assertSortByUsage(order) { - let siteItems = sitesList.getElementsByTagName("richlistitem"); - for (let i = 0; i < siteItems.length - 1; ++i) { - let aHost = siteItems[i].getAttribute("host"); - let bHost = siteItems[i + 1].getAttribute("host"); - let a = findSiteByHost(aHost); - let b = findSiteByHost(bHost); - let result = a.usage - b.usage; - if (order == "ascending") { - Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage"); - } else { - Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage"); - } - } - } - - function assertSortByCookies(order) { - let siteItems = sitesList.getElementsByTagName("richlistitem"); - for (let i = 0; i < siteItems.length - 1; ++i) { - let aHost = siteItems[i].getAttribute("host"); - let bHost = siteItems[i + 1].getAttribute("host"); - let a = findSiteByHost(aHost); - let b = findSiteByHost(bHost); - let result = a.cookies.length - b.cookies.length; - if (order == "ascending") { - Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies"); - } else { - Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies"); - } - } - } - - function findSiteByHost(host) { - return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); - } -}); - -// Test sorting based on access date (separate from cookies for simplicity, -// since cookies access date affects this as well, but we don't mock our cookies) -add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ - { - usage: 1024, - origin: "https://account.xyz.com", - persisted: true, - lastAccessed: (Date.now() - 120 * 1000) * 1000, - }, - { - usage: 1024 * 2, - origin: "https://books.foo.com", - persisted: false, - lastAccessed: (Date.now() - 240 * 1000) * 1000, - }, - { - usage: 1024 * 3, - origin: "http://cinema.bar.com", - persisted: true, - lastAccessed: Date.now() * 1000, - }, - ]); - - let updatePromise = promiseSiteDataManagerSitesUpdated(); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); - await updatePromise; - await openSiteDataSettingsDialog(); - - let dialog = content.gSubDialog._topDialog; - let dialogFrame = dialog._frame; - let frameDoc = dialogFrame.contentDocument; let lastAccessedCol = frameDoc.getElementById("lastAccessedCol"); let sitesList = frameDoc.getElementById("sitesList"); - // Test sorting on the date column - lastAccessedCol.click(); - assertSortByDate("ascending"); - lastAccessedCol.click(); - assertSortByDate("descending"); - - await mockSiteDataManager.unregister(); - BrowserTestUtils.removeTab(gBrowser.selectedTab); - - function assertSortByDate(order) { + function getHostOrder() { let siteItems = sitesList.getElementsByTagName("richlistitem"); - for (let i = 0; i < siteItems.length - 1; ++i) { - let aHost = siteItems[i].getAttribute("host"); - let bHost = siteItems[i + 1].getAttribute("host"); - let a = findSiteByHost(aHost); - let b = findSiteByHost(bHost); - let result = a.lastAccessed - b.lastAccessed; - if (order == "ascending") { - Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by date"); - } else { - Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order date"); - } - } + return Array.from(siteItems).map(item => item.getAttribute("host")); } - function findSiteByHost(host) { - return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); - } + // Test default sorting by usage, descending. + Assert.deepEqual(getHostOrder(), + ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage"); + + // Test sorting on the usage column + usageCol.click(); + Assert.deepEqual(getHostOrder(), + ["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted ascending by usage"); + usageCol.click(); + Assert.deepEqual(getHostOrder(), + ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage"); + + // Test sorting on the host column + hostCol.click(); + Assert.deepEqual(getHostOrder(), + ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted ascending by base domain"); + hostCol.click(); + Assert.deepEqual(getHostOrder(), + ["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted descending by base domain"); + + // Test sorting on the cookies column + cookiesCol.click(); + Assert.deepEqual(getHostOrder(), + ["books.foo.com", "cinema.bar.com", "account.xyz.com"], "Has sorted ascending by cookies"); + cookiesCol.click(); + Assert.deepEqual(getHostOrder(), + ["account.xyz.com", "cinema.bar.com", "books.foo.com"], "Has sorted descending by cookies"); + + await SiteDataTestUtils.clear(); + BrowserTestUtils.removeTab(gBrowser.selectedTab); }); diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js index 34266fb22b14..aecf10ff539a 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js @@ -2,44 +2,40 @@ // Test selecting and removing partial sites add_task(async function() { - mockSiteDataManager.register(SiteDataManager, [ - { - usage: 1024, - origin: "https://account.xyz.com", - persisted: true, - }, - { - usage: 1024, - origin: "https://shopping.xyz.com", - persisted: false, - }, - { - usage: 1024, - origin: "http://cinema.bar.com", - persisted: true, - }, - { - usage: 1024, - origin: "http://email.bar.com", - persisted: false, - }, - { - usage: 1024, - origin: "https://s3-us-west-2.amazonaws.com", - persisted: true, - }, + await SiteDataTestUtils.clear(); + + let hosts = await addTestData([ { usage: 1024, origin: "https://127.0.0.1", persisted: false, }, { - usage: 1024, - origin: "https://[0:0:0:0:0:0:0:1]", + usage: 1024 * 4, + origin: "http://cinema.bar.com", persisted: true, }, + { + usage: 1024 * 3, + origin: "http://email.bar.com", + persisted: false, + }, + { + usage: 1024 * 2, + origin: "https://s3-us-west-2.amazonaws.com", + persisted: true, + }, + { + usage: 1024 * 6, + origin: "https://account.xyz.com", + persisted: true, + }, + { + usage: 1024 * 5, + origin: "https://shopping.xyz.com", + persisted: false, + }, ]); - let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); @@ -49,18 +45,21 @@ add_task(async function() { let doc = gBrowser.selectedBrowser.contentDocument; // Test the initial state - assertSitesListed(doc, fakeHosts); + assertSitesListed(doc, hosts); let win = gBrowser.selectedBrowser.contentWindow; let frameDoc = win.gSubDialog._topDialog._frame.contentDocument; let removeBtn = frameDoc.getElementById("removeSelected"); is(removeBtn.disabled, true, "Should start with disabled removeSelected button"); + let hostCol = frameDoc.getElementById("hostCol"); + hostCol.click(); + let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL); let settingsDialogClosePromise = promiseSettingsDialogClose(); // Select some sites to remove. let sitesList = frameDoc.getElementById("sitesList"); - fakeHosts.slice(0, 2).forEach(host => { + hosts.slice(0, 2).forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); sitesList.addItemToSelection(site); }); @@ -68,10 +67,10 @@ add_task(async function() { is(removeBtn.disabled, false, "Should enable the removeSelected button"); removeBtn.doCommand(); is(sitesList.selectedIndex, 0, "Should select next item"); - assertSitesListed(doc, fakeHosts.slice(2)); + assertSitesListed(doc, hosts.slice(2)); // Select some other sites to remove with Delete. - fakeHosts.slice(2, 4).forEach(host => { + hosts.slice(2, 4).forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); sitesList.addItemToSelection(site); }); @@ -79,17 +78,21 @@ add_task(async function() { is(removeBtn.disabled, false, "Should enable the removeSelected button"); EventUtils.synthesizeKey("VK_DELETE"); is(sitesList.selectedIndex, 0, "Should select next item"); - assertSitesListed(doc, fakeHosts.slice(4)); + assertSitesListed(doc, hosts.slice(4)); + updatePromise = promiseSiteDataManagerSitesUpdated(); let saveBtn = frameDoc.getElementById("save"); saveBtn.doCommand(); await removeDialogOpenPromise; await settingsDialogClosePromise; + + await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, fakeHosts.slice(4)); + assertSitesListed(doc, hosts.slice(4)); - await mockSiteDataManager.unregister(); + await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); + diff --git a/browser/components/preferences/in-content/tests/siteData/head.js b/browser/components/preferences/in-content/tests/siteData/head.js index ed66b3d58467..4762a8ed30fa 100644 --- a/browser/components/preferences/in-content/tests/siteData/head.js +++ b/browser/components/preferences/in-content/tests/siteData/head.js @@ -127,66 +127,29 @@ function assertSitesListed(doc, hosts) { is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button"); } -const mockSiteDataManager = { +async function addTestData(data) { + let hosts = []; - _SiteDataManager: null, - _originalQMS: null, - _originalRemoveQuotaUsage: null, - - getUsage(onUsageResult) { - let result = this.fakeSites.map(site => ({ - origin: site.principal.origin, - usage: site.usage, - persisted: site.persisted, - lastAccessed: site.lastAccessed, - })); - onUsageResult({ result, resultCode: Cr.NS_OK }); - }, - - _removeQuotaUsage(site) { - var target = site.principals[0].URI.host; - this.fakeSites = this.fakeSites.filter(fakeSite => { - return fakeSite.principal.URI.host != target; - }); - }, - - register(siteDataManager, fakeSites) { - this._SiteDataManager = siteDataManager; - this._originalQMS = this._SiteDataManager._qms; - this._SiteDataManager._qms = this; - this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage; - this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this); - // Add some fake data. - this.fakeSites = fakeSites; - for (let site of fakeSites) { - if (!site.principal) { - site.principal = Services.scriptSecurityManager - .createCodebasePrincipalFromOrigin(site.origin); - } - - let uri = site.principal.URI; - try { - site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host); - } catch (e) { - site.baseDomain = uri.host; - } - - // Add some cookies if needed. - for (let i = 0; i < (site.cookies || 0); i++) { - Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i, - false, false, false, Date.now() + 1000 * 60 * 60, {}, - Ci.nsICookie2.SAMESITE_UNSET); - } + for (let site of data) { + is(typeof site.origin, "string", "Passed an origin string into addTestData."); + if (site.persisted) { + await SiteDataTestUtils.persist(site.origin); } - }, - async unregister() { - await this._SiteDataManager.removeAll(); - this.fakeSites = null; - this._SiteDataManager._qms = this._originalQMS; - this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage; - }, -}; + if (site.usage) { + await SiteDataTestUtils.addToIndexedDB(site.origin, site.usage); + } + + for (let i = 0; i < (site.cookies || 0); i++) { + SiteDataTestUtils.addToCookies(site.origin, Cu.now()); + } + + let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(site.origin); + hosts.push(principal.URI.host); + } + + return hosts; +} function promiseCookiesCleared() { return TestUtils.topicObserved("cookie-changed", (subj, data) => { From 0656b8e18927e4b3b0dd3153c5b6bd11b536c0d8 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:12:49 +0000 Subject: [PATCH 27/84] Bug 1522637 - Part 1: Disable in tests for allowLinkedWebInFileUriProcess, r=bobowen Differential Revision: https://phabricator.services.mozilla.com/D18602 --HG-- extra : moz-landing-system : lando --- .../test/tabs/browser_new_web_tab_in_file_process_pref.js | 1 + dom/ipc/WindowGlobalChild.h | 1 + 2 files changed, 2 insertions(+) diff --git a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js index fa3166099640..31948fe20feb 100644 --- a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js +++ b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js @@ -24,6 +24,7 @@ add_task(async function() { await SpecialPowers.pushPrefEnv( {set: [["browser.tabs.remote.separateFileUriProcess", true], ["browser.tabs.remote.allowLinkedWebInFileUriProcess", true], + ["browser.tabs.remote.useHTTPResponseProcessSelection", false], ["dom.ipc.processCount.file", 2]]}); // Open file:// page. diff --git a/dom/ipc/WindowGlobalChild.h b/dom/ipc/WindowGlobalChild.h index 2910e75b8fd3..5f1fe5b953ce 100644 --- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -20,6 +20,7 @@ namespace dom { class BrowsingContext; class WindowGlobalParent; class JSWindowActorChild; +class TabChild; /** * Actor for a single nsGlobalWindowInner. This actor is used to communicate From 530fa8e29b29c525b226f88419d7d3eea22aa42b Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:12:51 +0000 Subject: [PATCH 28/84] Bug 1522637 - Part 2: Include BrowsingContextID in LoadInfo for subdocument loads, r=valentin Depends on D18602 Differential Revision: https://phabricator.services.mozilla.com/D18603 --HG-- extra : moz-landing-system : lando --- .../components/sessionstore/SessionStore.jsm | 14 ++++++++----- ipc/glue/BackgroundUtils.cpp | 4 +++- netwerk/base/LoadInfo.cpp | 20 ++++++++++++++++++- netwerk/base/LoadInfo.h | 3 ++- netwerk/base/nsILoadInfo.idl | 7 +++++++ netwerk/ipc/NeckoChannelParams.ipdlh | 1 + 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index a3d092977e0a..5b3580ad8bf0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -2323,13 +2323,17 @@ var SessionStoreInternal = { return; // Not a document load. } - let browsingContext = aChannel.loadInfo.browsingContext; - if (!browsingContext) { - return; // Not loading in a browsing context. + let cpType = aChannel.loadInfo.externalContentPolicyType; + let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT; + if (!toplevel) { + return; // Not loading a toplevel document. } - if (browsingContext.parent) { - return; // Not a toplevel load, can't flip procs. + let browsingContext = toplevel + ? aChannel.loadInfo.browsingContext + : aChannel.loadInfo.frameBrowsingContext; + if (!browsingContext) { + return; // Not loading in a browsing context. } // Get principal for a document already loaded in the BrowsingContext. diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 9c7ed8a07ae9..85250564d2c2 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -477,6 +477,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetTopOuterWindowID(), aLoadInfo->GetFrameOuterWindowID(), aLoadInfo->GetBrowsingContextID(), + aLoadInfo->GetFrameBrowsingContextID(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetIsDocshellReload(), aLoadInfo->GetSendCSPViolationEvents(), aLoadInfo->GetOriginAttributes(), @@ -634,7 +635,8 @@ nsresult LoadInfoArgsToLoadInfo( loadInfoArgs.forceInheritPrincipalDropped(), loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), loadInfoArgs.parentOuterWindowID(), loadInfoArgs.topOuterWindowID(), loadInfoArgs.frameOuterWindowID(), - loadInfoArgs.browsingContextID(), loadInfoArgs.initialSecurityCheckDone(), + loadInfoArgs.browsingContextID(), loadInfoArgs.frameBrowsingContextID(), + loadInfoArgs.initialSecurityCheckDone(), loadInfoArgs.isInThirdPartyContext(), loadInfoArgs.isDocshellReload(), loadInfoArgs.sendCSPViolationEvents(), loadInfoArgs.originAttributes(), redirectChainIncludingInternalRedirects, redirectChain, diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index a35b8ce525b7..0e381e396378 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -80,6 +80,7 @@ LoadInfo::LoadInfo( mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), + mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), mIsDocshellReload(false), @@ -230,6 +231,9 @@ LoadInfo::LoadInfo( nsCOMPtr outerWindow = do_GetInterface(docShell); if (outerWindow) { mFrameOuterWindowID = outerWindow->WindowID(); + + RefPtr bc = outerWindow->GetBrowsingContext(); + mFrameBrowsingContextID = bc ? bc->Id() : 0; } } } @@ -362,6 +366,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), + mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), // NB: TYPE_DOCUMENT implies !third-party. mIsDocshellReload(false), @@ -500,7 +505,7 @@ LoadInfo::LoadInfo( bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, + uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyContext, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -543,6 +548,7 @@ LoadInfo::LoadInfo( mTopOuterWindowID(aTopOuterWindowID), mFrameOuterWindowID(aFrameOuterWindowID), mBrowsingContextID(aBrowsingContextID), + mFrameBrowsingContextID(aFrameBrowsingContextID), mInitialSecurityCheckDone(aInitialSecurityCheckDone), mIsThirdPartyContext(aIsThirdPartyContext), mIsDocshellReload(aIsDocshellReload), @@ -993,12 +999,24 @@ LoadInfo::GetBrowsingContextID(uint64_t* aResult) { return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetFrameBrowsingContextID(uint64_t* aResult) { + *aResult = mFrameBrowsingContextID; + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetBrowsingContext(dom::BrowsingContext** aResult) { *aResult = BrowsingContext::Get(mBrowsingContextID).take(); return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetFrameBrowsingContext(dom::BrowsingContext** aResult) { + *aResult = BrowsingContext::Get(mFrameBrowsingContextID).take(); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetScriptableOriginAttributes( JSContext* aCx, JS::MutableHandle aOriginAttributes) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 851602553ebe..15c016d5f850 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -111,7 +111,7 @@ class LoadInfo final : public nsILoadInfo { bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, + uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyRequest, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -184,6 +184,7 @@ class LoadInfo final : public nsILoadInfo { uint64_t mTopOuterWindowID; uint64_t mFrameOuterWindowID; uint64_t mBrowsingContextID; + uint64_t mFrameBrowsingContextID; bool mInitialSecurityCheckDone; bool mIsThirdPartyContext; bool mIsDocshellReload; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 6a8ba66c1a47..9c98c654fd60 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -634,6 +634,13 @@ interface nsILoadInfo : nsISupports [infallible] readonly attribute unsigned long long browsingContextID; readonly attribute BrowsingContext browsingContext; + /** + * Like `frameOuterWindowID`, however returning the BrowsingContextID + * instead. + */ + [infallible] readonly attribute unsigned long long frameBrowsingContextID; + readonly attribute BrowsingContext frameBrowsingContext; + /** * Resets the PrincipalToInherit to a freshly created NullPrincipal * which inherits the origin attributes from the loadInfo. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 267f9ea22aaa..08a92c60b5e7 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -64,6 +64,7 @@ struct LoadInfoArgs uint64_t topOuterWindowID; uint64_t frameOuterWindowID; uint64_t browsingContextID; + uint64_t frameBrowsingContextID; bool initialSecurityCheckDone; bool isInThirdPartyContext; bool isDocshellReload; From 438cbbeca174bcc1a82c939c1039c16be66dc991 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:36:02 +0000 Subject: [PATCH 29/84] Bug 1522637 - Part 3: Send history index when resuming redirected loads, r=qdot Depends on D18603 Differential Revision: https://phabricator.services.mozilla.com/D18604 --HG-- extra : moz-landing-system : lando --- .../sessionstore/ContentRestore.jsm | 3 +- .../components/sessionstore/SessionStore.jsm | 8 ++++ browser/components/sessionstore/TabState.jsm | 4 ++ docshell/base/nsDocShell.cpp | 38 ++++++++++++++----- docshell/base/nsIWebNavigation.idl | 6 ++- docshell/shistory/nsISHistory.idl | 8 ++++ docshell/shistory/nsSHistory.cpp | 6 +++ toolkit/components/browser/nsWebBrowser.cpp | 5 ++- .../modules/sessionstore/SessionHistory.jsm | 7 +++- 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/browser/components/sessionstore/ContentRestore.jsm b/browser/components/sessionstore/ContentRestore.jsm index b9d2b8449758..ce339b25a306 100644 --- a/browser/components/sessionstore/ContentRestore.jsm +++ b/browser/components/sessionstore/ContentRestore.jsm @@ -186,7 +186,8 @@ ContentRestoreInternal.prototype = { // If the load was started in another process, and the in-flight channel // was redirected into this process, resume that load within our process. if (loadArguments.redirectLoadSwitchId) { - webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId); + webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId, + loadArguments.redirectHistoryIndex); return true; } diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 5b3580ad8bf0..49b111ecd7c0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3235,6 +3235,14 @@ var SessionStoreInternal = { tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length)); } else { options.loadArguments = loadArguments; + + // If we're resuming a load which has been redirected from another + // process, record the history index which is currently being requested. + // It has to be offset by 1 to get back to native history indices from + // SessionStore history indicies. + if (loadArguments.redirectLoadSwitchId) { + loadArguments.redirectHistoryIndex = tabState.requestedIndex - 1; + } } // Need to reset restoring tabs. diff --git a/browser/components/sessionstore/TabState.jsm b/browser/components/sessionstore/TabState.jsm index 442e51362cd4..054bf7a68f9c 100644 --- a/browser/components/sessionstore/TabState.jsm +++ b/browser/components/sessionstore/TabState.jsm @@ -184,6 +184,10 @@ var TabStateInternal = { if (value.hasOwnProperty("index")) { tabData.index = value.index; } + + if (value.hasOwnProperty("requestedIndex")) { + tabData.requestedIndex = value.requestedIndex; + } } else { tabData[key] = value; } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 600955aa18be..ff67dd438ab3 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -12993,21 +12993,39 @@ nsDocShell::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier) { +nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { RefPtr self = this; RefPtr cpcl = ChildProcessChannelListener::GetSingleton(); // Call into InternalLoad with the pending channel when it is received. - cpcl->RegisterCallback(aIdentifier, [self](nsIChildChannel* aChannel) { - RefPtr loadState; - nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( - aChannel, getter_AddRefs(loadState)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - self->InternalLoad(loadState, nullptr, nullptr); - }); + cpcl->RegisterCallback( + aIdentifier, [self, aHistoryIndex](nsIChildChannel* aChannel) { + RefPtr loadState; + nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( + aChannel, getter_AddRefs(loadState)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + // If we're performing a history load, locate the correct history entry, + // and set the relevant bits on our loadState. + if (aHistoryIndex >= 0) { + nsCOMPtr legacySHistory = + self->mSessionHistory->LegacySHistory(); + + nsCOMPtr entry; + rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, + getter_AddRefs(entry)); + if (NS_SUCCEEDED(rv)) { + legacySHistory->InternalSetRequestedIndex(aHistoryIndex); + loadState->SetLoadType(LOAD_HISTORY); + loadState->SetSHEntry(entry); + } + } + + self->InternalLoad(loadState, nullptr, nullptr); + }); return NS_OK; } diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl index e7e38809de7b..cabae3f31d0f 100644 --- a/docshell/base/nsIWebNavigation.idl +++ b/docshell/base/nsIWebNavigation.idl @@ -342,6 +342,10 @@ interface nsIWebNavigation : nsISupports /** * Resume a load which has been redirected from another process. + * + * A negative |aHistoryIndex| value corresponds to a non-history load being + * resumed. */ - void resumeRedirectedLoad(in unsigned long long aLoadIdentifier); + void resumeRedirectedLoad(in unsigned long long aLoadIdentifier, + in long aHistoryIndex); }; diff --git a/docshell/shistory/nsISHistory.idl b/docshell/shistory/nsISHistory.idl index 73747d978986..429947d77124 100644 --- a/docshell/shistory/nsISHistory.idl +++ b/docshell/shistory/nsISHistory.idl @@ -52,6 +52,14 @@ interface nsISHistory: nsISupports */ [infallible] readonly attribute long requestedIndex; + /** + * Artifically set the |requestedIndex| for this nsISHEntry to the given + * index. This is used when resuming a cross-process load from a different + * process. + */ + [noscript, notxpcom] + void internalSetRequestedIndex(in long aRequestedIndex); + /** * Get the history entry at a given index. Returns non-null on success. * diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index e5ab98e0a839..2ebe5eab1e3d 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -626,6 +626,12 @@ nsSHistory::GetRequestedIndex(int32_t* aResult) { return NS_OK; } +NS_IMETHODIMP_(void) +nsSHistory::InternalSetRequestedIndex(int32_t aRequestedIndex) { + MOZ_ASSERT(aRequestedIndex >= -1 && aRequestedIndex < Length()); + mRequestedIndex = aRequestedIndex; +} + NS_IMETHODIMP nsSHistory::GetEntryAtIndex(int32_t aIndex, nsISHEntry** aResult) { NS_ENSURE_ARG_POINTER(aResult); diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp index 98fa6c90daf7..7a8bbe3330a4 100644 --- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -579,8 +579,9 @@ nsWebBrowser::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier) { - return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier); +nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier, + int32_t aHistoryIndex) { + return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier, aHistoryIndex); } NS_IMETHODIMP diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm index 110aabbb835a..60b158a9845d 100644 --- a/toolkit/modules/sessionstore/SessionHistory.jsm +++ b/toolkit/modules/sessionstore/SessionHistory.jsm @@ -76,7 +76,12 @@ var SessionHistoryInternal = { let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); let history = webNavigation.sessionHistory; - let data = {entries: [], userContextId: loadContext.originAttributes.userContextId }; + let data = { + entries: [], + userContextId: loadContext.originAttributes.userContextId, + requestedIndex: history.legacySHistory.requestedIndex + 1, + }; + // We want to keep track how many entries we *could* have collected and // how many we skipped, so we can sanitiy-check the current history index // and also determine whether we need to get any fallback data or not. From 60ebf8f8f0d5880356f00dc3f79d75e12231117e Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:01 +0000 Subject: [PATCH 30/84] Bug 1522637 - Part 4: Support browsers in globals without gMultiProcessBrowser, r=qdot Depends on D18604 Differential Revision: https://phabricator.services.mozilla.com/D18605 --HG-- extra : moz-landing-system : lando --- .../components/sessionstore/SessionStore.jsm | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 49b111ecd7c0..3e920df6cee0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -2286,6 +2286,8 @@ var SessionStoreInternal = { * processes. */ async _doProcessSwitch(aBrowser, aRemoteType, aChannel, aSwitchId) { + debug(`[process-switch]: performing switch from ${aBrowser.remoteType} to ${aRemoteType}`); + // Don't try to switch tabs before delayed startup is completed. await aBrowser.ownerGlobal.delayedStartupPromise; @@ -2309,7 +2311,9 @@ var SessionStoreInternal = { } // Tell our caller to redirect the load into this newly created process. - return aBrowser.frameLoader.tabParent; + let tabParent = aBrowser.frameLoader.tabParent; + debug(`[process-switch]: new tabID: ${tabParent.tabId}`); + return tabParent; }, // Examine the channel response to see if we should change the process @@ -2323,17 +2327,21 @@ var SessionStoreInternal = { return; // Not a document load. } + // Check that this is a toplevel document load. let cpType = aChannel.loadInfo.externalContentPolicyType; let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT; if (!toplevel) { - return; // Not loading a toplevel document. + debug(`[process-switch]: non-toplevel - ignoring`); + return; } + // Check that the document has a corresponding BrowsingContext. let browsingContext = toplevel ? aChannel.loadInfo.browsingContext : aChannel.loadInfo.frameBrowsingContext; if (!browsingContext) { - return; // Not loading in a browsing context. + debug(`[process-switch]: no BrowsingContext - ignoring`); + return; } // Get principal for a document already loaded in the BrowsingContext. @@ -2342,34 +2350,60 @@ var SessionStoreInternal = { currentPrincipal = browsingContext.currentWindowGlobal.documentPrincipal; } - let parentChannel = aChannel.notificationCallbacks - .getInterface(Ci.nsIParentChannel); - if (!parentChannel) { - return; // Not an actor channel + // Ensure we have an nsIParentChannel listener for a remote load. + let parentChannel; + try { + parentChannel = aChannel.notificationCallbacks + .getInterface(Ci.nsIParentChannel); + } catch (e) { + debug(`[process-switch]: No nsIParentChannel callback - ignoring`); + return; } - let tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsITabParent); - if (!tabParent || !tabParent.ownerElement) { - console.warn("warning: Missing tabParent"); - return; // Not an embedded browsing context + // Ensure we have a nsITabParent for our remote load. + let tabParent; + try { + tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsITabParent); + } catch (e) { + debug(`[process-switch]: No nsITabParent for channel - ignoring`); + return; } + // Ensure we're loaded in a regular tabbrowser environment, and can swap processes. let browser = tabParent.ownerElement; - if (browser.tagName !== "browser") { - console.warn("warning: Not a xul:browser element:", browser.tagName); - return; // Not a vanilla xul:browser element performing embedding. + if (!browser) { + debug(`[process-switch]: TabParent has no ownerElement - ignoring`); } + let tabbrowser = browser.ownerGlobal.gBrowser; + if (!tabbrowser) { + debug(`[process-switch]: cannot find tabbrowser for loading tab - ignoring`); + return; + } + + let tab = tabbrowser.getTabForBrowser(browser); + if (!tab) { + debug(`[process-switch]: not a normal tab, so cannot swap processes - ignoring`); + return; + } + + // Determine the process type the load should be performed in. let resultPrincipal = Services.scriptSecurityManager.getChannelResultPrincipal(aChannel); - let useRemoteTabs = browser.ownerGlobal.gMultiProcessBrowser; let remoteType = E10SUtils.getRemoteTypeForPrincipal(resultPrincipal, - useRemoteTabs, + true, browser.remoteType, currentPrincipal); if (browser.remoteType == remoteType) { - return; // Already in compatible process. + debug(`[process-switch]: type (${remoteType}) is compatible - ignoring`); + return; + } + + if (remoteType == E10SUtils.NOT_REMOTE || + browser.remoteType == E10SUtils.NOT_REMOTE) { + debug(`[process-switch]: non-remote source/target - ignoring`); + return; } // ------------------------------------------------------------------------ From 6599de014169ba8d1c373dfda4e6439f490bde4d Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:03 +0000 Subject: [PATCH 31/84] Bug 1522637 - Part 5: Add tests for history navigations between http and file URIs with new pref, r=qdot Depends on D18605 Differential Revision: https://phabricator.services.mozilla.com/D18606 --HG-- extra : moz-landing-system : lando --- .../tests/browser/browser.ini | 2 + .../browser_httpResponseProcessSelection.js | 16 --- .../browser/browser_httpToFileHistory.js | 99 +++++++++++++++++++ .../remotebrowserutils/tests/browser/head.js | 15 +++ 4 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js create mode 100644 toolkit/components/remotebrowserutils/tests/browser/head.js diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser.ini b/toolkit/components/remotebrowserutils/tests/browser/browser.ini index b55376c4d462..06834883e246 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser.ini +++ b/toolkit/components/remotebrowserutils/tests/browser/browser.ini @@ -4,6 +4,8 @@ support-files = dummy_page.html print_postdata.sjs 307redirect.sjs + head.js [browser_RemoteWebNavigation.js] [browser_httpResponseProcessSelection.js] +[browser_httpToFileHistory.js] diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js index 859555b9764a..1f0f0031093c 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js +++ b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js @@ -2,22 +2,6 @@ const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); let PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; -function fileURL(filename) { - let ifile = getChromeDir(getResolvedURI(gTestPath)); - ifile.append(filename); - return Services.io.newFileURI(ifile).spec; -} - -function httpURL(filename, host = "https://example.com/") { - let root = getRootDirectory(gTestPath) - .replace("chrome://mochitests/content/", host); - return root + filename; -} - -function add307(url, host = "https://example.com/") { - return httpURL("307redirect.sjs?" + url, host); -} - async function performLoad(browser, opts, action) { let loadedPromise = BrowserTestUtils.browserLoaded( browser, false, opts.url, opts.maybeErrorPage); diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js new file mode 100644 index 000000000000..495a6979d4cc --- /dev/null +++ b/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js @@ -0,0 +1,99 @@ +const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); + +const PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; +const HISTORY = [ + {url: httpURL("dummy_page.html")}, + {url: fileURL("dummy_page.html")}, + {url: httpURL("dummy_page.html")}, +]; + +function reversed(list) { + let copy = list.slice(); + copy.reverse(); + return copy; +} + +function butLast(list) { + let copy = list.slice(); + copy.pop(); + return copy; +} + +async function runTest() { + await BrowserTestUtils.withNewTab({gBrowser}, async function(aBrowser) { + // Perform initial load of each URL in the history. + let count = 0; + let index = -1; + for (let {url} of HISTORY) { + BrowserTestUtils.loadURI(aBrowser, url); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + count++; + index++; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Initial Navigation Count Match"); + is(docShell.sessionHistory.index, index, "Initial Navigation Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Initial Navigation URL Scheme"); + }); + } + + // Go back to the first entry. + for (let {url} of reversed(HISTORY).slice(1)) { + ContentTask.spawn(aBrowser, {}, () => { content.history.back(); }); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + index--; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Go Back Count Match"); + is(docShell.sessionHistory.index, index, "Go Back Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Go Back URL Scheme"); + }); + } + + // Go forward to the last entry. + for (let {url} of HISTORY.slice(1)) { + ContentTask.spawn(aBrowser, {}, () => { content.history.forward(); }); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + index++; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Go Forward Count Match"); + is(docShell.sessionHistory.index, index, "Go Forward Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Go Forward URL Scheme"); + }); + } + }); +} + + +add_task(async function prefDisabled() { + await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, false]]}); + await runTest(); +}); + + +add_task(async function prefEnabled() { + await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, true]]}); + await runTest(); +}); diff --git a/toolkit/components/remotebrowserutils/tests/browser/head.js b/toolkit/components/remotebrowserutils/tests/browser/head.js new file mode 100644 index 000000000000..8242eb9602a9 --- /dev/null +++ b/toolkit/components/remotebrowserutils/tests/browser/head.js @@ -0,0 +1,15 @@ +function fileURL(filename) { + let ifile = getChromeDir(getResolvedURI(gTestPath)); + ifile.append(filename); + return Services.io.newFileURI(ifile).spec; +} + +function httpURL(filename, host = "https://example.com/") { + let root = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", host); + return root + filename; +} + +function add307(url, host = "https://example.com/") { + return httpURL("307redirect.sjs?" + url, host); +} From 92f3f91156493221f96091e44c7714182cc0b81c Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:05 +0000 Subject: [PATCH 32/84] Bug 1522637 - Part 6: Enable httpResponseProcessSelection by default, r=qdot Depends on D18606 Differential Revision: https://phabricator.services.mozilla.com/D18607 --HG-- extra : moz-landing-system : lando --- browser/app/profile/firefox.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index a07a61ca2257..3f09bb66e776 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -483,6 +483,9 @@ pref("browser.tabs.newanimations", false); pref("browser.tabs.remote.separatePrivilegedContentProcess", true); #endif +// Turn on HTTP response process selection. +pref("browser.tabs.remote.useHTTPResponseProcessSelection", true); + pref("browser.ctrlTab.recentlyUsedOrder", true); // By default, do not export HTML at shutdown. From 1b032ecafb29d084a6c13d103cc038b5c50132c8 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:37:06 +0000 Subject: [PATCH 33/84] Bug 1522637 - Part 7: Perform process switches separtely from on-examine-response, r=valentin Issues were occuring where a process swap would be decided upon during on-examine-response, but before the swap could be handled by the channel, the channel was redirected. This new code takes the mildly hacky approach of simply using a separate observer notification which is fired at the correct time. A better solution may be to use a dedicated service for responding to these events, however that was not implemented for this initial patch. Depends on D18607 Differential Revision: https://phabricator.services.mozilla.com/D19691 --HG-- extra : moz-landing-system : lando --- .../components/sessionstore/SessionStore.jsm | 12 ++---- netwerk/protocol/http/nsHttpChannel.cpp | 38 ++++++++++++------- netwerk/protocol/http/nsHttpHandler.h | 4 ++ .../protocol/http/nsIHttpProtocolHandler.idl | 8 ++++ .../browser/browser_cross_process_redirect.js | 12 ++---- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 3e920df6cee0..c0370612cfc9 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -48,9 +48,7 @@ const OBSERVING = [ "quit-application", "browser:purge-session-history", "browser:purge-session-history-for-domain", "idle-daily", "clear-origin-attributes-data", - "http-on-examine-response", - "http-on-examine-merged-response", - "http-on-examine-cached-response", + "http-on-may-change-process", ]; // XUL Window properties to (re)store @@ -814,10 +812,8 @@ var SessionStoreInternal = { this._forgetTabsWithUserContextId(userContextId); } break; - case "http-on-examine-response": - case "http-on-examine-cached-response": - case "http-on-examine-merged-response": - this.onExamineResponse(aSubject); + case "http-on-may-change-process": + this.onMayChangeProcess(aSubject); break; } }, @@ -2318,7 +2314,7 @@ var SessionStoreInternal = { // Examine the channel response to see if we should change the process // performing the given load. - onExamineResponse(aChannel) { + onMayChangeProcess(aChannel) { if (!E10SUtils.useHttpResponseProcessSelection()) { return; } diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index e48e97e624a8..5fb40d79a1f0 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -2450,15 +2450,20 @@ nsresult nsHttpChannel::ContinueProcessResponse1() { } rv = NS_OK; - if (mRedirectTabPromise && !mCanceled) { - MOZ_ASSERT(!mOnStartRequestCalled); + if (!mCanceled) { + // notify "http-on-may-change-process" observers + gHttpHandler->OnMayChangeProcess(this); - PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; + if (mRedirectTabPromise) { + MOZ_ASSERT(!mOnStartRequestCalled); + + PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); } // No process switch needed, continue as normal. @@ -7121,6 +7126,8 @@ NS_IMETHODIMP nsHttpChannel::SwitchProcessTo(dom::Promise *aTabPromise, nsresult nsHttpChannel::StartCrossProcessRedirect() { nsresult rv; + LOG(("nsHttpChannel::StartCrossProcessRedirect [this=%p]", this)); + rv = CheckRedirectLimit(nsIChannelEventSink::REDIRECT_INTERNAL); NS_ENSURE_SUCCESS(rv, rv); @@ -7257,13 +7264,18 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { // before we check for redirects, check if the load should be shifted into a // new process. rv = NS_OK; - if (mRedirectTabPromise && !mCanceled) { - PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; + if (!mCanceled) { + // notify "http-on-may-change-process" observers + gHttpHandler->OnMayChangeProcess(this); + + if (mRedirectTabPromise) { + PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); } // No process change is needed, so continue on to ContinueOnStartRequest1. diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index d2eb2e08a90e..1e7dd003bac3 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -368,6 +368,10 @@ class nsHttpHandler final : public nsIHttpProtocolHandler, NotifyObservers(chan, NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC); } + void OnMayChangeProcess(nsIHttpChannel *chan) { + NotifyObservers(chan, NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC); + } + // Generates the host:port string for use in the Host: header as well as the // CONNECT line for proxies. This handles IPv6 literals correctly. static MOZ_MUST_USE nsresult GenerateHostPort(const nsCString &host, diff --git a/netwerk/protocol/http/nsIHttpProtocolHandler.idl b/netwerk/protocol/http/nsIHttpProtocolHandler.idl index 6132608011ae..6abe8e8276bb 100644 --- a/netwerk/protocol/http/nsIHttpProtocolHandler.idl +++ b/netwerk/protocol/http/nsIHttpProtocolHandler.idl @@ -123,6 +123,14 @@ interface nsIHttpProtocolHandler : nsIProxiedProtocolHandler */ #define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response" +/** + * The observer of this topic is notified before before the response for a HTTP + * load is available. The "subject" of the notification is the nsIHttpChannel + * instance. Observers may call "switchProcessTo" to perform a process switch + * while this is being run. + */ +#define NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC "http-on-may-change-process" + /** * Before an HTTP request corresponding to a channel with the LOAD_DOCUMENT_URI * flag is sent to the server, this observer topic is notified. The observer of diff --git a/netwerk/test/browser/browser_cross_process_redirect.js b/netwerk/test/browser/browser_cross_process_redirect.js index 28985bdd90c6..602d78f0f904 100644 --- a/netwerk/test/browser/browser_cross_process_redirect.js +++ b/netwerk/test/browser/browser_cross_process_redirect.js @@ -23,9 +23,7 @@ function ProcessChooser(tabParent, from, to, rejectPromise = false) { this.rejectPromise = rejectPromise; this.registered = true; - Services.obs.addObserver(this, "http-on-examine-response"); - Services.obs.addObserver(this, "http-on-examine-merged-response"); - Services.obs.addObserver(this, "http-on-examine-cached-response"); + Services.obs.addObserver(this, "http-on-may-change-process"); } ProcessChooser.prototype = { @@ -34,9 +32,7 @@ ProcessChooser.prototype = { return; } this.registered = false; - Services.obs.removeObserver(this, "http-on-examine-response"); - Services.obs.removeObserver(this, "http-on-examine-merged-response"); - Services.obs.removeObserver(this, "http-on-examine-cached-response"); + Services.obs.removeObserver(this, "http-on-may-change-process"); }, examine(aChannel) { @@ -83,9 +79,7 @@ ProcessChooser.prototype = { observe(aSubject, aTopic, aData) { switch (aTopic) { - case "http-on-examine-response": - case "http-on-examine-cached-response": - case "http-on-examine-merged-response": + case "http-on-may-change-process": this.examine(aSubject.QueryInterface(Ci.nsIHttpChannel)); break; default: From ffb42b332260ec62a063553affd7523352b0586c Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:10 +0000 Subject: [PATCH 34/84] Bug 1522637 - Part 8: Perform the preloaded document swap before checking for HTTP loads, r=mconley For HTTP loads from the preloaded document, no process swap was occuring if the preloaded document was loaded in a 'web' process. This caused test failures, and has potentially undesireable behaviour. This patch just moves the check for preloaded document swaps to before the check for http parent process interception, forcing a swap like normal. Depends on D19691 Differential Revision: https://phabricator.services.mozilla.com/D19692 --HG-- extra : moz-landing-system : lando --- toolkit/modules/E10SUtils.jsm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/toolkit/modules/E10SUtils.jsm b/toolkit/modules/E10SUtils.jsm index 594f0dab1d19..f95a4e724cf0 100644 --- a/toolkit/modules/E10SUtils.jsm +++ b/toolkit/modules/E10SUtils.jsm @@ -323,6 +323,20 @@ var E10SUtils = { return true; } + let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); + let sessionHistory = webNav.sessionHistory; + if (!aHasPostData && + Services.appinfo.remoteType == WEB_REMOTE_TYPE && + sessionHistory.count == 1 && + webNav.currentURI.spec == "about:newtab") { + // This is possibly a preloaded browser and we're about to navigate away for + // the first time. On the child side there is no way to tell for sure if that + // is the case, so let's redirect this request to the parent to decide if a new + // process is needed. But we don't currently properly handle POST data in + // redirects (bug 1457520), so if there is POST data, don't return false here. + return false; + } + // If we are performing HTTP response process selection, and are loading an // HTTP URI, we can start the load in the current process, and then perform // the switch later-on using the RedirectProcessChooser mechanism. @@ -347,8 +361,6 @@ var E10SUtils = { } // Allow history load if loaded in this process before. - let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); - let sessionHistory = webNav.sessionHistory; let requestedIndex = sessionHistory.legacySHistory.requestedIndex; if (requestedIndex >= 0) { if (sessionHistory.legacySHistory.getEntryAtIndex(requestedIndex).loadedInThisProcess) { @@ -362,18 +374,6 @@ var E10SUtils = { this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI); } - if (!aHasPostData && - Services.appinfo.remoteType == WEB_REMOTE_TYPE && - sessionHistory.count == 1 && - webNav.currentURI.spec == "about:newtab") { - // This is possibly a preloaded browser and we're about to navigate away for - // the first time. On the child side there is no way to tell for sure if that - // is the case, so let's redirect this request to the parent to decide if a new - // process is needed. But we don't currently properly handle POST data in - // redirects (bug 1457520), so if there is POST data, don't return false here. - return false; - } - // If the URI can be loaded in the current process then continue return this.shouldLoadURIInThisProcess(aURI); }, From c03a74b74a5bd8bf8a114ed93e51fba59bef8ff5 Mon Sep 17 00:00:00 2001 From: alwu Date: Thu, 14 Feb 2019 15:30:53 +0000 Subject: [PATCH 35/84] Bug 1527688 - do not show caption button when there is no rendering area. r=jaws According to the spec 7.1.1, https://www.w3.org/TR/webvtt1/#processing-model "If the media element is an audio element, or is another playback mechanism with no rendering area, abort these steps" Which also means that we should not show the caption button if there is no rendering area. Differential Revision: https://phabricator.services.mozilla.com/D19695 --HG-- extra : moz-landing-system : lando --- toolkit/content/widgets/videocontrols.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/toolkit/content/widgets/videocontrols.js b/toolkit/content/widgets/videocontrols.js index f10c8a6edef0..5d4c8d205456 100644 --- a/toolkit/content/widgets/videocontrols.js +++ b/toolkit/content/widgets/videocontrols.js @@ -1559,6 +1559,10 @@ this.VideoControlsImplWidget = class { }, get isClosedCaptionAvailable() { + // There is no rendering area, no need to show the caption. + if (!this.video.videoWidth || !this.video.videoHeight) { + return false; + } return this.overlayableTextTracks.length; }, From bc1582070938136c1a7a6e17a6b3c8609e1ab776 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 14 Feb 2019 14:20:15 +0000 Subject: [PATCH 36/84] Bug 1527498 - Separate picture texture cache r=gw Manage the texture space for picture tiles separately inside the texture cache. Differential Revision: https://phabricator.services.mozilla.com/D19708 --HG-- extra : moz-landing-system : lando --- gfx/wr/webrender/src/gpu_cache.rs | 6 +- gfx/wr/webrender/src/picture.rs | 37 +-- gfx/wr/webrender/src/profiler.rs | 2 + gfx/wr/webrender/src/renderer.rs | 4 +- gfx/wr/webrender/src/resource_cache.rs | 3 +- gfx/wr/webrender/src/texture_cache.rs | 315 +++++++++++++++++++------ 6 files changed, 269 insertions(+), 98 deletions(-) diff --git a/gfx/wr/webrender/src/gpu_cache.rs b/gfx/wr/webrender/src/gpu_cache.rs index 31d829f4be8c..55ab9ce0cba7 100644 --- a/gfx/wr/webrender/src/gpu_cache.rs +++ b/gfx/wr/webrender/src/gpu_cache.rs @@ -24,7 +24,9 @@ //! address in the GPU cache of a given resource slot //! for this frame. -use api::{DebugFlags, DocumentId, PremultipliedColorF, IdNamespace, TexelRect}; +use api::{DebugFlags, DocumentId, PremultipliedColorF, TexelRect}; +#[cfg(test)] +use api::IdNamespace; use euclid::{HomogeneousVector, TypedRect}; use internal_types::{FastHashMap}; use profiler::GpuCacheProfileCounters; @@ -708,7 +710,7 @@ impl GpuCache { /// Creates a GpuCache and sets it up with a valid `FrameStamp`, which /// is useful for avoiding panics when instantiating the `GpuCache` /// directly from unit test code. - #[allow(dead_code)] + #[cfg(test)] pub fn new_for_testing() -> Self { let mut cache = Self::new(); let mut now = FrameStamp::first(DocumentId(IdNamespace(1), 1)); diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 1f6a5cb30f0f..5cf754af0019 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -5,14 +5,13 @@ use api::{FilterOp, MixBlendMode, PipelineId, PremultipliedColorF, PictureRect, PicturePoint, WorldPoint}; use api::{DeviceIntRect, DeviceIntSize, DevicePoint, DeviceRect}; use api::{LayoutRect, PictureToRasterTransform, LayoutPixel, PropertyBinding, PropertyBindingId}; -use api::{DevicePixelScale, RasterRect, RasterSpace, ColorF, ImageKey, DirtyRect, WorldSize, ClipMode, LayoutSize}; -use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, ImageFormat, ImageDescriptor, WorldVector2D, LayoutPoint}; +use api::{DevicePixelScale, RasterRect, RasterSpace, ColorF, ImageKey, WorldSize, ClipMode, LayoutSize}; +use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, WorldVector2D, LayoutPoint}; use api::{DebugFlags, DeviceHomogeneousVector, DeviceVector2D}; use box_shadow::{BLUR_SAMPLE_SCALE}; use clip::{ClipChainId, ClipChainNode, ClipItem, ClipStore, ClipDataStore, ClipChainStack}; use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex, CoordinateSystemId, VisibleFace}; use debug_colors; -use device::TextureFilter; use euclid::{size2, vec3, TypedPoint2D, TypedScale, TypedSize2D}; use euclid::approxeq::ApproxEq; use frame_builder::{FrameVisibilityContext, FrameVisibilityState}; @@ -35,7 +34,7 @@ use scene_builder::Interners; use smallvec::SmallVec; use std::{mem, u16}; use std::sync::atomic::{AtomicUsize, Ordering}; -use texture_cache::{Eviction, TextureCacheHandle}; +use texture_cache::TextureCacheHandle; use tiling::RenderTargetKind; use util::{ComparableVec, TransformedRectKind, MatrixHelpers, MaxRect}; @@ -101,9 +100,10 @@ pub struct TileIndex(pub usize); /// Note that we use a separate, smaller size during wrench testing, so that /// we get tighter dirty rects and can do more meaningful invalidation /// tests. -pub const TILE_SIZE_WIDTH: i32 = 1024; -pub const TILE_SIZE_HEIGHT: i32 = 256; -pub const TILE_SIZE_TESTING: i32 = 64; +const TILE_SIZE_WIDTH: i32 = 1024; +const TILE_SIZE_HEIGHT: i32 = 256; +const TILE_SIZE_TESTING: i32 = 64; + pub const FRAMES_BEFORE_PICTURE_CACHING: usize = 2; const MAX_DIRTY_RECTS: usize = 3; @@ -783,7 +783,7 @@ impl TileCache { } let DeviceIntSize { width: tile_width, height: tile_height, _unit: _ } = - self.tile_dimensions(frame_context.config.testing); + Self::tile_dimensions(frame_context.config.testing); // Work out the scroll offset to apply to the world reference point. let scroll_offset_point = frame_context.clip_scroll_tree @@ -1391,15 +1391,6 @@ impl TileCache { return LayoutRect::max_rect(); } - let dim = self.tile_dimensions(frame_context.config.testing); - let descriptor = ImageDescriptor::new( - dim.width, - dim.height, - ImageFormat::BGRA8, - true, - false, - ); - // Skip all tiles if completely off-screen. if !self.world_bounding_rect.intersects(&frame_context.screen_world_rect) { return LayoutRect::zero(); @@ -1547,17 +1538,9 @@ impl TileCache { if tile.same_frames >= FRAMES_BEFORE_PICTURE_CACHING { // Ensure that this texture is allocated. if !resource_cache.texture_cache.is_allocated(&tile.handle) { - resource_cache.texture_cache.update( + resource_cache.texture_cache.update_picture_cache( &mut tile.handle, - descriptor, - TextureFilter::Linear, - None, - [0.0; 3], - DirtyRect::All, gpu_cache, - None, - UvRectKind::Rect, - Eviction::Eager, ); } @@ -1618,7 +1601,7 @@ impl TileCache { local_clip_rect } - fn tile_dimensions(&self, testing: bool) -> DeviceIntSize { + pub fn tile_dimensions(testing: bool) -> DeviceIntSize { if testing { size2(TILE_SIZE_TESTING, TILE_SIZE_TESTING) } else { diff --git a/gfx/wr/webrender/src/profiler.rs b/gfx/wr/webrender/src/profiler.rs index 5095991398e8..2597eef2c801 100644 --- a/gfx/wr/webrender/src/profiler.rs +++ b/gfx/wr/webrender/src/profiler.rs @@ -391,6 +391,7 @@ pub struct TextureCacheProfileCounters { pub pages_a16_linear: ResourceProfileCounter, pub pages_rgba8_linear: ResourceProfileCounter, pub pages_rgba8_nearest: ResourceProfileCounter, + pub pages_picture: ResourceProfileCounter, } impl TextureCacheProfileCounters { @@ -400,6 +401,7 @@ impl TextureCacheProfileCounters { pages_a16_linear: ResourceProfileCounter::new("Texture A16 cached pages"), pages_rgba8_linear: ResourceProfileCounter::new("Texture RGBA8 cached pages (L)"), pages_rgba8_nearest: ResourceProfileCounter::new("Texture RGBA8 cached pages (N)"), + pages_picture: ResourceProfileCounter::new("Picture cached pages"), } } } diff --git a/gfx/wr/webrender/src/renderer.rs b/gfx/wr/webrender/src/renderer.rs index cb43163da1ca..b141d7b915a0 100644 --- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -58,7 +58,7 @@ use internal_types::{CacheTextureId, DebugOutput, FastHashMap, LayerIndex, Rende use internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource}; use internal_types::{RenderTargetInfo, SavedTargetIndex}; use malloc_size_of::MallocSizeOfOps; -use picture::RecordedDirtyRegion; +use picture::{RecordedDirtyRegion, TileCache}; use prim_store::DeferredResolve; use profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter, GpuProfileTag, RendererProfileCounters, RendererProfileTimers}; @@ -1931,6 +1931,7 @@ impl Renderer { let texture_cache = TextureCache::new( max_texture_size, max_texture_layers, + TileCache::tile_dimensions(config.testing), ); let resource_cache = ResourceCache::new( @@ -2850,7 +2851,6 @@ impl Renderer { if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) { self.clear_texture(&texture, TEXTURE_CACHE_DBG_CLEAR_COLOR); } - } let old = self.texture_resolver.texture_cache_map.insert(allocation.id, texture); diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs index 0a3685554897..f87c2fe6c9c5 100644 --- a/gfx/wr/webrender/src/resource_cache.rs +++ b/gfx/wr/webrender/src/resource_cache.rs @@ -1792,7 +1792,7 @@ impl ResourceCache { self.cached_render_tasks.clear(); } if what.contains(ClearCache::TEXTURE_CACHE) { - self.texture_cache.clear(); + self.texture_cache.clear_all(); } if what.contains(ClearCache::RASTERIZED_BLOBS) { self.rasterized_blob_images.clear(); @@ -2199,6 +2199,7 @@ impl ResourceCache { self.texture_cache = TextureCache::new( self.texture_cache.max_texture_size(), self.texture_cache.max_texture_layers(), + self.texture_cache.picture_tile_size(), ); } } diff --git a/gfx/wr/webrender/src/texture_cache.rs b/gfx/wr/webrender/src/texture_cache.rs index 9cdbd1a86fc3..b0391a25f9b5 100644 --- a/gfx/wr/webrender/src/texture_cache.rs +++ b/gfx/wr/webrender/src/texture_cache.rs @@ -4,7 +4,9 @@ use api::{DebugFlags, DeviceIntPoint, DeviceIntRect, DeviceIntSize}; use api::{DirtyRect, ImageDirtyRect, DocumentId, ExternalImageType, ImageFormat}; -use api::{IdNamespace, ImageDescriptor}; +use api::{ImageDescriptor}; +#[cfg(test)] +use api::IdNamespace; use device::{TextureFilter, total_gpu_bytes_allocated}; use freelist::{FreeList, FreeListHandle, UpsertResult, WeakFreeListHandle}; use gpu_cache::{GpuCache, GpuCacheHandle}; @@ -23,6 +25,13 @@ use std::rc::Rc; /// The size of each region/layer in shared cache texture arrays. const TEXTURE_REGION_DIMENSIONS: i32 = 512; +/// The number of slices for picture caching to allocate at start. +const BASE_PICTURE_TEXTURE_SLICES: usize = 16; +/// The number of slices to add when we grow out of the current range. +const ADD_PICTURE_TEXTURE_SLICES: usize = 8; +/// The chosen image format for picture tiles. +const PICTURE_TILE_FORMAT: ImageFormat = ImageFormat::BGRA8; + /// The number of pixels in a region. Derived from the above. const TEXTURE_REGION_PIXELS: usize = (TEXTURE_REGION_DIMENSIONS as usize) * (TEXTURE_REGION_DIMENSIONS as usize); @@ -34,6 +43,9 @@ const TEXTURE_REGION_PIXELS: usize = #[cfg_attr(feature = "replay", derive(Deserialize))] enum EntryDetails { Standalone, + Picture { + layer_index: usize, + }, Cache { /// Origin within the texture layer where this item exists. origin: DeviceIntPoint, @@ -42,11 +54,22 @@ enum EntryDetails { }, } +impl EntryDetails { + fn describe(&self) -> (LayerIndex, DeviceIntPoint) { + match *self { + EntryDetails::Standalone => (0, DeviceIntPoint::zero()), + EntryDetails::Picture { layer_index } => (layer_index, DeviceIntPoint::zero()), + EntryDetails::Cache { origin, layer_index } => (layer_index, origin), + } + } +} + impl EntryDetails { /// Returns the kind associated with the details. fn kind(&self) -> EntryKind { match *self { EntryDetails::Standalone => EntryKind::Standalone, + EntryDetails::Picture { .. } => EntryKind::Picture, EntryDetails::Cache { .. } => EntryKind::Shared, } } @@ -56,6 +79,7 @@ impl EntryDetails { #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum EntryKind { Standalone, + Picture, Shared, } @@ -120,14 +144,11 @@ impl CacheEntry { // to fetch from. fn update_gpu_cache(&mut self, gpu_cache: &mut GpuCache) { if let Some(mut request) = gpu_cache.request(&mut self.uv_rect_handle) { - let (origin, layer_index) = match self.details { - EntryDetails::Standalone => (DeviceIntPoint::zero(), 0.0), - EntryDetails::Cache { origin, layer_index } => (origin, layer_index as f32), - }; + let (layer_index, origin) = self.details.describe(); let image_source = ImageSource { p0: origin.to_f32(), p1: (origin + self.size).to_f32(), - texture_layer: layer_index, + texture_layer: layer_index as f32, user_data: self.user_data, uv_rect_kind: self.uv_rect_kind, }; @@ -284,6 +305,8 @@ impl SharedTextures { struct EntryHandles { /// Handles for each standalone texture cache entry. standalone: Vec>, + /// Handles for each picture cache entry. + picture: Vec>, /// Handles for each shared texture cache entry. shared: Vec>, } @@ -293,6 +316,7 @@ impl EntryHandles { fn select(&mut self, kind: EntryKind) -> &mut Vec> { match kind { EntryKind::Standalone => &mut self.standalone, + EntryKind::Picture => &mut self.picture, EntryKind::Shared => &mut self.shared, } } @@ -319,6 +343,7 @@ struct CacheAllocParams { /// well. The pair of values in our eviction threshold generally do not match /// the stamp of any actual frame, and the comparison semantics are also /// different - so it's best to use a distinct type. +#[derive(Clone, Copy)] struct EvictionThreshold { id: FrameId, time: SystemTime, @@ -449,6 +474,9 @@ pub struct TextureCache { /// Set of texture arrays in different formats used for the shared cache. shared_textures: SharedTextures, + /// A single texture array for picture caching. + picture_texture: WholeTextureArray, + /// Maximum texture size supported by hardware. max_texture_size: i32, @@ -489,7 +517,11 @@ pub struct TextureCache { } impl TextureCache { - pub fn new(max_texture_size: i32, mut max_texture_layers: usize) -> Self { + pub fn new( + max_texture_size: i32, + mut max_texture_layers: usize, + picture_tile_size: DeviceIntSize, + ) -> Self { if cfg!(target_os = "macos") { // On MBP integrated Intel GPUs, texture arrays appear to be // implemented as a single texture of stacked layers, and that @@ -516,15 +548,26 @@ impl TextureCache { max_texture_layers = max_texture_layers.min(32); } + let picture_texture = WholeTextureArray { + size: picture_tile_size, + filter: TextureFilter::Linear, + format: PICTURE_TILE_FORMAT, + texture_id: CacheTextureId(1), + slices: vec![WholeTextureSlice { uv_rect_handle: None }; BASE_PICTURE_TEXTURE_SLICES], + }; + let mut pending_updates = TextureUpdateList::new(); + pending_updates.push_alloc(picture_texture.texture_id, picture_texture.to_info()); + TextureCache { shared_textures: SharedTextures::new(), + picture_texture, reached_reclaim_threshold: None, entries: FreeList::new(), max_texture_size, max_texture_layers, debug_flags: DebugFlags::empty(), - next_id: CacheTextureId(1), - pending_updates: TextureUpdateList::new(), + next_id: CacheTextureId(2), + pending_updates, now: FrameStamp::INVALID, per_doc_data: FastHashMap::default(), doc_data: PerDocumentData::new(), @@ -534,9 +577,10 @@ impl TextureCache { /// Creates a TextureCache and sets it up with a valid `FrameStamp`, which /// is useful for avoiding panics when instantiating the `TextureCache` /// directly from unit test code. - #[allow(dead_code)] + #[cfg(test)] pub fn new_for_testing(max_texture_size: i32, max_texture_layers: usize) -> Self { - let mut cache = Self::new(max_texture_size, max_texture_layers); + let tile_size = DeviceIntSize::new(64, 64); + let mut cache = Self::new(max_texture_size, max_texture_layers, tile_size); let mut now = FrameStamp::first(DocumentId(IdNamespace(1), 1)); now.advance(); cache.begin_frame(now); @@ -547,9 +591,8 @@ impl TextureCache { self.debug_flags = flags; } - /// Clear all standalone textures in the cache. - pub fn clear_standalone(&mut self) { - debug_assert!(!self.now.is_valid()); + /// Clear all entries of the specified kind. + fn clear_kind(&mut self, kind: EntryKind) { // This pref just helps us avoid crashes when we begin using multiple documents. // What we need to do for clear to work correctly with multiple documents is // to ensure that we generate frames for all documents whenever we do this. @@ -559,12 +602,12 @@ impl TextureCache { let mut per_doc_data = mem::replace(&mut self.per_doc_data, FastHashMap::default()); for (&_, doc_data) in per_doc_data.iter_mut() { - let standalone_entry_handles = mem::replace( - &mut doc_data.handles.standalone, + let entry_handles = mem::replace( + doc_data.handles.select(kind), Vec::new(), ); - for handle in standalone_entry_handles { + for handle in entry_handles { let entry = self.entries.free(handle); entry.evict(); self.free(entry); @@ -573,39 +616,33 @@ impl TextureCache { self.per_doc_data = per_doc_data; } - /// Clear all shared textures in the cache. - pub fn clear_shared(&mut self) { - // This pref just helps us avoid crashes when we begin using multiple documents. - // What we need to do for clear to work correctly with multiple documents is - // to ensure that we generate frames for all documents whenever we do this. + fn clear_standalone(&mut self) { + debug_assert!(!self.now.is_valid()); + self.clear_kind(EntryKind::Standalone); + } + + fn clear_picture(&mut self) { + self.clear_kind(EntryKind::Picture); + if let Some(texture_id) = self.picture_texture.reset(BASE_PICTURE_TEXTURE_SLICES) { + self.pending_updates.push_realloc(texture_id, self.picture_texture.to_info()); + } + } + + fn clear_shared(&mut self) { if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG_DISABLE_SHRINK) { return; } - self.unset_doc_data(); - let mut per_doc_data = mem::replace(&mut self.per_doc_data, FastHashMap::default()); - for (&_, doc_data) in per_doc_data.iter_mut() { - let shared_entry_handles = mem::replace( - &mut doc_data.handles.shared, - Vec::new(), - ); - - for handle in shared_entry_handles { - let entry = self.entries.free(handle); - entry.evict(); - self.free(entry); - } - } - + self.clear_kind(EntryKind::Shared); self.shared_textures.clear(&mut self.pending_updates); - self.per_doc_data = per_doc_data; self.set_doc_data(); } /// Clear all entries in the texture cache. This is a fairly drastic /// step that should only be called very rarely. - pub fn clear(&mut self) { + pub fn clear_all(&mut self) { self.clear_standalone(); + self.clear_picture(); self.clear_shared(); } @@ -689,6 +726,7 @@ impl TextureCache { // at an acceptable level. let threshold = self.default_eviction(); self.expire_old_entries(EntryKind::Standalone, threshold); + self.expire_old_entries(EntryKind::Picture, threshold); self.shared_textures.array_a8_linear .update_profile(&mut texture_cache_profile.pages_a8_linear); @@ -699,6 +737,9 @@ impl TextureCache { self.shared_textures.array_rgba8_nearest .update_profile(&mut texture_cache_profile.pages_rgba8_nearest); + self.picture_texture + .update_profile(&mut texture_cache_profile.pages_picture); + self.unset_doc_data(); self.now = FrameStamp::INVALID; } @@ -735,11 +776,16 @@ impl TextureCache { self.max_texture_size } - #[allow(dead_code)] + #[cfg(feature = "replay")] pub fn max_texture_layers(&self) -> usize { self.max_texture_layers } + #[cfg(feature = "replay")] + pub fn picture_tile_size(&self) -> DeviceIntSize { + self.picture_texture.size + } + pub fn pending_updates(&mut self) -> TextureUpdateList { mem::replace(&mut self.pending_updates, TextureUpdateList::new()) } @@ -794,6 +840,7 @@ impl TextureCache { // Invalidate the contents of the resource rect in the GPU cache. // This ensures that the update_gpu_cache below will add // the new information to the GPU cache. + //TODO: only invalidate if the parameters change? gpu_cache.invalidate(&entry.uv_rect_handle); // Upload the resource rect and texture array layer. @@ -805,11 +852,7 @@ impl TextureCache { // to upload the new image data into the correct location // in GPU memory. if let Some(data) = data { - let (layer_index, origin) = match entry.details { - EntryDetails::Standalone => (0, DeviceIntPoint::zero()), - EntryDetails::Cache { layer_index, origin } => (layer_index, origin), - }; - + let (layer_index, origin) = entry.details.describe(); let op = TextureCacheUpdate::new_update( data, &descriptor, @@ -857,16 +900,7 @@ impl TextureCache { .get_opt(handle) .expect("BUG: was dropped from cache or not updated!"); debug_assert_eq!(entry.last_access, self.now); - let (layer_index, origin) = match entry.details { - EntryDetails::Standalone { .. } => { - (0, DeviceIntPoint::zero()) - } - EntryDetails::Cache { - layer_index, - origin, - .. - } => (layer_index, origin), - }; + let (layer_index, origin) = entry.details.describe(); (entry.texture_id, layer_index as usize, DeviceIntRect::new(origin, entry.size), @@ -964,6 +998,21 @@ impl TextureCache { // This is a standalone texture allocation. Free it directly. self.pending_updates.push_free(entry.texture_id); } + EntryDetails::Picture { layer_index } => { + self.picture_texture.slices[layer_index].uv_rect_handle = None; + if self.debug_flags.contains( + DebugFlags::TEXTURE_CACHE_DBG | + DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED) + { + self.pending_updates.push_debug_clear( + entry.texture_id, + DeviceIntPoint::zero(), + self.picture_texture.size.width, + self.picture_texture.size.height, + layer_index, + ); + } + } EntryDetails::Cache { origin, layer_index } => { // Free the block in the given region. let texture_array = self.shared_textures.select(entry.format, entry.filter); @@ -971,13 +1020,14 @@ impl TextureCache { if self.debug_flags.contains( DebugFlags::TEXTURE_CACHE_DBG | - DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED) { + DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED) + { self.pending_updates.push_debug_clear( entry.texture_id, origin, region.slab_size.width, region.slab_size.height, - layer_index + layer_index, ); } region.free(origin, &mut texture_array.empty_regions); @@ -1157,13 +1207,12 @@ impl TextureCache { } } - /// Allocates a cache entry for the given parameters, and updates the - /// provided handle to point to the new entry. - fn allocate(&mut self, params: &CacheAllocParams, handle: &mut TextureCacheHandle) { - debug_assert!(self.now.is_valid()); - let new_cache_entry = self.allocate_cache_entry(params); - let new_kind = new_cache_entry.details.kind(); - + fn upsert_entry( + &mut self, + cache_entry: CacheEntry, + handle: &mut TextureCacheHandle, + ) { + let new_kind = cache_entry.details.kind(); // If the handle points to a valid cache entry, we want to replace the // cache entry with our newly updated location. We also need to ensure // that the storage (region or standalone) associated with the previous @@ -1173,7 +1222,7 @@ impl TextureCache { // result to the corresponding vector. // // This is managed with a database style upsert operation. - match self.entries.upsert(handle, new_cache_entry) { + match self.entries.upsert(handle, cache_entry) { UpsertResult::Updated(old_entry) => { if new_kind != old_entry.details.kind() { // Handle the rare case than an update moves an entry from @@ -1182,6 +1231,7 @@ impl TextureCache { let (from, to) = match new_kind { EntryKind::Standalone => (&mut self.doc_data.handles.shared, &mut self.doc_data.handles.standalone), + EntryKind::Picture => unreachable!(), EntryKind::Shared => (&mut self.doc_data.handles.standalone, &mut self.doc_data.handles.shared), }; @@ -1196,6 +1246,44 @@ impl TextureCache { } } } + + /// Allocates a cache entry for the given parameters, and updates the + /// provided handle to point to the new entry. + fn allocate(&mut self, params: &CacheAllocParams, handle: &mut TextureCacheHandle) { + debug_assert!(self.now.is_valid()); + let new_cache_entry = self.allocate_cache_entry(params); + self.upsert_entry(new_cache_entry, handle) + } + + // Update the data stored by a given texture cache handle for picture caching specifically. + pub fn update_picture_cache( + &mut self, + handle: &mut TextureCacheHandle, + gpu_cache: &mut GpuCache, + ) { + debug_assert!(self.now.is_valid()); + + if self.entries.get_opt(handle).is_none() { + let layer_index = match self.picture_texture.find_free() { + Some(index) => index, + None => { + let index = self.picture_texture.grow(ADD_PICTURE_TEXTURE_SLICES); + let info = self.picture_texture.to_info(); + self.pending_updates.push_realloc(self.picture_texture.texture_id, info); + index + }, + }; + + let cache_entry = self.picture_texture.occupy(layer_index, self.now); + self.upsert_entry(cache_entry, handle) + } + + // Upload the resource rect and texture array layer. + self.entries + .get_opt_mut(handle) + .expect("BUG: handle must be valid now") + .update_gpu_cache(gpu_cache); + } } #[cfg_attr(feature = "capture", derive(Serialize))] @@ -1207,7 +1295,7 @@ struct SlabSize { } impl SlabSize { - fn new(size: DeviceIntSize) -> SlabSize { + fn new(size: DeviceIntSize) -> Self { let x_size = quantize_dimension(size.width); let y_size = quantize_dimension(size.height); @@ -1465,6 +1553,101 @@ impl TextureArray { } } + +/// A tracking structure for each slice in `WholeTextureArray`. +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(Clone, Copy, Debug)] +struct WholeTextureSlice { + uv_rect_handle: Option, +} + +/// A texture array that allocates whole slices and doesn't do any region tracking. +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +struct WholeTextureArray { + size: DeviceIntSize, + filter: TextureFilter, + format: ImageFormat, + texture_id: CacheTextureId, + slices: Vec, +} + +impl WholeTextureArray { + fn to_info(&self) -> TextureCacheAllocInfo { + TextureCacheAllocInfo { + width: self.size.width, + height: self.size.height, + format: self.format, + filter: self.filter, + layer_count: self.slices.len() as i32, + is_shared_cache: true, //TODO: reconsider + } + } + + /// Returns the number of GPU bytes consumed by this texture array. + fn size_in_bytes(&self) -> usize { + let bpp = self.format.bytes_per_pixel() as usize; + self.slices.len() * (self.size.width * self.size.height) as usize * bpp + } + + fn update_profile(&self, counter: &mut ResourceProfileCounter) { + counter.set(self.slices.len(), self.size_in_bytes()); + } + + /// Find an free slice. + fn find_free(&self) -> Option { + self.slices.iter().position(|slice| slice.uv_rect_handle.is_none()) + } + + /// Grow the array by the specified number of slices + fn grow(&mut self, count: usize) -> LayerIndex { + let index = self.slices.len(); + for _ in 0 .. count { + self.slices.push(WholeTextureSlice { + uv_rect_handle: None, + }); + } + index + } + + /// Occupy a specified slice by a cache entry. + fn occupy(&mut self, layer_index: usize, now: FrameStamp) -> CacheEntry { + let uv_rect_handle = GpuCacheHandle::new(); + assert!(self.slices[layer_index].uv_rect_handle.is_none()); + self.slices[layer_index].uv_rect_handle = Some(uv_rect_handle); + + CacheEntry { + size: self.size, + user_data: [0.0; 3], + last_access: now, + details: EntryDetails::Picture { + layer_index, + }, + uv_rect_handle, + format: self.format, + filter: self.filter, + texture_id: self.texture_id, + eviction_notice: None, + uv_rect_kind: UvRectKind::Rect, + eviction: Eviction::Eager, + } + } + + /// Reset the texture array to the specified number of slices, if it's larger. + fn reset( + &mut self, num_slices: usize + ) -> Option { + if self.slices.len() <= num_slices { + None + } else { + self.slices.truncate(num_slices); + Some(self.texture_id) + } + } +} + + impl TextureCacheUpdate { // Constructs a TextureCacheUpdate operation to be passed to the // rendering thread in order to do an upload to the right From c9edc914a9cfd67188c3bdd5a4112bcb60a8fd1e Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Thu, 14 Feb 2019 16:02:12 +0000 Subject: [PATCH 37/84] Bug 1514392 - Use fallback process start time, even if inconsistent r=wlach,chutten Differential Revision: https://phabricator.services.mozilla.com/D19645 --HG-- extra : moz-landing-system : lando --- toolkit/components/telemetry/Scalars.yaml | 14 ++++++++++++++ .../components/telemetry/app/TelemetryUtils.jsm | 6 +----- .../components/telemetry/core/TelemetryCommon.cpp | 15 ++++++++++----- .../components/telemetry/docs/data/main-ping.rst | 4 ---- .../telemetry/pings/TelemetrySession.jsm | 11 +---------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/toolkit/components/telemetry/Scalars.yaml b/toolkit/components/telemetry/Scalars.yaml index 76a304d934c6..b5e4bfecf7c2 100644 --- a/toolkit/components/telemetry/Scalars.yaml +++ b/toolkit/components/telemetry/Scalars.yaml @@ -1806,6 +1806,20 @@ telemetry: record_in_processes: - 'main' + process_creation_timestamp_inconsistent: + bug_numbers: + - 1514392 + description: > + The number of times ProcessCreation saw an inconsistent value. + expires: "72" + kind: uint + notification_emails: + - jrediger@mozilla.com + release_channel_collection: opt-out + record_in_processes: + - 'main' + - 'content' + telemetry.discarded: accumulations: bug_numbers: diff --git a/toolkit/components/telemetry/app/TelemetryUtils.jsm b/toolkit/components/telemetry/app/TelemetryUtils.jsm index bc55d8dbc487..bb3793cd661b 100644 --- a/toolkit/components/telemetry/app/TelemetryUtils.jsm +++ b/toolkit/components/telemetry/app/TelemetryUtils.jsm @@ -217,11 +217,7 @@ var TelemetryUtils = { * or (non-monotonic) Date value if this fails back. */ monotonicNow() { - try { - return Services.telemetry.msSinceProcessStart(); - } catch (ex) { - return Date.now(); - } + return Services.telemetry.msSinceProcessStart(); }, /** diff --git a/toolkit/components/telemetry/core/TelemetryCommon.cpp b/toolkit/components/telemetry/core/TelemetryCommon.cpp index b12e1e99db29..9da667be6c21 100644 --- a/toolkit/components/telemetry/core/TelemetryCommon.cpp +++ b/toolkit/components/telemetry/core/TelemetryCommon.cpp @@ -14,6 +14,7 @@ #include "nsThreadUtils.h" #include "nsVersionComparator.h" #include "TelemetryProcessData.h" +#include "Telemetry.h" namespace mozilla { namespace Telemetry { @@ -83,11 +84,15 @@ bool CanRecordProduct(SupportedProduct aProducts) { } nsresult MsSinceProcessStart(double* aResult) { - bool error; - *aResult = (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation(&error)) - .ToMilliseconds(); - if (error) { - return NS_ERROR_NOT_AVAILABLE; + bool isInconsistent = false; + *aResult = + (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation(&isInconsistent)) + .ToMilliseconds(); + + if (isInconsistent) { + Telemetry::ScalarAdd( + Telemetry::ScalarID::TELEMETRY_PROCESS_CREATION_TIMESTAMP_INCONSISTENT, + 1); } return NS_OK; } diff --git a/toolkit/components/telemetry/docs/data/main-ping.rst b/toolkit/components/telemetry/docs/data/main-ping.rst index 0990f43a4bec..6662cb8b2bfc 100644 --- a/toolkit/components/telemetry/docs/data/main-ping.rst +++ b/toolkit/components/telemetry/docs/data/main-ping.rst @@ -86,8 +86,6 @@ The length of the current session so far in seconds. This uses a monotonic clock, so this may mismatch with other measurements that are not monotonic like calculations based on ``Date.now()``. -If the monotonic clock failed, this will be ``-1``. - Note that this currently does not behave consistently over our supported platforms: * On Windows this uses ``GetTickCount64()``, which does increase over sleep periods @@ -101,8 +99,6 @@ subsessionLength The length of this subsession in seconds. This uses a monotonic clock, so this may mismatch with other measurements that are not monotonic (e.g. based on ``Date.now()``). -If ``sessionLength`` is ``-1``, the monotonic clock is not working. - Also see the remarks for ``sessionLength`` on platform consistency. processes diff --git a/toolkit/components/telemetry/pings/TelemetrySession.jsm b/toolkit/components/telemetry/pings/TelemetrySession.jsm index ae30acf6dbe4..94043e0aecb4 100644 --- a/toolkit/components/telemetry/pings/TelemetrySession.jsm +++ b/toolkit/components/telemetry/pings/TelemetrySession.jsm @@ -88,21 +88,12 @@ function generateUUID() { return str.substring(1, str.length - 1); } -function getMsSinceProcessStart() { - try { - return Telemetry.msSinceProcessStart(); - } catch (ex) { - // If this fails return a special value. - return -1; - } -} - /** * This is a policy object used to override behavior for testing. */ var Policy = { now: () => new Date(), - monotonicNow: getMsSinceProcessStart, + monotonicNow: Utils.monotonicNow, generateSessionUUID: () => generateUUID(), generateSubsessionUUID: () => generateUUID(), setSchedulerTickTimeout: (callback, delayMs) => setTimeout(callback, delayMs), From 4c0cf6db4524d91c04b9df185b42ddbb7dd089cf Mon Sep 17 00:00:00 2001 From: Bogdan Tara Date: Thu, 14 Feb 2019 18:29:54 +0200 Subject: [PATCH 38/84] Backed out 3 changesets (bug 1523272) for ES Linut failure CLOSED TREE Backed out changeset 80d103201d1d (bug 1523272) Backed out changeset bbd8f0b2e3b2 (bug 1523272) Backed out changeset bf2ec5cdc33b (bug 1523272) --- .../test/sanitize/SiteDataTestUtils.jsm | 42 ++-- .../test/sanitize/browser_cookiePermission.js | 5 +- .../tests/siteData/browser_siteData2.js | 104 +++++----- .../tests/siteData/browser_siteData3.js | 192 +++++++++++++----- .../siteData/browser_siteData_multi_select.js | 75 ++++--- .../in-content/tests/siteData/head.js | 77 +++++-- browser/modules/SiteDataManager.jsm | 116 ++++++----- .../modules/test/unit/test_SiteDataManager.js | 148 -------------- browser/modules/test/unit/xpcshell.ini | 1 - 9 files changed, 367 insertions(+), 393 deletions(-) delete mode 100644 browser/modules/test/unit/test_SiteDataManager.js diff --git a/browser/base/content/test/sanitize/SiteDataTestUtils.jsm b/browser/base/content/test/sanitize/SiteDataTestUtils.jsm index 3e24dcb756ca..af50a049b221 100644 --- a/browser/base/content/test/sanitize/SiteDataTestUtils.jsm +++ b/browser/base/content/test/sanitize/SiteDataTestUtils.jsm @@ -15,8 +15,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "swm", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager"); -XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]); - /** * This module assists with tasks around testing functionality that shows * or clears site data. @@ -27,44 +25,31 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]); var SiteDataTestUtils = { /** - * Makes an origin have persistent data storage. - * - * @param {String} origin - the origin of the site to give persistent storage - * - * @returns a Promise that resolves when storage was persisted - */ - persist(origin, value = Services.perms.ALLOW_ACTION) { - return new Promise(resolve => { - let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); - Services.perms.addFromPrincipal(principal, "persistent-storage", value); - Services.qms.persist(principal).callback = () => resolve(); - }); - }, - - /** - * Adds a new blob entry to a dummy indexedDB database for the specified origin. + * Adds a new entry to a dummy indexedDB database for the specified origin. * * @param {String} origin - the origin of the site to add test data for - * @param {Number} size [optional] - the size of the entry in bytes + * @param {String} name [optional] - the entry key + * @param {String} value [optional] - the entry value + * @param {Object} originAttributes [optional] - the originAttributes * * @returns a Promise that resolves when the data was added successfully. */ - addToIndexedDB(origin, size = 1024) { + addToIndexedDB(origin, key = "foo", value = "bar", originAttributes = {}) { return new Promise(resolve => { - let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + let uri = Services.io.newURI(origin); + let principal = + Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes); let request = indexedDB.openForPrincipal(principal, "TestDatabase", 1); request.onupgradeneeded = function(e) { let db = e.target.result; - db.createObjectStore("TestStore"); + db.createObjectStore("TestStore", { keyPath: "id" }); }; request.onsuccess = function(e) { let db = e.target.result; let tx = db.transaction("TestStore", "readwrite"); let store = tx.objectStore("TestStore"); tx.oncomplete = resolve; - let buffer = new ArrayBuffer(size); - let blob = new Blob([buffer]); - store.add(blob, Cu.now()); + store.put({ id: key, description: value}); }; }); }, @@ -78,8 +63,8 @@ var SiteDataTestUtils = { * @param {String} value [optional] - the cookie value */ addToCookies(origin, name = "foo", value = "bar") { - let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); - Services.cookies.add(principal.URI.host, principal.URI.pathQueryRef, name, value, + let uri = Services.io.newURI(origin); + Services.cookies.add(uri.host, uri.pathQueryRef, name, value, false, false, false, Date.now() + 24000 * 60 * 60, {}, Ci.nsICookie2.SAMESITE_UNSET); }, @@ -136,7 +121,8 @@ var SiteDataTestUtils = { */ getQuotaUsage(origin) { return new Promise(resolve => { - let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin); + let uri = Services.io.newURI(origin); + let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage)); }); }, diff --git a/browser/base/content/test/sanitize/browser_cookiePermission.js b/browser/base/content/test/sanitize/browser_cookiePermission.js index 897c2e91b1fb..74745dc07696 100644 --- a/browser/base/content/test/sanitize/browser_cookiePermission.js +++ b/browser/base/content/test/sanitize/browser_cookiePermission.js @@ -18,9 +18,8 @@ function checkDataForAboutURL() { } function createIndexedDB(host, originAttributes) { - let uri = Services.io.newURI("https://" + host); - let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes); - return SiteDataTestUtils.addToIndexedDB(principal.origin); + return SiteDataTestUtils.addToIndexedDB("https://" + host, "foo", "bar", + originAttributes); } function checkIndexedDB(host, originAttributes) { diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js index e929c9c9d00c..d8aed9b70131 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js @@ -12,8 +12,8 @@ function assertAllSitesNotListed(win) { } // Test selecting and removing all sites one by one -add_task(async function test_selectRemove() { - let hosts = await addTestData([ +add_task(async function() { + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, origin: "https://account.xyz.com", @@ -22,6 +22,7 @@ add_task(async function test_selectRemove() { { usage: 1024, origin: "https://shopping.xyz.com", + persisted: false, }, { usage: 1024, @@ -31,11 +32,12 @@ add_task(async function test_selectRemove() { { usage: 1024, origin: "http://email.bar.com", + persisted: false, }, ]); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -48,7 +50,7 @@ add_task(async function test_selectRemove() { let settingsDialogClosePromise = null; // Test the initial state - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Cancel" button settingsDialogClosePromise = promiseSettingsDialogClose(); @@ -59,7 +61,7 @@ add_task(async function test_selectRemove() { cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but cancelling save let cancelPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel"); @@ -74,7 +76,7 @@ add_task(async function test_selectRemove() { cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save let acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept"); @@ -91,7 +93,7 @@ add_task(async function test_selectRemove() { await openSiteDataSettingsDialog(); assertAllSitesNotListed(win); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); function removeAllSitesOneByOne() { @@ -107,8 +109,8 @@ add_task(async function test_selectRemove() { }); // Test selecting and removing partial sites -add_task(async function test_removePartialSites() { - let hosts = await addTestData([ +add_task(async function() { + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, origin: "https://account.xyz.com", @@ -139,10 +141,15 @@ add_task(async function test_removePartialSites() { origin: "https://127.0.0.1", persisted: false, }, + { + usage: 1024, + origin: "https://[0:0:0:0:0:0:0:1]", + persisted: true, + }, ]); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -156,18 +163,18 @@ add_task(async function test_removePartialSites() { let settingsDialogClosePromise = null; // Test the initial state - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Cancel" button settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; cancelBtn = frameDoc.getElementById("cancel"); - await removeSelectedSite(hosts.slice(0, 2)); - assertSitesListed(doc, hosts.slice(2)); + removeSelectedSite(fakeHosts.slice(0, 2)); + assertSitesListed(doc, fakeHosts.slice(2)); cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button but canceling save removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel", REMOVE_DIALOG_URL); @@ -175,49 +182,44 @@ add_task(async function test_removePartialSites() { frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); cancelBtn = frameDoc.getElementById("cancel"); - await removeSelectedSite(hosts.slice(0, 2)); - assertSitesListed(doc, hosts.slice(2)); + removeSelectedSite(fakeHosts.slice(0, 2)); + assertSitesListed(doc, fakeHosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; cancelBtn.doCommand(); await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); // Test the "Save Changes" button and accepting save removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL); settingsDialogClosePromise = promiseSettingsDialogClose(); frameDoc = win.gSubDialog._topDialog._frame.contentDocument; saveBtn = frameDoc.getElementById("save"); - await removeSelectedSite(hosts.slice(0, 2)); - assertSitesListed(doc, hosts.slice(2)); + removeSelectedSite(fakeHosts.slice(0, 2)); + assertSitesListed(doc, fakeHosts.slice(2)); saveBtn.doCommand(); await removeDialogOpenPromise; await settingsDialogClosePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts.slice(2)); + assertSitesListed(doc, fakeHosts.slice(2)); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); - function removeSelectedSite(removeHosts) { + function removeSelectedSite(hosts) { frameDoc = win.gSubDialog._topDialog._frame.contentDocument; let removeBtn = frameDoc.getElementById("removeSelected"); is(removeBtn.disabled, true, "Should start with disabled removeSelected button"); let sitesList = frameDoc.getElementById("sitesList"); - removeHosts.forEach(host => { + hosts.forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); if (site) { site.click(); let currentSelectedIndex = sitesList.selectedIndex; is(removeBtn.disabled, false, "Should enable the removeSelected button"); removeBtn.doCommand(); - let newSelectedIndex = sitesList.selectedIndex; - if (currentSelectedIndex >= sitesList.itemCount) { - is(newSelectedIndex, currentSelectedIndex - 1); - } else { - is(newSelectedIndex, currentSelectedIndex); - } + is(sitesList.selectedIndex, currentSelectedIndex); } else { ok(false, `Should not select and remove inexistent site of ${host}`); } @@ -227,7 +229,7 @@ add_task(async function test_removePartialSites() { // Test searching and then removing only visible sites add_task(async function() { - let hosts = await addTestData([ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, origin: "https://account.xyz.com", @@ -249,9 +251,9 @@ add_task(async function() { persisted: false, }, ]); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -263,7 +265,7 @@ add_task(async function() { let searchBox = frameDoc.getElementById("searchBox"); searchBox.value = "xyz"; searchBox.doCommand(); - assertSitesListed(doc, hosts.filter(host => host.includes("xyz"))); + assertSitesListed(doc, fakeHosts.filter(host => host.includes("xyz"))); // Test only removing all visible sites listed updatePromise = promiseSiteDataManagerSitesUpdated(); @@ -277,15 +279,15 @@ add_task(async function() { await settingsDialogClosePromise; await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts.filter(host => !host.includes("xyz"))); + assertSitesListed(doc, fakeHosts.filter(host => !host.includes("xyz"))); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test dynamically clearing all site data add_task(async function() { - let hosts = await addTestData([ + mockSiteDataManager.register(SiteDataManager, [ { usage: 1024, origin: "https://account.xyz.com", @@ -297,28 +299,28 @@ add_task(async function() { persisted: false, }, ]); - - let updatePromise = promiseSiteDataManagerSitesUpdated(); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); // Test the initial state + let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); let doc = gBrowser.selectedBrowser.contentDocument; - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); - await addTestData([ - { - usage: 1024, - origin: "http://cinema.bar.com", - persisted: true, - }, - { - usage: 1024, - origin: "http://email.bar.com", - persisted: false, - }, - ]); + // Add more sites dynamically + mockSiteDataManager.fakeSites.push({ + usage: 1024, + principal: Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin("http://cinema.bar.com"), + persisted: true, + }, { + usage: 1024, + principal: Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin("http://email.bar.com"), + persisted: false, + }); // Test clearing all site data dynamically let win = gBrowser.selectedBrowser.contentWindow; @@ -336,6 +338,6 @@ add_task(async function() { await openSiteDataSettingsDialog(); assertAllSitesNotListed(win); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js index a0ca9dac28ff..1fa44d79ef05 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData3.js @@ -1,8 +1,8 @@ "use strict"; // Test not displaying sites which store 0 byte and don't have persistent storage. -add_task(async function test_exclusions() { - let hosts = await addTestData([ +add_task(async function() { + mockSiteDataManager.register(SiteDataManager, [ { usage: 0, origin: "https://account.xyz.com", @@ -30,22 +30,23 @@ add_task(async function test_exclusions() { persisted: false, }, ]); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); let doc = gBrowser.selectedBrowser.contentDocument; await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts.filter(host => host != "shopping.xyz.com")); + assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com")); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test grouping and listing sites across scheme, port and origin attributes by host -add_task(async function test_grouping() { - let quotaUsage = 7000000; - await addTestData([ +add_task(async function() { + const quotaUsage = 1024; + mockSiteDataManager.register(SiteDataManager, [ { usage: quotaUsage, origin: "https://account.xyz.com^userContextId=1", @@ -90,51 +91,40 @@ add_task(async function test_grouping() { is(columns[1].value, "5", "Should group cookies across scheme, port and origin attributes"); - let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * 4); - let l10nAttributes = frameDoc.l10n.getAttributes(columns[2]); - is(l10nAttributes.id, "site-usage-persistent", - "Should show the site as persistent if one origin is persistent."); - // The shown quota can be slightly larger than the raw data we put in (though it should - // never be smaller), but that doesn't really matter to us since we only want to test that - // the site data dialog accumulates this into a single column. - ok(parseFloat(l10nAttributes.args.value) >= parseFloat(value), - "Should show the correct accumulated quota size."); - is(l10nAttributes.args.unit, unit, "Should show the correct quota size unit."); + let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length); + Assert.deepEqual(frameDoc.l10n.getAttributes(columns[2]), { + id: "site-usage-persistent", + args: { value, unit }, + }, "Should sum up usages across scheme, port, origin attributes and persistent status"); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); // Test sorting -add_task(async function test_sorting() { - let testData = [ +add_task(async function() { + mockSiteDataManager.register(SiteDataManager, [ { - baseDomain: "xyz.com", usage: 1024, origin: "https://account.xyz.com", cookies: 6, persisted: true, }, { - baseDomain: "foo.com", usage: 1024 * 2, origin: "https://books.foo.com", cookies: 0, persisted: false, }, { - baseDomain: "bar.com", usage: 1024 * 3, origin: "http://cinema.bar.com", cookies: 3, persisted: true, }, - ]; - - await addTestData(testData); + ]); let updatePromise = promiseSiteDataManagerSitesUpdated(); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); await updatePromise; await openSiteDataSettingsDialog(); @@ -145,42 +135,146 @@ add_task(async function test_sorting() { let hostCol = frameDoc.getElementById("hostCol"); let usageCol = frameDoc.getElementById("usageCol"); let cookiesCol = frameDoc.getElementById("cookiesCol"); - let lastAccessedCol = frameDoc.getElementById("lastAccessedCol"); let sitesList = frameDoc.getElementById("sitesList"); - function getHostOrder() { - let siteItems = sitesList.getElementsByTagName("richlistitem"); - return Array.from(siteItems).map(item => item.getAttribute("host")); - } - - // Test default sorting by usage, descending. - Assert.deepEqual(getHostOrder(), - ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage"); + // Test default sorting + assertSortByUsage("descending"); // Test sorting on the usage column usageCol.click(); - Assert.deepEqual(getHostOrder(), - ["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted ascending by usage"); + assertSortByUsage("ascending"); usageCol.click(); - Assert.deepEqual(getHostOrder(), - ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage"); + assertSortByUsage("descending"); // Test sorting on the host column hostCol.click(); - Assert.deepEqual(getHostOrder(), - ["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted ascending by base domain"); + assertSortByBaseDomain("ascending"); hostCol.click(); - Assert.deepEqual(getHostOrder(), - ["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted descending by base domain"); + assertSortByBaseDomain("descending"); // Test sorting on the cookies column cookiesCol.click(); - Assert.deepEqual(getHostOrder(), - ["books.foo.com", "cinema.bar.com", "account.xyz.com"], "Has sorted ascending by cookies"); + assertSortByCookies("ascending"); cookiesCol.click(); - Assert.deepEqual(getHostOrder(), - ["account.xyz.com", "cinema.bar.com", "books.foo.com"], "Has sorted descending by cookies"); + assertSortByCookies("descending"); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); + + function assertSortByBaseDomain(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.baseDomain.localeCompare(b.baseDomain); + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host"); + } + } + } + + function assertSortByUsage(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.usage - b.usage; + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage"); + } + } + } + + function assertSortByCookies(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.cookies.length - b.cookies.length; + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies"); + } + } + } + + function findSiteByHost(host) { + return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); + } +}); + +// Test sorting based on access date (separate from cookies for simplicity, +// since cookies access date affects this as well, but we don't mock our cookies) +add_task(async function() { + mockSiteDataManager.register(SiteDataManager, [ + { + usage: 1024, + origin: "https://account.xyz.com", + persisted: true, + lastAccessed: (Date.now() - 120 * 1000) * 1000, + }, + { + usage: 1024 * 2, + origin: "https://books.foo.com", + persisted: false, + lastAccessed: (Date.now() - 240 * 1000) * 1000, + }, + { + usage: 1024 * 3, + origin: "http://cinema.bar.com", + persisted: true, + lastAccessed: Date.now() * 1000, + }, + ]); + + let updatePromise = promiseSiteDataManagerSitesUpdated(); + await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); + await updatePromise; + await openSiteDataSettingsDialog(); + + let dialog = content.gSubDialog._topDialog; + let dialogFrame = dialog._frame; + let frameDoc = dialogFrame.contentDocument; + let lastAccessedCol = frameDoc.getElementById("lastAccessedCol"); + let sitesList = frameDoc.getElementById("sitesList"); + + // Test sorting on the date column + lastAccessedCol.click(); + assertSortByDate("ascending"); + lastAccessedCol.click(); + assertSortByDate("descending"); + + await mockSiteDataManager.unregister(); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + function assertSortByDate(order) { + let siteItems = sitesList.getElementsByTagName("richlistitem"); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aHost = siteItems[i].getAttribute("host"); + let bHost = siteItems[i + 1].getAttribute("host"); + let a = findSiteByHost(aHost); + let b = findSiteByHost(bHost); + let result = a.lastAccessed - b.lastAccessed; + if (order == "ascending") { + Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by date"); + } else { + Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order date"); + } + } + } + + function findSiteByHost(host) { + return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host); + } }); diff --git a/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js b/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js index aecf10ff539a..34266fb22b14 100644 --- a/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js +++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js @@ -2,40 +2,44 @@ // Test selecting and removing partial sites add_task(async function() { - await SiteDataTestUtils.clear(); - - let hosts = await addTestData([ + mockSiteDataManager.register(SiteDataManager, [ + { + usage: 1024, + origin: "https://account.xyz.com", + persisted: true, + }, + { + usage: 1024, + origin: "https://shopping.xyz.com", + persisted: false, + }, + { + usage: 1024, + origin: "http://cinema.bar.com", + persisted: true, + }, + { + usage: 1024, + origin: "http://email.bar.com", + persisted: false, + }, + { + usage: 1024, + origin: "https://s3-us-west-2.amazonaws.com", + persisted: true, + }, { usage: 1024, origin: "https://127.0.0.1", persisted: false, }, { - usage: 1024 * 4, - origin: "http://cinema.bar.com", + usage: 1024, + origin: "https://[0:0:0:0:0:0:0:1]", persisted: true, }, - { - usage: 1024 * 3, - origin: "http://email.bar.com", - persisted: false, - }, - { - usage: 1024 * 2, - origin: "https://s3-us-west-2.amazonaws.com", - persisted: true, - }, - { - usage: 1024 * 6, - origin: "https://account.xyz.com", - persisted: true, - }, - { - usage: 1024 * 5, - origin: "https://shopping.xyz.com", - persisted: false, - }, ]); + let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host); let updatePromise = promiseSiteDataManagerSitesUpdated(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); @@ -45,21 +49,18 @@ add_task(async function() { let doc = gBrowser.selectedBrowser.contentDocument; // Test the initial state - assertSitesListed(doc, hosts); + assertSitesListed(doc, fakeHosts); let win = gBrowser.selectedBrowser.contentWindow; let frameDoc = win.gSubDialog._topDialog._frame.contentDocument; let removeBtn = frameDoc.getElementById("removeSelected"); is(removeBtn.disabled, true, "Should start with disabled removeSelected button"); - let hostCol = frameDoc.getElementById("hostCol"); - hostCol.click(); - let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL); let settingsDialogClosePromise = promiseSettingsDialogClose(); // Select some sites to remove. let sitesList = frameDoc.getElementById("sitesList"); - hosts.slice(0, 2).forEach(host => { + fakeHosts.slice(0, 2).forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); sitesList.addItemToSelection(site); }); @@ -67,10 +68,10 @@ add_task(async function() { is(removeBtn.disabled, false, "Should enable the removeSelected button"); removeBtn.doCommand(); is(sitesList.selectedIndex, 0, "Should select next item"); - assertSitesListed(doc, hosts.slice(2)); + assertSitesListed(doc, fakeHosts.slice(2)); // Select some other sites to remove with Delete. - hosts.slice(2, 4).forEach(host => { + fakeHosts.slice(2, 4).forEach(host => { let site = sitesList.querySelector(`richlistitem[host="${host}"]`); sitesList.addItemToSelection(site); }); @@ -78,21 +79,17 @@ add_task(async function() { is(removeBtn.disabled, false, "Should enable the removeSelected button"); EventUtils.synthesizeKey("VK_DELETE"); is(sitesList.selectedIndex, 0, "Should select next item"); - assertSitesListed(doc, hosts.slice(4)); + assertSitesListed(doc, fakeHosts.slice(4)); - updatePromise = promiseSiteDataManagerSitesUpdated(); let saveBtn = frameDoc.getElementById("save"); saveBtn.doCommand(); await removeDialogOpenPromise; await settingsDialogClosePromise; - - await updatePromise; await openSiteDataSettingsDialog(); - assertSitesListed(doc, hosts.slice(4)); + assertSitesListed(doc, fakeHosts.slice(4)); - await SiteDataTestUtils.clear(); + await mockSiteDataManager.unregister(); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); - diff --git a/browser/components/preferences/in-content/tests/siteData/head.js b/browser/components/preferences/in-content/tests/siteData/head.js index 4762a8ed30fa..ed66b3d58467 100644 --- a/browser/components/preferences/in-content/tests/siteData/head.js +++ b/browser/components/preferences/in-content/tests/siteData/head.js @@ -127,29 +127,66 @@ function assertSitesListed(doc, hosts) { is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button"); } -async function addTestData(data) { - let hosts = []; +const mockSiteDataManager = { - for (let site of data) { - is(typeof site.origin, "string", "Passed an origin string into addTestData."); - if (site.persisted) { - await SiteDataTestUtils.persist(site.origin); + _SiteDataManager: null, + _originalQMS: null, + _originalRemoveQuotaUsage: null, + + getUsage(onUsageResult) { + let result = this.fakeSites.map(site => ({ + origin: site.principal.origin, + usage: site.usage, + persisted: site.persisted, + lastAccessed: site.lastAccessed, + })); + onUsageResult({ result, resultCode: Cr.NS_OK }); + }, + + _removeQuotaUsage(site) { + var target = site.principals[0].URI.host; + this.fakeSites = this.fakeSites.filter(fakeSite => { + return fakeSite.principal.URI.host != target; + }); + }, + + register(siteDataManager, fakeSites) { + this._SiteDataManager = siteDataManager; + this._originalQMS = this._SiteDataManager._qms; + this._SiteDataManager._qms = this; + this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage; + this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this); + // Add some fake data. + this.fakeSites = fakeSites; + for (let site of fakeSites) { + if (!site.principal) { + site.principal = Services.scriptSecurityManager + .createCodebasePrincipalFromOrigin(site.origin); + } + + let uri = site.principal.URI; + try { + site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host); + } catch (e) { + site.baseDomain = uri.host; + } + + // Add some cookies if needed. + for (let i = 0; i < (site.cookies || 0); i++) { + Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i, + false, false, false, Date.now() + 1000 * 60 * 60, {}, + Ci.nsICookie2.SAMESITE_UNSET); + } } + }, - if (site.usage) { - await SiteDataTestUtils.addToIndexedDB(site.origin, site.usage); - } - - for (let i = 0; i < (site.cookies || 0); i++) { - SiteDataTestUtils.addToCookies(site.origin, Cu.now()); - } - - let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(site.origin); - hosts.push(principal.URI.host); - } - - return hosts; -} + async unregister() { + await this._SiteDataManager.removeAll(); + this.fakeSites = null; + this._SiteDataManager._qms = this._originalQMS; + this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage; + }, +}; function promiseCookiesCleared() { return TestUtils.topicObserved("cookie-changed", (subj, data) => { diff --git a/browser/modules/SiteDataManager.jsm b/browser/modules/SiteDataManager.jsm index bb6305f6ab99..49ace509a68a 100644 --- a/browser/modules/SiteDataManager.jsm +++ b/browser/modules/SiteDataManager.jsm @@ -3,6 +3,11 @@ const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +ChromeUtils.defineModuleGetter(this, "OfflineAppCacheHelper", + "resource://gre/modules/offlineAppCache.jsm"); +ChromeUtils.defineModuleGetter(this, "ServiceWorkerCleanUp", + "resource://gre/modules/ServiceWorkerCleanUp.jsm"); + var EXPORTED_SYMBOLS = [ "SiteDataManager", ]; @@ -320,23 +325,6 @@ var SiteDataManager = { site.cookies = []; }, - // Returns a list of permissions from the permission manager that - // we consider part of "site data and cookies". - _getDeletablePermissions() { - let perms = []; - let enumerator = Services.perms.enumerator; - - while (enumerator.hasMoreElements()) { - let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission); - if (permission.type == "persistent-storage" || - permission.type == "storage-access") { - perms.push(permission); - } - } - - return perms; - }, - /** * Removes all site data for the specified list of hosts. * @@ -345,28 +333,35 @@ var SiteDataManager = { * manager has been updated. */ async remove(hosts) { - let perms = this._getDeletablePermissions(); + // Make sure we have up-to-date information. + await this._getQuotaUsage(); + this._updateAppCache(); + + let unknownHost = ""; let promises = []; for (let host of hosts) { - promises.push(new Promise(function(resolve) { - Services.clearData.deleteDataFromHost(host, true, - Ci.nsIClearDataService.CLEAR_COOKIES | - Ci.nsIClearDataService.CLEAR_DOM_STORAGES | - Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS | - Ci.nsIClearDataService.CLEAR_PLUGIN_DATA | - Ci.nsIClearDataService.CLEAR_EME | - Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve); - })); - - for (let perm of perms) { - if (Services.eTLD.hasRootDomain(perm.principal.URI.host, host)) { - Services.perms.removePermission(perm); - } + let site = this._sites.get(host); + if (site) { + // Clear localStorage & sessionStorage + Services.obs.notifyObservers(null, "extension:purge-localStorage", host); + Services.obs.notifyObservers(null, "browser:purge-sessionStorage", host); + this._removePermission(site); + this._removeAppCache(site); + this._removeCookies(site); + promises.push(ServiceWorkerCleanUp.removeFromHost(host)); + promises.push(this._removeQuotaUsage(site)); + } else { + unknownHost = host; + break; } } await Promise.all(promises); + if (unknownHost) { + throw `SiteDataManager: removing unknown site of ${unknownHost}`; + } + return this.updateSites(); }, @@ -410,41 +405,54 @@ var SiteDataManager = { * @returns a Promise that resolves when the data is cleared. */ async removeAll() { - await this.removeCache(); + this.removeCache(); return this.removeSiteData(); }, /** - * Clears all caches. - * - * @returns a Promise that resolves when the data is cleared. + * Clears the entire network cache. */ removeCache() { - return new Promise(function(resolve) { - Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve); - }); + Services.cache2.clear(); }, /** - * Clears all site data, but not cache, because the UI offers - * that functionality separately. + * Clears all site data, which currently means + * - Cookies + * - AppCache + * - LocalStorage + * - ServiceWorkers + * - Quota Managed Storage + * - persistent-storage permissions * - * @returns a Promise that resolves when the data is cleared. + * @returns a Promise that resolves with the cache size on disk in bytes */ async removeSiteData() { - await new Promise(function(resolve) { - Services.clearData.deleteData( - Ci.nsIClearDataService.CLEAR_COOKIES | - Ci.nsIClearDataService.CLEAR_DOM_STORAGES | - Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS | - Ci.nsIClearDataService.CLEAR_EME | - Ci.nsIClearDataService.CLEAR_PLUGIN_DATA, resolve); - }); + // LocalStorage + Services.obs.notifyObservers(null, "extension:purge-localStorage"); - for (let permission of this._getDeletablePermissions()) { - Services.perms.removePermission(permission); + Services.cookies.removeAll(); + OfflineAppCacheHelper.clear(); + + await ServiceWorkerCleanUp.removeAll(); + + // Refresh sites using quota usage again. + // This is for the case: + // 1. User goes to the about:preferences Site Data section. + // 2. With the about:preferences opened, user visits another website. + // 3. The website saves to quota usage, like indexedDB. + // 4. User goes back to the Site Data section and commands to clear all site data. + // For this case, we should refresh the site list so not to miss the website in the step 3. + // We don't do "Clear All" on the quota manager like the cookie, appcache, http cache above + // because that would clear browser data as well too, + // see https://bugzilla.mozilla.org/show_bug.cgi?id=1312361#c9 + this._sites.clear(); + await this._getQuotaUsage(); + let promises = []; + for (let site of this._sites.values()) { + this._removePermission(site); + promises.push(this._removeQuotaUsage(site)); } - - return this.updateSites(); + return Promise.all(promises).then(() => this.updateSites()); }, }; diff --git a/browser/modules/test/unit/test_SiteDataManager.js b/browser/modules/test/unit/test_SiteDataManager.js deleted file mode 100644 index d181b3eb9e59..000000000000 --- a/browser/modules/test/unit/test_SiteDataManager.js +++ /dev/null @@ -1,148 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ -"use strict"; - -const EXAMPLE_ORIGIN = "https://www.example.com"; -const EXAMPLE_ORIGIN_2 = "https://example.org"; - -const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); -const {SiteDataManager} = ChromeUtils.import("resource:///modules/SiteDataManager.jsm"); -const {SiteDataTestUtils} = ChromeUtils.import("resource://testing-common/SiteDataTestUtils.jsm"); -ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm"); -ChromeUtils.defineModuleGetter(this, "TestUtils", "resource://testing-common/TestUtils.jsm"); - -add_task(function setup() { - do_get_profile(); -}); - -add_task(async function testGetSites() { - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); - await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); - - await SiteDataManager.updateSites(); - - let sites = await SiteDataManager.getSites(); - - let site1 = sites.find((site) => site.baseDomain == "example.com"); - let site2 = sites.find((site) => site.baseDomain == "example.org"); - - Assert.equal(site1.baseDomain, "example.com", "Has the correct base domain for example.com"); - Assert.equal(site1.host, "www.example.com", "Has the correct host for example.com"); - Assert.greater(site1.usage, 4096, "Has correct usage for example.com"); - Assert.equal(site1.persisted, false, "example.com is not persisted"); - Assert.equal(site1.cookies.length, 2, "Has correct number of cookies for example.com"); - Assert.ok(typeof site1.lastAccessed.getDate == "function", "lastAccessed for example.com is a Date"); - Assert.ok(site1.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.com happened recently"); - - Assert.equal(site2.baseDomain, "example.org", "Has the correct base domain for example.org"); - Assert.equal(site2.host, "example.org", "Has the correct host for example.org"); - Assert.greater(site2.usage, 2048, "Has correct usage for example.org"); - Assert.equal(site2.persisted, true, "example.org is persisted"); - Assert.equal(site2.cookies.length, 1, "Has correct number of cookies for example.org"); - Assert.ok(typeof site2.lastAccessed.getDate == "function", "lastAccessed for example.org is a Date"); - Assert.ok(site2.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.org happened recently"); - - await SiteDataTestUtils.clear(); -}); - -add_task(async function testGetTotalUsage() { - await SiteDataManager.updateSites(); - let sites = await SiteDataManager.getSites(); - Assert.equal(sites.length, 0, "SiteDataManager is empty"); - - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); - - await SiteDataManager.updateSites(); - - let usage = await SiteDataManager.getTotalUsage(); - - Assert.greater(usage, 4096 + 2048, "Has the correct total usage."); - - await SiteDataTestUtils.clear(); -}); - -add_task(async function testRemove() { - await SiteDataManager.updateSites(); - - let uri = Services.io.newURI(EXAMPLE_ORIGIN); - Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION); - - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); - await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); - - await SiteDataManager.updateSites(); - - let sites = await SiteDataManager.getSites(); - - Assert.equal(sites.length, 2, "Has two sites."); - - await SiteDataManager.remove(["www.example.com"]); - - sites = await SiteDataManager.getSites(); - - Assert.equal(sites.length, 1, "Has one site."); - Assert.equal(sites[0].host, "example.org", "Has not cleared data for example.org"); - - let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN); - Assert.equal(usage, 0, "Has cleared quota usage for example.com"); - - let cookies = Services.cookies.countCookiesFromHost("example.com"); - Assert.equal(cookies, 0, "Has cleared cookies for example.com"); - - let perm = Services.perms.testPermission(uri, "persistent-storage"); - Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission."); - perm = Services.perms.testPermission(uri, "camera"); - Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions."); - - Services.perms.remove(uri, "camera"); -}); - -add_task(async function testRemoveSiteData() { - let uri = Services.io.newURI(EXAMPLE_ORIGIN); - Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION); - - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1"); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096); - SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar"); - await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048); - await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2); - - await SiteDataManager.updateSites(); - - let sites = await SiteDataManager.getSites(); - - Assert.equal(sites.length, 2, "Has two sites."); - - await SiteDataManager.removeSiteData(); - - sites = await SiteDataManager.getSites(); - - Assert.equal(sites.length, 0, "Has no sites."); - - let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN); - Assert.equal(usage, 0, "Has cleared quota usage for example.com"); - - usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN_2); - Assert.equal(usage, 0, "Has cleared quota usage for example.org"); - - let cookies = Services.cookies.countCookiesFromHost("example.org"); - Assert.equal(cookies, 0, "Has cleared cookies for example.org"); - - let perm = Services.perms.testPermission(uri, "persistent-storage"); - Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission."); - perm = Services.perms.testPermission(uri, "camera"); - Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions."); - - Services.perms.remove(uri, "camera"); -}); diff --git a/browser/modules/test/unit/xpcshell.ini b/browser/modules/test/unit/xpcshell.ini index 75957a037d1c..e934e2613ec9 100644 --- a/browser/modules/test/unit/xpcshell.ini +++ b/browser/modules/test/unit/xpcshell.ini @@ -8,6 +8,5 @@ skip-if = toolkit == 'android' [test_LiveBookmarkMigrator.js] [test_Sanitizer_interrupted.js] [test_SitePermissions.js] -[test_SiteDataManager.js] [test_LaterRun.js] [test_discovery.js] From 1e0e61116db7eb105fb5bdb259d2852e4284c940 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Thu, 14 Feb 2019 16:35:27 +0000 Subject: [PATCH 39/84] Bug 1526322 - Ensure GeckoWebExecutor doesn't clobber the Content-Type header. r=csadilek Differential Revision: https://phabricator.services.mozilla.com/D19506 --HG-- extra : moz-landing-system : lando --- .../org/mozilla/geckoview/test/WebExecutorTest.kt | 2 ++ widget/android/WebExecutorSupport.cpp | 15 ++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExecutorTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExecutorTest.kt index 6add031baeee..7ae2cce48535 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExecutorTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExecutorTest.kt @@ -107,6 +107,7 @@ class WebExecutorTest { .addHeader("Header2", "Value1") .addHeader("Header2", "Value2") .referrer(referrer) + .header("Content-Type", "text/plain") .body(bodyString.toDirectByteBuffer()) .build() @@ -121,6 +122,7 @@ class WebExecutorTest { assertThat("Method should match", body.getString("method"), equalTo("POST")) assertThat("Headers should match", body.getJSONObject("headers").getString("Header1"), equalTo("Value")) assertThat("Headers should match", body.getJSONObject("headers").getString("Header2"), equalTo("Value1, Value2")) + assertThat("Headers should match", body.getJSONObject("headers").getString("Content-Type"), equalTo("text/plain")) assertThat("Referrer should match", body.getJSONObject("headers").getString("Referer"), equalTo(referrer)) assertThat("Data should match", body.getString("data"), equalTo(bodyString)); } diff --git a/widget/android/WebExecutorSupport.cpp b/widget/android/WebExecutorSupport.cpp index efa0289270d4..eb67a0bd76b6 100644 --- a/widget/android/WebExecutorSupport.cpp +++ b/widget/android/WebExecutorSupport.cpp @@ -362,14 +362,19 @@ nsresult WebExecutorSupport::CreateStreamLoader( // Headers const auto keys = reqBase->GetHeaderKeys(); const auto values = reqBase->GetHeaderValues(); + auto contentType = EmptyCString(); for (size_t i = 0; i < keys->Length(); i++) { - const auto key = jni::String::LocalRef(keys->GetElement(i)); - const auto value = jni::String::LocalRef(values->GetElement(i)); + const auto key = jni::String::LocalRef(keys->GetElement(i))->ToCString(); + const auto value = + jni::String::LocalRef(values->GetElement(i))->ToCString(); + + if (key.LowerCaseEqualsASCII("content-type")) { + contentType = value; + } // We clobber any duplicate keys here because we've already merged them // in the upstream WebRequest. - rv = httpChannel->SetRequestHeader(key->ToCString(), value->ToCString(), - false /* merge */); + rv = httpChannel->SetRequestHeader(key, value, false /* merge */); NS_ENSURE_SUCCESS(rv, rv); } @@ -382,7 +387,7 @@ nsresult WebExecutorSupport::CreateStreamLoader( NS_ENSURE_SUCCESS(rv, rv); rv = uploadChannel->ExplicitSetUploadStream( - stream, EmptyCString(), -1, aRequest->Method()->ToCString(), false); + stream, contentType, -1, aRequest->Method()->ToCString(), false); NS_ENSURE_SUCCESS(rv, rv); } From 0cb12a123a449a9b5e87e83b176bcdd8ff0ce622 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Thu, 14 Feb 2019 16:40:58 +0000 Subject: [PATCH 40/84] Bug 1400344: Rename mscom::MainThreadRuntime to mscom::ProcessRuntime and make it aware of Win32k lockdown and of multiple instantiations; r=Jamie This patch takes care of a bunch of issues and does some cleanup: * We rename mscom::MainThreadRuntime to mscom::ProcessRuntime, as the latter is a more accurate name going forward. * We make ProcessRuntime aware of the Win32k Lockdown process mitigation policy. When Win32k is disabled, we perform process-wide COM initialization in the multi-threaded apartment (since we cannot create an STA window). * We refactor the mscom apartment region stuff to enable the Win32k lockdown pieces in ProcessRuntime. * We move some Gecko-specific stuff into MOZILLA_INTERNAL_API guards so that ProcessRuntime is usable outside of xul.dll (I will be needing it for the launcher process). * Another thing that might happen with the launcher process is that, under error conditions in the launcher, we create a ProcessRuntime object on a background thread for the purposes of telemetry logging, but we also allow the main thread to proceed to start as the browser. This could result in a scenario where the main thread, as the browser process, is attempting to instantiate its ProcessRuntime and ends up racing with the launcher process's telemetry thread which has its own ProcessRuntime. To account for this situation, we add mutual exclusion to the process-wide initialization code. We host this part inside mozglue since that state is shared between both firefox.exe and xul.dll. * We clean up ProcessRuntime::InitializeSecurity by using Vector to set up the EXPLICIT_ACCESS entries. * We remove mscom::MainThreadClientInfo and replace it with a direct call to CoGetCallerTID * We revise all references to this class to use the new name. Differential Revision: https://phabricator.services.mozilla.com/D19551 --HG-- rename : ipc/mscom/COMApartmentRegion.h => ipc/mscom/ApartmentRegion.h rename : ipc/mscom/MainThreadRuntime.cpp => ipc/mscom/ProcessRuntime.cpp rename : ipc/mscom/MainThreadRuntime.h => ipc/mscom/ProcessRuntime.h extra : moz-landing-system : lando --- accessible/windows/msaa/LazyInstantiator.cpp | 4 +- browser/app/winlauncher/LaunchUnelevated.cpp | 2 +- dom/ipc/ContentProcess.h | 4 +- dom/media/ipc/RDDProcessImpl.h | 2 +- dom/plugins/ipc/PluginProcessChild.h | 4 +- gfx/ipc/GPUProcessImpl.h | 4 +- ipc/mscom/ApartmentRegion.h | 94 ++++++++ ipc/mscom/COMApartmentRegion.h | 53 ----- ipc/mscom/EnsureMTA.h | 1 - ipc/mscom/MainThreadClientInfo.cpp | 133 ----------- ipc/mscom/MainThreadClientInfo.h | 52 ----- ipc/mscom/MainThreadRuntime.h | 58 ----- ...inThreadRuntime.cpp => ProcessRuntime.cpp} | 213 ++++++++++-------- ipc/mscom/ProcessRuntime.h | 61 +++++ ipc/mscom/Ptr.h | 2 + ipc/mscom/moz.build | 12 +- ipc/mscom/mozglue/ProcessRuntimeShared.cpp | 33 +++ ipc/mscom/mozglue/ProcessRuntimeShared.h | 54 +++++ ipc/mscom/mozglue/moz.build | 21 ++ mozglue/build/moz.build | 3 + toolkit/xre/nsAppRunner.cpp | 4 +- widget/windows/JumpListBuilder.cpp | 2 +- 22 files changed, 412 insertions(+), 404 deletions(-) create mode 100644 ipc/mscom/ApartmentRegion.h delete mode 100644 ipc/mscom/COMApartmentRegion.h delete mode 100644 ipc/mscom/MainThreadClientInfo.cpp delete mode 100644 ipc/mscom/MainThreadClientInfo.h delete mode 100644 ipc/mscom/MainThreadRuntime.h rename ipc/mscom/{MainThreadRuntime.cpp => ProcessRuntime.cpp} (52%) create mode 100644 ipc/mscom/ProcessRuntime.h create mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.cpp create mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.h create mode 100644 ipc/mscom/mozglue/moz.build diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp index f376e40d1621..a82a2738d446 100644 --- a/accessible/windows/msaa/LazyInstantiator.cpp +++ b/accessible/windows/msaa/LazyInstantiator.cpp @@ -11,7 +11,7 @@ #include "mozilla/a11y/Compatibility.h" #include "mozilla/a11y/Platform.h" #include "mozilla/Assertions.h" -#include "mozilla/mscom/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" #include "mozilla/mscom/Registration.h" #include "mozilla/UniquePtr.h" #include "nsAccessibilityService.h" @@ -313,7 +313,7 @@ LazyInstantiator::MaybeResolveRoot() { } if (GetAccService() || - ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) { + ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) { mWeakRootAccWrap = ResolveRootAccWrap(); if (!mWeakRootAccWrap) { return E_POINTER; diff --git a/browser/app/winlauncher/LaunchUnelevated.cpp b/browser/app/winlauncher/LaunchUnelevated.cpp index b0ba54df7908..38ee8e66986b 100644 --- a/browser/app/winlauncher/LaunchUnelevated.cpp +++ b/browser/app/winlauncher/LaunchUnelevated.cpp @@ -9,7 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/LauncherResult.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/RefPtr.h" #include "nsWindowsHelpers.h" diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h index eb9a908328dd..c6b2a58684b8 100644 --- a/dom/ipc/ContentProcess.h +++ b/dom/ipc/ContentProcess.h @@ -12,7 +12,7 @@ #include "ContentChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -39,7 +39,7 @@ class ContentProcess : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif DISALLOW_EVIL_CONSTRUCTORS(ContentProcess); diff --git a/dom/media/ipc/RDDProcessImpl.h b/dom/media/ipc/RDDProcessImpl.h index a75f1934758e..8c044132da34 100644 --- a/dom/media/ipc/RDDProcessImpl.h +++ b/dom/media/ipc/RDDProcessImpl.h @@ -8,7 +8,7 @@ #include "mozilla/ipc/ProcessChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif #include "RDDParent.h" diff --git a/dom/plugins/ipc/PluginProcessChild.h b/dom/plugins/ipc/PluginProcessChild.h index 48d3bc066a76..b715f0d649a0 100644 --- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -11,7 +11,7 @@ #include "mozilla/plugins/PluginModuleChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -40,7 +40,7 @@ class PluginProcessChild : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) /* Drag-and-drop depends on the host initializing COM. * This object initializes and configures COM. */ - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif PluginModuleChild mPlugin; diff --git a/gfx/ipc/GPUProcessImpl.h b/gfx/ipc/GPUProcessImpl.h index a76aeb406b33..a205e2b2333b 100644 --- a/gfx/ipc/GPUProcessImpl.h +++ b/gfx/ipc/GPUProcessImpl.h @@ -10,7 +10,7 @@ #include "GPUParent.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -33,7 +33,7 @@ class GPUProcessImpl final : public ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif }; diff --git a/ipc/mscom/ApartmentRegion.h b/ipc/mscom/ApartmentRegion.h new file mode 100644 index 000000000000..dc56e3fc9676 --- /dev/null +++ b/ipc/mscom/ApartmentRegion.h @@ -0,0 +1,94 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ApartmentRegion_h +#define mozilla_mscom_ApartmentRegion_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ApartmentRegion { + public: + /** + * This constructor is to be used when we want to instantiate the object but + * we do not yet know which type of apartment we want. Call Init() to + * complete initialization. + */ + ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} + + explicit ApartmentRegion(COINIT aAptType) + : mInitResult(::CoInitializeEx(nullptr, aAptType)) { + // If this fires then we're probably mixing apartments on the same thread + MOZ_ASSERT(IsValid()); + } + + ~ApartmentRegion() { + if (IsValid()) { + ::CoUninitialize(); + } + } + + explicit operator bool() const { return IsValid(); } + + bool IsValidOutermost() const { return mInitResult == S_OK; } + + bool IsValid() const { return SUCCEEDED(mInitResult); } + + bool Init(COINIT aAptType) { + MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); + mInitResult = ::CoInitializeEx(nullptr, aAptType); + MOZ_ASSERT(IsValid()); + return IsValid(); + } + + HRESULT + GetHResult() const { return mInitResult; } + + private: + ApartmentRegion(const ApartmentRegion&) = delete; + ApartmentRegion& operator=(const ApartmentRegion&) = delete; + ApartmentRegion(ApartmentRegion&&) = delete; + ApartmentRegion& operator=(ApartmentRegion&&) = delete; + + HRESULT mInitResult; +}; + +template +class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT { + public: + ApartmentRegionT() : mAptRgn(T) {} + + ~ApartmentRegionT() = default; + + explicit operator bool() const { return mAptRgn.IsValid(); } + + bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); } + + bool IsValid() const { return mAptRgn.IsValid(); } + + HRESULT GetHResult() const { return mAptRgn.GetHResult(); } + + private: + ApartmentRegionT(const ApartmentRegionT&) = delete; + ApartmentRegionT& operator=(const ApartmentRegionT&) = delete; + ApartmentRegionT(ApartmentRegionT&&) = delete; + ApartmentRegionT& operator=(ApartmentRegionT&&) = delete; + + ApartmentRegion mAptRgn; +}; + +typedef ApartmentRegionT STARegion; +typedef ApartmentRegionT MTARegion; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ApartmentRegion_h diff --git a/ipc/mscom/COMApartmentRegion.h b/ipc/mscom/COMApartmentRegion.h deleted file mode 100644 index 9fbd8c87967d..000000000000 --- a/ipc/mscom/COMApartmentRegion.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_COMApartmentRegion_h -#define mozilla_mscom_COMApartmentRegion_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include - -namespace mozilla { -namespace mscom { - -template -class MOZ_NON_TEMPORARY_CLASS COMApartmentRegion { - public: - COMApartmentRegion() : mInitResult(::CoInitializeEx(nullptr, T)) { - // If this fires then we're probably mixing apartments on the same thread - MOZ_ASSERT(IsValid()); - } - - ~COMApartmentRegion() { - if (IsValid()) { - ::CoUninitialize(); - } - } - - bool IsValidOutermost() const { return mInitResult == S_OK; } - - bool IsValid() const { return SUCCEEDED(mInitResult); } - - HRESULT GetHResult() const { return mInitResult; } - - private: - COMApartmentRegion(const COMApartmentRegion&) = delete; - COMApartmentRegion& operator=(const COMApartmentRegion&) = delete; - COMApartmentRegion(COMApartmentRegion&&) = delete; - COMApartmentRegion& operator=(COMApartmentRegion&&) = delete; - - HRESULT mInitResult; -}; - -typedef COMApartmentRegion STARegion; -typedef COMApartmentRegion MTARegion; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_COMApartmentRegion_h diff --git a/ipc/mscom/EnsureMTA.h b/ipc/mscom/EnsureMTA.h index 690d55101e2b..7719b0f324c6 100644 --- a/ipc/mscom/EnsureMTA.h +++ b/ipc/mscom/EnsureMTA.h @@ -11,7 +11,6 @@ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/Unused.h" -#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/mscom/Utils.h" #include "nsCOMPtr.h" #include "nsIThread.h" diff --git a/ipc/mscom/MainThreadClientInfo.cpp b/ipc/mscom/MainThreadClientInfo.cpp deleted file mode 100644 index d163d05dbf8a..000000000000 --- a/ipc/mscom/MainThreadClientInfo.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- 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 "MainThreadClientInfo.h" - -#include "MainThreadUtils.h" -#include "mozilla/Assertions.h" - -#include - -namespace mozilla { -namespace mscom { - -/* static */ -HRESULT -MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) { - MOZ_ASSERT(aOutObj && NS_IsMainThread()); - *aOutObj = nullptr; - - RefPtr obj(new MainThreadClientInfo()); - - RefPtr prevFilter; - HRESULT hr = ::CoRegisterMessageFilter(obj.get(), getter_AddRefs(prevFilter)); - if (FAILED(hr)) { - return hr; - } - - obj->mPrevFilter = prevFilter.forget(); - - obj.forget(aOutObj); - return S_OK; -} - -DWORD -MainThreadClientInfo::GetLastRemoteCallThreadId() const { - MOZ_ASSERT(NS_IsMainThread()); - return mLastRemoteCallTid; -} - -HRESULT -MainThreadClientInfo::QueryInterface(REFIID aIid, void** aOutInterface) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!aOutInterface) { - return E_INVALIDARG; - } - - if (aIid == IID_IUnknown || aIid == IID_IMessageFilter) { - RefPtr filter(this); - filter.forget(aOutInterface); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG -MainThreadClientInfo::AddRef() { - MOZ_ASSERT(NS_IsMainThread()); - - return ++mRefCnt; -} - -ULONG -MainThreadClientInfo::Release() { - MOZ_ASSERT(NS_IsMainThread()); - - ULONG newCount = --mRefCnt; - if (!newCount) { - delete this; - } - return newCount; -} - -DWORD -MainThreadClientInfo::HandleInComingCall(DWORD aCallType, HTASK aCallerTid, - DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) { - MOZ_ASSERT(NS_IsMainThread()); - - // aCallerTid is an HTASK for historical reasons but is actually just a - // regular DWORD Thread ID. - mLastRemoteCallTid = - static_cast(reinterpret_cast(aCallerTid)); - - if (!mPrevFilter) { - return SERVERCALL_ISHANDLED; - } - - return mPrevFilter->HandleInComingCall(aCallType, aCallerTid, aTickCount, - aInterfaceInfo); -} - -DWORD -MainThreadClientInfo::RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return 0; - } - - return mPrevFilter->RetryRejectedCall(aCalleeTid, aTickCount, aRejectType); -} - -DWORD -MainThreadClientInfo::MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return PENDINGMSG_WAITNOPROCESS; - } - - return mPrevFilter->MessagePending(aCalleeTid, aTickCount, aPendingType); -} - -MainThreadClientInfo::MainThreadClientInfo() - : mRefCnt(0), mLastRemoteCallTid(0) { - MOZ_ASSERT(NS_IsMainThread()); -} - -void MainThreadClientInfo::Detach() { - MOZ_ASSERT(NS_IsMainThread()); - ::CoRegisterMessageFilter(mPrevFilter, nullptr); - mPrevFilter = nullptr; -} - -} // namespace mscom -} // namespace mozilla diff --git a/ipc/mscom/MainThreadClientInfo.h b/ipc/mscom/MainThreadClientInfo.h deleted file mode 100644 index e762ec9b00a2..000000000000 --- a/ipc/mscom/MainThreadClientInfo.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_MainThreadClientInfo -#define mozilla_mscom_MainThreadClientInfo - -#include "mozilla/RefPtr.h" -#include "nsString.h" - -#include - -namespace mozilla { -namespace mscom { - -class MainThreadClientInfo final : public IMessageFilter { - public: - static HRESULT Create(MainThreadClientInfo** aOutObj); - - DWORD GetLastRemoteCallThreadId() const; - void Detach(); - - STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - STDMETHODIMP_(DWORD) - HandleInComingCall(DWORD aCallType, HTASK aCallerTid, DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) override; - STDMETHODIMP_(DWORD) - RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) override; - STDMETHODIMP_(DWORD) - MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) override; - - private: - MainThreadClientInfo(); - ~MainThreadClientInfo() = default; - - private: - ULONG mRefCnt; - RefPtr mPrevFilter; - DWORD mLastRemoteCallTid; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadClientInfo diff --git a/ipc/mscom/MainThreadRuntime.h b/ipc/mscom/MainThreadRuntime.h deleted file mode 100644 index 00cae6c1965e..000000000000 --- a/ipc/mscom/MainThreadRuntime.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_MainThreadRuntime_h -#define mozilla_mscom_MainThreadRuntime_h - -#include "mozilla/Attributes.h" -#if defined(ACCESSIBILITY) -# include "mozilla/mscom/ActivationContext.h" -#endif // defined(ACCESSIBILITY) -#include "mozilla/mscom/COMApartmentRegion.h" -#include "mozilla/mscom/MainThreadClientInfo.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { -namespace mscom { - -class MOZ_NON_TEMPORARY_CLASS MainThreadRuntime { - public: - MainThreadRuntime(); - ~MainThreadRuntime(); - - explicit operator bool() const { - return mStaRegion.IsValidOutermost() && SUCCEEDED(mInitResult); - } - - MainThreadRuntime(MainThreadRuntime&) = delete; - MainThreadRuntime(MainThreadRuntime&&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&&) = delete; - - /** - * @return 0 if call is in-process or resolving the calling thread failed, - * otherwise contains the thread id of the calling thread. - */ - static DWORD GetClientThreadId(); - - private: - HRESULT InitializeSecurity(); - - HRESULT mInitResult; -#if defined(ACCESSIBILITY) - ActivationContextRegion mActCtxRgn; -#endif // defined(ACCESSIBILITY) - STARegion mStaRegion; - - RefPtr mClientInfo; - - static MainThreadRuntime* sInstance; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadRuntime_h diff --git a/ipc/mscom/MainThreadRuntime.cpp b/ipc/mscom/ProcessRuntime.cpp similarity index 52% rename from ipc/mscom/MainThreadRuntime.cpp rename to ipc/mscom/ProcessRuntime.cpp index bce1701e4891..ffbb9261d6d0 100644 --- a/ipc/mscom/MainThreadRuntime.cpp +++ b/ipc/mscom/ProcessRuntime.cpp @@ -4,21 +4,25 @@ * 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 "mozilla/mscom/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" -#if defined(ACCESSIBILITY) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) # include "mozilla/a11y/Compatibility.h" -#endif -#include "mozilla/ArrayUtils.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) #include "mozilla/Assertions.h" +#include "mozilla/DynamicallyLinkedFunctionPtr.h" +#include "mozilla/mscom/ProcessRuntimeShared.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" +#include "mozilla/Unused.h" +#include "mozilla/Vector.h" #include "mozilla/WindowsVersion.h" -#if defined(ACCESSIBILITY) -# include "nsExceptionHandler.h" -#endif // defined(ACCESSIBILITY) #include "nsWindowsHelpers.h" -#include "nsXULAppAPI.h" + +#if defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/EnsureMTA.h" +# include "nsThreadManager.h" +#endif // defined(MOZILLA_INTERNAL_API) #include #include @@ -28,27 +32,65 @@ // This API from oleaut32.dll is not declared in Windows SDK headers extern "C" void __cdecl SetOaNoCache(void); +#if (_WIN32_WINNT < 0x0602) +BOOL WINAPI GetProcessMitigationPolicy( + HANDLE hProcess, PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, + SIZE_T dwLength); +#endif // (_WIN32_WINNT < 0x0602) + namespace mozilla { namespace mscom { -MainThreadRuntime* MainThreadRuntime::sInstance = nullptr; - -MainThreadRuntime::MainThreadRuntime() - : mInitResult(E_UNEXPECTED) -#if defined(ACCESSIBILITY) +ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType) + : mInitResult(CO_E_NOTINITIALIZED), + mIsParentProcess(aProcessType == GeckoProcessType_Default) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId()) -#endif // defined(ACCESSIBILITY) +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) { +#if defined(MOZILLA_INTERNAL_API) + // If our process is running under Win32k lockdown, we cannot initialize + // COM with single-threaded apartments. This is because STAs create a hidden + // window, which implicitly requires user32 and Win32k, which are blocked. + // Instead we start a multi-threaded apartment and conduct our process-wide + // COM initialization on that MTA background thread. + if (IsWin32kLockedDown()) { + // It is possible that we're running so early that we might need to start + // the thread manager ourselves. + nsresult rv = nsThreadManager::get().Init(); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + if (NS_FAILED(rv)) { + return; + } + + EnsureMTA([this]() -> void { InitInsideApartment(); }); + return; + } +#endif // defined(MOZILLA_INTERNAL_API) + + // Otherwise we initialize a single-threaded apartment on the current thread. + mAptRegion.Init(COINIT_APARTMENTTHREADED); + // We must be the outermost COM initialization on this thread. The COM runtime // cannot be configured once we start manipulating objects - MOZ_ASSERT(mStaRegion.IsValidOutermost()); - if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) { + MOZ_ASSERT(mAptRegion.IsValidOutermost()); + if (!mAptRegion.IsValidOutermost()) { + mInitResult = mAptRegion.GetHResult(); return; } - // We are required to initialize security in order to configure global - // options. + InitInsideApartment(); +} + +void ProcessRuntime::InitInsideApartment() { + ProcessInitLock lock; + if (lock.IsInitialized()) { + // COM has already been initialized by a previous ProcessRuntime instance + return; + } + + // We are required to initialize security prior to configuring global options. mInitResult = InitializeSecurity(); MOZ_ASSERT(SUCCEEDED(mInitResult)); if (FAILED(mInitResult)) { @@ -76,58 +118,25 @@ MainThreadRuntime::MainThreadRuntime() return; } - if (XRE_IsParentProcess()) { - MainThreadClientInfo::Create(getter_AddRefs(mClientInfo)); - } - - MOZ_ASSERT(!sInstance); - sInstance = this; -} - -MainThreadRuntime::~MainThreadRuntime() { - if (mClientInfo) { - mClientInfo->Detach(); - } - - MOZ_ASSERT(sInstance == this); - if (sInstance == this) { - sInstance = nullptr; - } + lock.SetInitialized(); } /* static */ DWORD -MainThreadRuntime::GetClientThreadId() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_IsParentProcess(), "Unsupported outside of parent process"); - if (!XRE_IsParentProcess()) { +ProcessRuntime::GetClientThreadId() { + DWORD callerTid; + HRESULT hr = ::CoGetCallerTID(&callerTid); + // Don't return callerTid unless the call succeeded and returned S_FALSE, + // indicating that the caller originates from a different process. + if (hr != S_FALSE) { return 0; } - // Don't check for a calling executable if the caller is in-process. - // We verify this by asking COM for a call context. If none exists, then - // we must be a local call. - RefPtr serverSecurity; - if (FAILED(::CoGetCallContext(IID_IServerSecurity, - getter_AddRefs(serverSecurity)))) { - return 0; - } - - MOZ_ASSERT(sInstance); - if (!sInstance) { - return 0; - } - - MOZ_ASSERT(sInstance->mClientInfo); - if (!sInstance->mClientInfo) { - return 0; - } - - return sInstance->mClientInfo->GetLastRemoteCallThreadId(); + return callerTid; } HRESULT -MainThreadRuntime::InitializeSecurity() { +ProcessRuntime::InitializeSecurity() { HANDLE rawToken = nullptr; BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken); if (!ok) { @@ -186,7 +195,7 @@ MainThreadRuntime::InitializeSecurity() { BYTE appContainersSid[SECURITY_MAX_SID_SIZE]; DWORD appContainersSidSize = sizeof(appContainersSid); - if (XRE_IsParentProcess() && IsWin8OrLater()) { + if (mIsParentProcess && IsWin8OrLater()) { if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr, appContainersSid, &appContainersSidSize)) { return HRESULT_FROM_WIN32(::GetLastError()); @@ -195,38 +204,43 @@ MainThreadRuntime::InitializeSecurity() { // Grant access to SYSTEM, Administrators, the user, and when running as the // browser process on Windows 8+, all app containers. - EXPLICIT_ACCESS entries[] = { - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(systemSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(tokenUser.User.Sid)}}, - // appContainersSid must be the last entry in this array! - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, - reinterpret_cast(appContainersSid)}}}; + const size_t kMaxInlineEntries = 4; + mozilla::Vector entries; - ULONG numEntries = ArrayLength(entries); - if (!XRE_IsParentProcess() || !IsWin8OrLater()) { - // Exclude appContainersSid on Windows 7 and non-parent processes. - --numEntries; + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(systemSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(tokenUser.User.Sid)}}); + + if (mIsParentProcess && IsWin8OrLater()) { + Unused << entries.append( + EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, + reinterpret_cast(appContainersSid)}}); } PACL rawDacl = nullptr; - win32Error = ::SetEntriesInAcl(numEntries, entries, nullptr, &rawDacl); + win32Error = + ::SetEntriesInAclW(entries.length(), entries.begin(), nullptr, &rawDacl); if (win32Error != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(win32Error); } @@ -251,5 +265,26 @@ MainThreadRuntime::InitializeSecurity() { RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr); } +#if defined(MOZILLA_INTERNAL_API) + +/* static */ bool +ProcessRuntime::IsWin32kLockedDown() { + static const DynamicallyLinkedFunctionPtr + pGetProcessMitigationPolicy(L"kernel32.dll", "GetProcessMitigationPolicy"); + if (!pGetProcessMitigationPolicy) { + return false; + } + + PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY polInfo; + if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), + ProcessSystemCallDisablePolicy, &polInfo, sizeof(polInfo))) { + return false; + } + + return polInfo.DisallowWin32kSystemCalls; +} + +#endif // defined(MOZILLA_INTERNAL_API) + } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/ProcessRuntime.h b/ipc/mscom/ProcessRuntime.h new file mode 100644 index 000000000000..3d27e8f43d82 --- /dev/null +++ b/ipc/mscom/ProcessRuntime.h @@ -0,0 +1,61 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ProcessRuntime_h +#define mozilla_mscom_ProcessRuntime_h + +#include "mozilla/Attributes.h" +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/ActivationContext.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#include "mozilla/mscom/ApartmentRegion.h" +#include "nsXULAppAPI.h" + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final { + public: +#if defined(MOZILLA_INTERNAL_API) + ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {} +#endif // defined(MOZILLA_INTERNAL_API) + + explicit ProcessRuntime(GeckoProcessType aProcessType); + ~ProcessRuntime() = default; + + explicit operator bool() const { return SUCCEEDED(mInitResult); } + + ProcessRuntime(ProcessRuntime&) = delete; + ProcessRuntime(ProcessRuntime&&) = delete; + ProcessRuntime& operator=(ProcessRuntime&) = delete; + ProcessRuntime& operator=(ProcessRuntime&&) = delete; + + /** + * @return 0 if call is in-process or resolving the calling thread failed, + * otherwise contains the thread id of the calling thread. + */ + static DWORD GetClientThreadId(); + + private: + void InitInsideApartment(); + HRESULT InitializeSecurity(); + +#if defined(MOZILLA_INTERNAL_API) + static bool IsWin32kLockedDown(); +#endif // defined(MOZILLA_INTERNAL_API) + + HRESULT mInitResult; + bool mIsParentProcess; +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ActivationContextRegion mActCtxRgn; +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ApartmentRegion mAptRegion; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntime_h diff --git a/ipc/mscom/Ptr.h b/ipc/mscom/Ptr.h index 9df05b4a0b79..98cbef684f94 100644 --- a/ipc/mscom/Ptr.h +++ b/ipc/mscom/Ptr.h @@ -16,6 +16,8 @@ #include "nsThreadUtils.h" #include "nsXULAppAPI.h" +#include + /** * The glue code in mozilla::mscom often needs to pass around interface pointers * belonging to a different apartment from the current one. We must not touch diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index 5f425ceb806b..71a3cb05f8d5 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -7,19 +7,22 @@ EXPORTS.mozilla.mscom += [ 'Aggregation.h', 'AgileReference.h', + 'ApartmentRegion.h', 'AsyncInvoker.h', - 'COMApartmentRegion.h', 'COMPtrHolder.h', 'EnsureMTA.h', - 'MainThreadClientInfo.h', - 'MainThreadRuntime.h', 'Objref.h', 'PassthruProxy.h', + 'ProcessRuntime.h', 'ProxyStream.h', 'Ptr.h', 'Utils.h', ] +DIRS += [ + 'mozglue', +] + SOURCES += [ 'VTableBuilder.c', ] @@ -27,10 +30,9 @@ SOURCES += [ UNIFIED_SOURCES += [ 'AgileReference.cpp', 'EnsureMTA.cpp', - 'MainThreadClientInfo.cpp', - 'MainThreadRuntime.cpp', 'Objref.cpp', 'PassthruProxy.cpp', + 'ProcessRuntime.cpp', 'ProxyStream.cpp', 'RegistrationAnnotator.cpp', 'Utils.cpp', diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp new file mode 100644 index 000000000000..517918f2d87c --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp @@ -0,0 +1,33 @@ +/* -*- 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 "mozilla/mscom/ProcessRuntimeShared.h" +#include "MozglueUtils.h" + +// We allow multiple ProcessRuntime instances to exist simultaneously (even +// on separate threads), but only one should be doing the process-wide +// initialization. These variables provide that mutual exclusion. +static mozilla::glue::Win32SRWLock gLock; +static bool gIsProcessInitialized = false; + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& +BeginProcessRuntimeInit() { + gLock.LockExclusive(); + return gIsProcessInitialized; +} + +MFBT_API void +EndProcessRuntimeInit() { + gLock.UnlockExclusive(); +} + +} // namespace detail +} // namespace mscom +} // namespace mozilla diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.h b/ipc/mscom/mozglue/ProcessRuntimeShared.h new file mode 100644 index 000000000000..a42b1b818e54 --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.h @@ -0,0 +1,54 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ProcessRuntimeShared_h +#define mozilla_mscom_ProcessRuntimeShared_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/Types.h" + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& BeginProcessRuntimeInit(); +MFBT_API void EndProcessRuntimeInit(); + +} // namespace detail + +class MOZ_RAII ProcessInitLock final { + public: + ProcessInitLock() + : mIsProcessInitialized(detail::BeginProcessRuntimeInit()) { + } + + ~ProcessInitLock() { + detail::EndProcessRuntimeInit(); + } + + bool IsInitialized() const { + return mIsProcessInitialized; + } + + void SetInitialized() { + MOZ_ASSERT(!mIsProcessInitialized); + mIsProcessInitialized = true; + } + + ProcessInitLock(const ProcessInitLock&) = delete; + ProcessInitLock(ProcessInitLock&&) = delete; + ProcessInitLock operator=(const ProcessInitLock&) = delete; + ProcessInitLock operator=(ProcessInitLock&&) = delete; + + private: + bool& mIsProcessInitialized; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntimeShared_h diff --git a/ipc/mscom/mozglue/moz.build b/ipc/mscom/mozglue/moz.build new file mode 100644 index 000000000000..2d444a2e50af --- /dev/null +++ b/ipc/mscom/mozglue/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Library('mscom-mozglue') + +EXPORTS.mozilla.mscom += [ + 'ProcessRuntimeShared.h', +] + +LOCAL_INCLUDES += [ + '/mozglue/build', +] + +DEFINES['IMPL_MFBT'] = True + +UNIFIED_SOURCES += [ + 'ProcessRuntimeShared.cpp', +] diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 4a5a18c659a4..aa4e8710de96 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -36,6 +36,9 @@ if CONFIG['OS_TARGET'] == 'WINNT': 'user32.dll', ] RCINCLUDE = 'mozglue.rc' + USE_LIBS += [ + 'mscom-mozglue', + ] if CONFIG['MOZ_PGO'] and CONFIG['CC_TYPE'] == 'clang-cl': SOURCES += ['cygprofile.cpp'] diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index fc91477d20cb..9454ea1dd871 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -110,7 +110,7 @@ # include "cairo/cairo-features.h" # include "mozilla/WindowsDllBlocklist.h" # include "mozilla/WinHeaderOnlyUtils.h" -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" # include "mozilla/widget/AudioSession.h" # if defined(MOZ_LAUNCHER_PROCESS) @@ -4803,7 +4803,7 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) { // trivial COM is run in the application. Since these settings may affect // stability, we should instantiate COM ASAP so that we can ensure that these // global settings are configured before anything can interfere. - mozilla::mscom::MainThreadRuntime msCOMRuntime; + mozilla::mscom::ProcessRuntime msCOMRuntime; #endif // init diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp index 48c419828a36..32cd7d03be41 100644 --- a/widget/windows/JumpListBuilder.cpp +++ b/widget/windows/JumpListBuilder.cpp @@ -23,7 +23,7 @@ #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "mozilla/dom/Promise.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/mscom/EnsureMTA.h" #include From 340eefe66ecfe5853d1e7af00addd617436dfe90 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Thu, 14 Feb 2019 16:26:19 +0000 Subject: [PATCH 41/84] Bug 1527843 - Don't take the slow path for cross-realm functions in IonBuilder::createThis. r=anba This has some minor fixes to ensure we create the object in the callee's realm for MCreateThisWithTemplate and MCreateThisWithProto. It also fixes Baseline to actually create a template object for Ion for cross-realm calls. Differential Revision: https://phabricator.services.mozilla.com/D19760 --HG-- extra : moz-landing-system : lando --- js/src/jit/BaselineIC.cpp | 21 +++++++++++---------- js/src/jit/CodeGenerator.cpp | 26 +++++++++++++------------- js/src/jit/IonBuilder.cpp | 10 ++++++++-- js/src/jit/Recover.cpp | 2 +- js/src/jit/VMFunctions.cpp | 3 ++- js/src/vm/Interpreter.cpp | 14 +++++++++++++- js/src/vm/Interpreter.h | 1 + js/src/vm/JSObject-inl.h | 3 ++- js/src/vm/JSObject.cpp | 18 +++++++++++++----- js/src/vm/JSObject.h | 4 ++-- 10 files changed, 66 insertions(+), 36 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 7e2042e0b50d..92514217cfaf 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3565,6 +3565,7 @@ static bool TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, } if (protov.isObject()) { + AutoRealm ar(cx, fun); TaggedProto proto(&protov.toObject()); ObjectGroup* group = ObjectGroup::defaultNewGroup(cx, nullptr, proto, newTarget); @@ -3584,17 +3585,17 @@ static bool TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, } } - if (cx->realm() == fun->realm()) { - JSObject* thisObject = - CreateThisForFunction(cx, fun, newTarget, TenuredObject); - if (!thisObject) { - return false; - } + JSObject* thisObject = + CreateThisForFunction(cx, fun, newTarget, TenuredObject); + if (!thisObject) { + return false; + } - if (thisObject->is() || - thisObject->is()) { - templateObject = thisObject; - } + MOZ_ASSERT(thisObject->nonCCWRealm() == fun->realm()); + + if (thisObject->is() || + thisObject->is()) { + templateObject = thisObject; } } diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 59883fecf147..06d3d1785f2d 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -6796,26 +6796,21 @@ void CodeGenerator::visitCreateThis(LCreateThis* lir) { callVM(CreateThisInfoCodeGen, lir); } -static JSObject* CreateThisForFunctionWithProtoWrapper(JSContext* cx, - HandleObject callee, - HandleObject newTarget, - HandleObject proto) { - return CreateThisForFunctionWithProto(cx, callee, newTarget, proto); -} - -typedef JSObject* (*CreateThisWithProtoFn)(JSContext* cx, HandleObject callee, +typedef JSObject* (*CreateThisWithProtoFn)(JSContext* cx, HandleFunction callee, HandleObject newTarget, - HandleObject proto); + HandleObject proto, + NewObjectKind newKind); static const VMFunction CreateThisWithProtoInfo = - FunctionInfo( - CreateThisForFunctionWithProtoWrapper, - "CreateThisForFunctionWithProtoWrapper"); + FunctionInfo(CreateThisForFunctionWithProto, + "CreateThisForFunctionWithProto"); void CodeGenerator::visitCreateThisWithProto(LCreateThisWithProto* lir) { const LAllocation* callee = lir->getCallee(); const LAllocation* newTarget = lir->getNewTarget(); const LAllocation* proto = lir->getPrototype(); + pushArg(Imm32(GenericObject)); + if (proto->isConstant()) { pushArg(ImmGCPtr(&proto->toConstant()->toObject())); } else { @@ -6837,13 +6832,18 @@ void CodeGenerator::visitCreateThisWithProto(LCreateThisWithProto* lir) { callVM(CreateThisWithProtoInfo, lir); } +typedef JSObject* (*CreateThisWithTemplateFn)(JSContext*, HandleObject); +static const VMFunction CreateThisWithTemplateInfo = + FunctionInfo(CreateThisWithTemplate, + "CreateThisWithTemplate"); + void CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate* lir) { JSObject* templateObject = lir->mir()->templateObject(); Register objReg = ToRegister(lir->output()); Register tempReg = ToRegister(lir->temp()); OutOfLineCode* ool = - oolCallVM(NewInitObjectWithTemplateInfo, lir, + oolCallVM(CreateThisWithTemplateInfo, lir, ArgList(ImmGCPtr(templateObject)), StoreRegisterTo(objReg)); // Allocate. If the FreeList is empty, call to VM, which may GC. diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 55ae1594b120..5653f387482e 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5179,6 +5179,9 @@ MDefinition* IonBuilder::createThisScriptedSingleton(JSFunction* target) { if (templateObject->staticPrototype() != proto) { return nullptr; } + if (templateObject->nonCCWRealm() != target->realm()) { + return nullptr; + } TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group()); @@ -5225,6 +5228,9 @@ MDefinition* IonBuilder::createThisScriptedBaseline(MDefinition* callee) { !templateObject->is()) { return nullptr; } + if (templateObject->nonCCWRealm() != target->realm()) { + return nullptr; + } Shape* shape = target->lookupPure(realm->runtime()->names().prototype); if (!shape || !shape->isDataProperty()) { @@ -5283,8 +5289,8 @@ MDefinition* IonBuilder::createThisScriptedBaseline(MDefinition* callee) { MDefinition* IonBuilder::createThis(JSFunction* target, MDefinition* callee, MDefinition* newTarget) { - // Create |this| for unknown target or cross-realm target. - if (!target || target->realm() != script()->realm()) { + // Create |this| for unknown target. + if (!target) { if (MDefinition* createThis = createThisScriptedBaseline(callee)) { return createThis; } diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index ea7153e5c081..6c58c8aa7419 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -1355,7 +1355,7 @@ bool RCreateThisWithTemplate::recover(JSContext* cx, RootedObject templateObject(cx, &iter.read().toObject()); // See CodeGenerator::visitCreateThisWithTemplate - JSObject* resultObject = NewObjectOperationWithTemplate(cx, templateObject); + JSObject* resultObject = CreateThisWithTemplate(cx, templateObject); if (!resultObject) { return false; } diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index b1a4510dea96..b7a0433b617f 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -557,10 +557,11 @@ bool CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, if (!script) { return false; } - AutoRealm ar(cx, script); if (!js::CreateThis(cx, fun, script, newTarget, GenericObject, rval)) { return false; } + MOZ_ASSERT_IF(rval.isObject(), + fun->realm() == rval.toObject().nonCCWRealm()); } } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 1382de3c9ed0..4428e1d566ae 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -346,7 +346,7 @@ static bool MaybeCreateThisForConstructor(JSContext* cx, JSScript* calleeScript, return true; } - RootedObject callee(cx, &args.callee()); + RootedFunction callee(cx, &args.callee().as()); RootedObject newTarget(cx, &args.newTarget().toObject()); NewObjectKind newKind = createSingleton ? SingletonObject : GenericObject; @@ -5153,6 +5153,7 @@ JSObject* js::NewObjectOperationWithTemplate(JSContext* cx, // object is not a singleton and has had its preliminary objects analyzed, // with the template object a copy of the object to create. MOZ_ASSERT(!templateObject->isSingleton()); + MOZ_ASSERT(cx->realm() == templateObject->nonCCWRealm()); NewObjectKind newKind; bool isUnboxed; @@ -5177,6 +5178,17 @@ JSObject* js::NewObjectOperationWithTemplate(JSContext* cx, return obj; } +JSObject* js::CreateThisWithTemplate(JSContext* cx, + HandleObject templateObject) { + mozilla::Maybe ar; + if (cx->realm() != templateObject->nonCCWRealm()) { + MOZ_ASSERT(cx->compartment() == templateObject->compartment()); + ar.emplace(cx, templateObject); + } + + return NewObjectOperationWithTemplate(cx, templateObject); +} + JSObject* js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32_t length, NewObjectKind newKind /* = GenericObject */) { diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index a5b7606ad214..a34200bf7e93 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -540,6 +540,7 @@ JSObject* NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc, JSObject* NewObjectOperationWithTemplate(JSContext* cx, HandleObject templateObject); +JSObject* CreateThisWithTemplate(JSContext* cx, HandleObject templateObject); JSObject* NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32_t length, diff --git a/js/src/vm/JSObject-inl.h b/js/src/vm/JSObject-inl.h index f83e64f4fe27..8c42d51711f3 100644 --- a/js/src/vm/JSObject-inl.h +++ b/js/src/vm/JSObject-inl.h @@ -623,7 +623,7 @@ inline bool IsConstructor(const Value& v) { return v.isObject() && v.toObject().isConstructor(); } -MOZ_ALWAYS_INLINE bool CreateThis(JSContext* cx, HandleObject callee, +MOZ_ALWAYS_INLINE bool CreateThis(JSContext* cx, HandleFunction callee, JSScript* calleeScript, HandleObject newTarget, NewObjectKind newKind, MutableHandleValue thisv) { @@ -645,6 +645,7 @@ MOZ_ALWAYS_INLINE bool CreateThis(JSContext* cx, HandleObject callee, return false; } + MOZ_ASSERT(obj->nonCCWRealm() == callee->realm()); thisv.setObject(*obj); return true; } diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp index ece680001f21..846fd42325ce 100644 --- a/js/src/vm/JSObject.cpp +++ b/js/src/vm/JSObject.cpp @@ -12,6 +12,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/MathAlgorithms.h" +#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TemplateLib.h" @@ -1109,10 +1110,17 @@ static inline JSObject* CreateThisForFunctionWithGroup(JSContext* cx, } JSObject* js::CreateThisForFunctionWithProto( - JSContext* cx, HandleObject callee, HandleObject newTarget, + JSContext* cx, HandleFunction callee, HandleObject newTarget, HandleObject proto, NewObjectKind newKind /* = GenericObject */) { RootedObject res(cx); + // Ion may call this with a cross-realm callee. + mozilla::Maybe ar; + if (cx->realm() != callee->realm()) { + MOZ_ASSERT(cx->compartment() == callee->compartment()); + ar.emplace(cx, callee); + } + if (proto) { RootedObjectGroup group( cx, ObjectGroup::defaultNewGroup(cx, nullptr, TaggedProto(proto), @@ -1145,8 +1153,8 @@ JSObject* js::CreateThisForFunctionWithProto( } if (res) { - JSScript* script = - JSFunction::getOrCreateScript(cx, callee.as()); + MOZ_ASSERT(res->nonCCWRealm() == callee->realm()); + JSScript* script = JSFunction::getOrCreateScript(cx, callee); if (!script) { return nullptr; } @@ -1199,7 +1207,7 @@ bool js::GetPrototypeFromConstructor(JSContext* cx, HandleObject newTarget, return true; } -JSObject* js::CreateThisForFunction(JSContext* cx, HandleObject callee, +JSObject* js::CreateThisForFunction(JSContext* cx, HandleFunction callee, HandleObject newTarget, NewObjectKind newKind) { RootedObject proto(cx); @@ -1216,7 +1224,7 @@ JSObject* js::CreateThisForFunction(JSContext* cx, HandleObject callee, /* Reshape the singleton before passing it as the 'this' value. */ NativeObject::clear(cx, nobj); - JSScript* calleeScript = callee->as().nonLazyScript(); + JSScript* calleeScript = callee->nonLazyScript(); TypeScript::SetThis(cx, calleeScript, TypeSet::ObjectType(nobj)); return nobj; diff --git a/js/src/vm/JSObject.h b/js/src/vm/JSObject.h index 227d853ad910..3826d959b1fb 100644 --- a/js/src/vm/JSObject.h +++ b/js/src/vm/JSObject.h @@ -870,11 +870,11 @@ MOZ_ALWAYS_INLINE bool GetPrototypeFromBuiltinConstructor( // Specialized call for constructing |this| with a known function callee, // and a known prototype. extern JSObject* CreateThisForFunctionWithProto( - JSContext* cx, js::HandleObject callee, HandleObject newTarget, + JSContext* cx, js::HandleFunction callee, HandleObject newTarget, HandleObject proto, NewObjectKind newKind = GenericObject); // Specialized call for constructing |this| with a known function callee. -extern JSObject* CreateThisForFunction(JSContext* cx, js::HandleObject callee, +extern JSObject* CreateThisForFunction(JSContext* cx, js::HandleFunction callee, js::HandleObject newTarget, NewObjectKind newKind); From ce727c14e7c2d02df06d85a6943c71cbeed5f626 Mon Sep 17 00:00:00 2001 From: Thomas Daede Date: Thu, 14 Feb 2019 17:11:57 +0000 Subject: [PATCH 42/84] Bug 1511224 - Add win64-nasm toolchain. r=ted,jya,glandium Differential Revision: https://phabricator.services.mozilla.com/D13875 --HG-- extra : moz-landing-system : lando --- build/mozconfig.common | 1 + build/mozconfig.nasm | 11 +++++++++ media/ffvpx/config_win64.asm | 2 +- taskcluster/ci/build/windows.yml | 33 ++++++++++++++++++++++++++ taskcluster/ci/fetch/toolchains.yml | 8 +++++++ taskcluster/ci/toolchain/clang.yml | 2 +- taskcluster/ci/toolchain/kind.yml | 1 + taskcluster/ci/toolchain/nasm.yml | 18 ++++++++++++++ taskcluster/scripts/misc/build-nasm.sh | 25 +++++++++++++++++++ 9 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 build/mozconfig.nasm create mode 100644 taskcluster/ci/toolchain/nasm.yml create mode 100755 taskcluster/scripts/misc/build-nasm.sh diff --git a/build/mozconfig.common b/build/mozconfig.common index 308795ff549c..2951948a18dd 100644 --- a/build/mozconfig.common +++ b/build/mozconfig.common @@ -19,6 +19,7 @@ MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0} ac_add_options --enable-js-shell +. "$topsrcdir/build/mozconfig.nasm" . "$topsrcdir/build/mozconfig.node" . "$topsrcdir/build/mozconfig.automation" . "$topsrcdir/build/mozconfig.rust" diff --git a/build/mozconfig.nasm b/build/mozconfig.nasm new file mode 100644 index 000000000000..9db9ba2b0303 --- /dev/null +++ b/build/mozconfig.nasm @@ -0,0 +1,11 @@ +# 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/. + +case "$(uname -s)" in +MINGW*) + export NASM=$topsrcdir/nasm/nasm.exe + ;; +*) + ;; +esac diff --git a/media/ffvpx/config_win64.asm b/media/ffvpx/config_win64.asm index fecfee4988a5..64e1c6dfb62d 100644 --- a/media/ffvpx/config_win64.asm +++ b/media/ffvpx/config_win64.asm @@ -54,7 +54,7 @@ %define HAVE_SSE42 1 %define HAVE_SSSE3 1 %define HAVE_XOP 1 -%define HAVE_CPUNOP 1 +%define HAVE_CPUNOP 0 %define HAVE_I686 1 %define HAVE_MIPSFPU 0 %define HAVE_MIPS32R2 0 diff --git a/taskcluster/ci/build/windows.yml b/taskcluster/ci/build/windows.yml index 89aba43c7cd6..9063ccd89bfb 100755 --- a/taskcluster/ci/build/windows.yml +++ b/taskcluster/ci/build/windows.yml @@ -34,6 +34,7 @@ win32/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32/opt: @@ -67,6 +68,7 @@ win32/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32/pgo: @@ -100,6 +102,7 @@ win32/pgo: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64/debug: @@ -133,6 +136,7 @@ win64/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-fuzzing/debug: @@ -168,6 +172,7 @@ win64-fuzzing/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-plain/debug: @@ -201,6 +206,7 @@ win64-plain/debug: - win64-clang-cl - win64-rust - win64-node + - win64-nasm - win64-cbindgen win64/opt: @@ -234,6 +240,7 @@ win64/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-plain/opt: @@ -267,6 +274,7 @@ win64-plain/opt: toolchains: - win64-clang-cl - win64-rust + - win64-nasm - win64-node - win64-cbindgen @@ -314,6 +322,7 @@ win32-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-nightly/opt: @@ -353,6 +362,7 @@ win64-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64/pgo: @@ -386,6 +396,7 @@ win64/pgo: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-add-on-devel/opt: @@ -419,6 +430,7 @@ win32-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-add-on-devel/opt: @@ -452,6 +464,7 @@ win64-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-noopt/debug: @@ -484,6 +497,7 @@ win64-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-noopt/debug: @@ -516,6 +530,7 @@ win32-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-rusttests/opt: @@ -553,6 +568,7 @@ win32-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-rusttests/debug: @@ -590,6 +606,7 @@ win32-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-rusttests/opt: @@ -622,6 +639,7 @@ win64-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-rusttests/debug: @@ -654,6 +672,7 @@ win64-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-ccov/debug: @@ -690,6 +709,7 @@ win64-ccov/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node fetches: toolchain: @@ -726,6 +746,7 @@ win64-asan/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan/opt: @@ -760,6 +781,7 @@ win64-asan/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan-reporter-nightly/opt: @@ -802,6 +824,7 @@ win64-asan-reporter-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan-fuzzing/opt: @@ -835,6 +858,7 @@ win64-asan-fuzzing/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-devedition-nightly/opt: @@ -882,6 +906,7 @@ win32-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-devedition-nightly/opt: @@ -922,6 +947,7 @@ win64-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-msvc/debug: @@ -953,6 +979,7 @@ win32-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-msvc/opt: @@ -985,6 +1012,7 @@ win32-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-msvc/debug: @@ -1016,6 +1044,7 @@ win64-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-msvc/opt: @@ -1048,6 +1077,7 @@ win64-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64/debug: @@ -1083,6 +1113,7 @@ win64-aarch64/debug: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64/opt: @@ -1118,6 +1149,7 @@ win64-aarch64/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64-nightly/opt: @@ -1157,6 +1189,7 @@ win64-aarch64-nightly/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-mingwclang/opt: diff --git a/taskcluster/ci/fetch/toolchains.yml b/taskcluster/ci/fetch/toolchains.yml index c67fa0de1c63..505d3167aa9a 100644 --- a/taskcluster/ci/fetch/toolchains.yml +++ b/taskcluster/ci/fetch/toolchains.yml @@ -173,6 +173,14 @@ mpfr-3.1.5: sig-url: "{url}.asc" key-path: build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key +nasm-2.14.02: + description: nasm 2.14.02 source code + fetch: + type: static-url + url: https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.xz + sha256: e24ade3e928f7253aa8c14aa44726d1edf3f98643f87c9d72ec1df44b26be8f5 + size: 827620 + wix-3.1.1: description: wix 3.1.1 binary release # WIX doesn't use a wrapping toplevel DIR, so we should really repackage it when diff --git a/taskcluster/ci/toolchain/clang.yml b/taskcluster/ci/toolchain/clang.yml index af6ef32554a8..a68385e362de 100644 --- a/taskcluster/ci/toolchain/clang.yml +++ b/taskcluster/ci/toolchain/clang.yml @@ -60,7 +60,7 @@ linux64-clang-trunk-mingw-x64: description: "MinGW-Clang Trunk x64 toolchain build" treeherder: symbol: TMW(clang-x64) - tier: 2 + tier: 1 run: script: build-clang-trunk-mingw.sh arguments: [ diff --git a/taskcluster/ci/toolchain/kind.yml b/taskcluster/ci/toolchain/kind.yml index 2e7ce5b92da5..57af10e234c1 100644 --- a/taskcluster/ci/toolchain/kind.yml +++ b/taskcluster/ci/toolchain/kind.yml @@ -35,6 +35,7 @@ jobs-from: - mingw.yml - minidump_stackwalk.yml - misc.yml + - nasm.yml - node.yml - rust.yml - rust-size.yml diff --git a/taskcluster/ci/toolchain/nasm.yml b/taskcluster/ci/toolchain/nasm.yml new file mode 100644 index 000000000000..5313ac6a5196 --- /dev/null +++ b/taskcluster/ci/toolchain/nasm.yml @@ -0,0 +1,18 @@ +win64-nasm: + description: "nasm win64 build" + treeherder: + symbol: TW64(nasm) + worker-type: aws-provisioner-v1/gecko-{level}-b-linux + worker: + docker-image: {in-tree: mingw32-build} + max-run-time: 1800 + run: + script: build-nasm.sh + resources: + - 'taskcluster/scripts/misc/tooltool-download.sh' + toolchain-artifact: public/build/nasm.tar.bz2 + toolchains: + - linux64-clang-trunk-mingw-x64 + fetches: + fetch: + - nasm-2.14.02 diff --git a/taskcluster/scripts/misc/build-nasm.sh b/taskcluster/scripts/misc/build-nasm.sh new file mode 100755 index 000000000000..c7673ea20cbb --- /dev/null +++ b/taskcluster/scripts/misc/build-nasm.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -x -e -v + +case "$(uname -s)" in + Linux) + WORKSPACE=$HOME/workspace + UPLOAD_DIR=$HOME/artifacts + COMPRESS_EXT=bz2 + ;; +esac + +cd $WORKSPACE/build/src + +. taskcluster/scripts/misc/tooltool-download.sh +export PATH="$WORKSPACE/build/src/clang/bin:$PATH" + +cd $WORKSPACE/build/nasm-2.14.02 +./configure CC=x86_64-w64-mingw32-clang AR=llvm-ar RANLIB=llvm-ranlib --host=x86_64-w64-mingw32 +make -j$(nproc) + +mkdir nasm +mv nasm.exe nasm/ +tar -acf nasm.tar.$COMPRESS_EXT nasm +mkdir -p "$UPLOAD_DIR" +cp nasm.tar.$COMPRESS_EXT "$UPLOAD_DIR" From c732fccb1e12c905f4f015e29f2bbf0f027a478e Mon Sep 17 00:00:00 2001 From: Bogdan Tara Date: Thu, 14 Feb 2019 19:20:58 +0200 Subject: [PATCH 43/84] Backed out 8 changesets (bug 1522637) for browser_all_files_referenced.js failures CLOSED TREE Backed out changeset f7ab0e6e739b (bug 1522637) Backed out changeset 3d24e8e81c02 (bug 1522637) Backed out changeset 41ca0b87537e (bug 1522637) Backed out changeset 6e0d4b6b1c93 (bug 1522637) Backed out changeset 8f494271ec06 (bug 1522637) Backed out changeset 6b4d010964ec (bug 1522637) Backed out changeset 5eeda2ba8e79 (bug 1522637) Backed out changeset 5988b8e7d17c (bug 1522637) --- browser/app/profile/firefox.js | 3 - ...rowser_new_web_tab_in_file_process_pref.js | 1 - .../sessionstore/ContentRestore.jsm | 3 +- .../components/sessionstore/SessionStore.jsm | 100 +++++------------- browser/components/sessionstore/TabState.jsm | 4 - docshell/base/nsDocShell.cpp | 38 ++----- docshell/base/nsIWebNavigation.idl | 6 +- docshell/shistory/nsISHistory.idl | 8 -- docshell/shistory/nsSHistory.cpp | 6 -- dom/ipc/WindowGlobalChild.h | 1 - ipc/glue/BackgroundUtils.cpp | 4 +- netwerk/base/LoadInfo.cpp | 20 +--- netwerk/base/LoadInfo.h | 3 +- netwerk/base/nsILoadInfo.idl | 7 -- netwerk/ipc/NeckoChannelParams.ipdlh | 1 - netwerk/protocol/http/nsHttpChannel.cpp | 38 +++---- netwerk/protocol/http/nsHttpHandler.h | 4 - .../protocol/http/nsIHttpProtocolHandler.idl | 8 -- .../browser/browser_cross_process_redirect.js | 12 ++- toolkit/components/browser/nsWebBrowser.cpp | 5 +- .../tests/browser/browser.ini | 2 - .../browser_httpResponseProcessSelection.js | 16 +++ .../browser/browser_httpToFileHistory.js | 99 ----------------- .../remotebrowserutils/tests/browser/head.js | 15 --- toolkit/modules/E10SUtils.jsm | 28 ++--- .../modules/sessionstore/SessionHistory.jsm | 7 +- 26 files changed, 99 insertions(+), 340 deletions(-) delete mode 100644 toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js delete mode 100644 toolkit/components/remotebrowserutils/tests/browser/head.js diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 3f09bb66e776..a07a61ca2257 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -483,9 +483,6 @@ pref("browser.tabs.newanimations", false); pref("browser.tabs.remote.separatePrivilegedContentProcess", true); #endif -// Turn on HTTP response process selection. -pref("browser.tabs.remote.useHTTPResponseProcessSelection", true); - pref("browser.ctrlTab.recentlyUsedOrder", true); // By default, do not export HTML at shutdown. diff --git a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js index 31948fe20feb..fa3166099640 100644 --- a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js +++ b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js @@ -24,7 +24,6 @@ add_task(async function() { await SpecialPowers.pushPrefEnv( {set: [["browser.tabs.remote.separateFileUriProcess", true], ["browser.tabs.remote.allowLinkedWebInFileUriProcess", true], - ["browser.tabs.remote.useHTTPResponseProcessSelection", false], ["dom.ipc.processCount.file", 2]]}); // Open file:// page. diff --git a/browser/components/sessionstore/ContentRestore.jsm b/browser/components/sessionstore/ContentRestore.jsm index ce339b25a306..b9d2b8449758 100644 --- a/browser/components/sessionstore/ContentRestore.jsm +++ b/browser/components/sessionstore/ContentRestore.jsm @@ -186,8 +186,7 @@ ContentRestoreInternal.prototype = { // If the load was started in another process, and the in-flight channel // was redirected into this process, resume that load within our process. if (loadArguments.redirectLoadSwitchId) { - webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId, - loadArguments.redirectHistoryIndex); + webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId); return true; } diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index c0370612cfc9..a3d092977e0a 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -48,7 +48,9 @@ const OBSERVING = [ "quit-application", "browser:purge-session-history", "browser:purge-session-history-for-domain", "idle-daily", "clear-origin-attributes-data", - "http-on-may-change-process", + "http-on-examine-response", + "http-on-examine-merged-response", + "http-on-examine-cached-response", ]; // XUL Window properties to (re)store @@ -812,8 +814,10 @@ var SessionStoreInternal = { this._forgetTabsWithUserContextId(userContextId); } break; - case "http-on-may-change-process": - this.onMayChangeProcess(aSubject); + case "http-on-examine-response": + case "http-on-examine-cached-response": + case "http-on-examine-merged-response": + this.onExamineResponse(aSubject); break; } }, @@ -2282,8 +2286,6 @@ var SessionStoreInternal = { * processes. */ async _doProcessSwitch(aBrowser, aRemoteType, aChannel, aSwitchId) { - debug(`[process-switch]: performing switch from ${aBrowser.remoteType} to ${aRemoteType}`); - // Don't try to switch tabs before delayed startup is completed. await aBrowser.ownerGlobal.delayedStartupPromise; @@ -2307,14 +2309,12 @@ var SessionStoreInternal = { } // Tell our caller to redirect the load into this newly created process. - let tabParent = aBrowser.frameLoader.tabParent; - debug(`[process-switch]: new tabID: ${tabParent.tabId}`); - return tabParent; + return aBrowser.frameLoader.tabParent; }, // Examine the channel response to see if we should change the process // performing the given load. - onMayChangeProcess(aChannel) { + onExamineResponse(aChannel) { if (!E10SUtils.useHttpResponseProcessSelection()) { return; } @@ -2323,21 +2323,13 @@ var SessionStoreInternal = { return; // Not a document load. } - // Check that this is a toplevel document load. - let cpType = aChannel.loadInfo.externalContentPolicyType; - let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT; - if (!toplevel) { - debug(`[process-switch]: non-toplevel - ignoring`); - return; + let browsingContext = aChannel.loadInfo.browsingContext; + if (!browsingContext) { + return; // Not loading in a browsing context. } - // Check that the document has a corresponding BrowsingContext. - let browsingContext = toplevel - ? aChannel.loadInfo.browsingContext - : aChannel.loadInfo.frameBrowsingContext; - if (!browsingContext) { - debug(`[process-switch]: no BrowsingContext - ignoring`); - return; + if (browsingContext.parent) { + return; // Not a toplevel load, can't flip procs. } // Get principal for a document already loaded in the BrowsingContext. @@ -2346,60 +2338,34 @@ var SessionStoreInternal = { currentPrincipal = browsingContext.currentWindowGlobal.documentPrincipal; } - // Ensure we have an nsIParentChannel listener for a remote load. - let parentChannel; - try { - parentChannel = aChannel.notificationCallbacks - .getInterface(Ci.nsIParentChannel); - } catch (e) { - debug(`[process-switch]: No nsIParentChannel callback - ignoring`); - return; + let parentChannel = aChannel.notificationCallbacks + .getInterface(Ci.nsIParentChannel); + if (!parentChannel) { + return; // Not an actor channel } - // Ensure we have a nsITabParent for our remote load. - let tabParent; - try { - tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsITabParent); - } catch (e) { - debug(`[process-switch]: No nsITabParent for channel - ignoring`); - return; + let tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsITabParent); + if (!tabParent || !tabParent.ownerElement) { + console.warn("warning: Missing tabParent"); + return; // Not an embedded browsing context } - // Ensure we're loaded in a regular tabbrowser environment, and can swap processes. let browser = tabParent.ownerElement; - if (!browser) { - debug(`[process-switch]: TabParent has no ownerElement - ignoring`); + if (browser.tagName !== "browser") { + console.warn("warning: Not a xul:browser element:", browser.tagName); + return; // Not a vanilla xul:browser element performing embedding. } - let tabbrowser = browser.ownerGlobal.gBrowser; - if (!tabbrowser) { - debug(`[process-switch]: cannot find tabbrowser for loading tab - ignoring`); - return; - } - - let tab = tabbrowser.getTabForBrowser(browser); - if (!tab) { - debug(`[process-switch]: not a normal tab, so cannot swap processes - ignoring`); - return; - } - - // Determine the process type the load should be performed in. let resultPrincipal = Services.scriptSecurityManager.getChannelResultPrincipal(aChannel); + let useRemoteTabs = browser.ownerGlobal.gMultiProcessBrowser; let remoteType = E10SUtils.getRemoteTypeForPrincipal(resultPrincipal, - true, + useRemoteTabs, browser.remoteType, currentPrincipal); if (browser.remoteType == remoteType) { - debug(`[process-switch]: type (${remoteType}) is compatible - ignoring`); - return; - } - - if (remoteType == E10SUtils.NOT_REMOTE || - browser.remoteType == E10SUtils.NOT_REMOTE) { - debug(`[process-switch]: non-remote source/target - ignoring`); - return; + return; // Already in compatible process. } // ------------------------------------------------------------------------ @@ -3265,14 +3231,6 @@ var SessionStoreInternal = { tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length)); } else { options.loadArguments = loadArguments; - - // If we're resuming a load which has been redirected from another - // process, record the history index which is currently being requested. - // It has to be offset by 1 to get back to native history indices from - // SessionStore history indicies. - if (loadArguments.redirectLoadSwitchId) { - loadArguments.redirectHistoryIndex = tabState.requestedIndex - 1; - } } // Need to reset restoring tabs. diff --git a/browser/components/sessionstore/TabState.jsm b/browser/components/sessionstore/TabState.jsm index 054bf7a68f9c..442e51362cd4 100644 --- a/browser/components/sessionstore/TabState.jsm +++ b/browser/components/sessionstore/TabState.jsm @@ -184,10 +184,6 @@ var TabStateInternal = { if (value.hasOwnProperty("index")) { tabData.index = value.index; } - - if (value.hasOwnProperty("requestedIndex")) { - tabData.requestedIndex = value.requestedIndex; - } } else { tabData[key] = value; } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ff67dd438ab3..600955aa18be 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -12993,39 +12993,21 @@ nsDocShell::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { +nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier) { RefPtr self = this; RefPtr cpcl = ChildProcessChannelListener::GetSingleton(); // Call into InternalLoad with the pending channel when it is received. - cpcl->RegisterCallback( - aIdentifier, [self, aHistoryIndex](nsIChildChannel* aChannel) { - RefPtr loadState; - nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( - aChannel, getter_AddRefs(loadState)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - // If we're performing a history load, locate the correct history entry, - // and set the relevant bits on our loadState. - if (aHistoryIndex >= 0) { - nsCOMPtr legacySHistory = - self->mSessionHistory->LegacySHistory(); - - nsCOMPtr entry; - rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, - getter_AddRefs(entry)); - if (NS_SUCCEEDED(rv)) { - legacySHistory->InternalSetRequestedIndex(aHistoryIndex); - loadState->SetLoadType(LOAD_HISTORY); - loadState->SetSHEntry(entry); - } - } - - self->InternalLoad(loadState, nullptr, nullptr); - }); + cpcl->RegisterCallback(aIdentifier, [self](nsIChildChannel* aChannel) { + RefPtr loadState; + nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( + aChannel, getter_AddRefs(loadState)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + self->InternalLoad(loadState, nullptr, nullptr); + }); return NS_OK; } diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl index cabae3f31d0f..e7e38809de7b 100644 --- a/docshell/base/nsIWebNavigation.idl +++ b/docshell/base/nsIWebNavigation.idl @@ -342,10 +342,6 @@ interface nsIWebNavigation : nsISupports /** * Resume a load which has been redirected from another process. - * - * A negative |aHistoryIndex| value corresponds to a non-history load being - * resumed. */ - void resumeRedirectedLoad(in unsigned long long aLoadIdentifier, - in long aHistoryIndex); + void resumeRedirectedLoad(in unsigned long long aLoadIdentifier); }; diff --git a/docshell/shistory/nsISHistory.idl b/docshell/shistory/nsISHistory.idl index 429947d77124..73747d978986 100644 --- a/docshell/shistory/nsISHistory.idl +++ b/docshell/shistory/nsISHistory.idl @@ -52,14 +52,6 @@ interface nsISHistory: nsISupports */ [infallible] readonly attribute long requestedIndex; - /** - * Artifically set the |requestedIndex| for this nsISHEntry to the given - * index. This is used when resuming a cross-process load from a different - * process. - */ - [noscript, notxpcom] - void internalSetRequestedIndex(in long aRequestedIndex); - /** * Get the history entry at a given index. Returns non-null on success. * diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index 2ebe5eab1e3d..e5ab98e0a839 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -626,12 +626,6 @@ nsSHistory::GetRequestedIndex(int32_t* aResult) { return NS_OK; } -NS_IMETHODIMP_(void) -nsSHistory::InternalSetRequestedIndex(int32_t aRequestedIndex) { - MOZ_ASSERT(aRequestedIndex >= -1 && aRequestedIndex < Length()); - mRequestedIndex = aRequestedIndex; -} - NS_IMETHODIMP nsSHistory::GetEntryAtIndex(int32_t aIndex, nsISHEntry** aResult) { NS_ENSURE_ARG_POINTER(aResult); diff --git a/dom/ipc/WindowGlobalChild.h b/dom/ipc/WindowGlobalChild.h index 5f1fe5b953ce..2910e75b8fd3 100644 --- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -20,7 +20,6 @@ namespace dom { class BrowsingContext; class WindowGlobalParent; class JSWindowActorChild; -class TabChild; /** * Actor for a single nsGlobalWindowInner. This actor is used to communicate diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 85250564d2c2..9c7ed8a07ae9 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -477,7 +477,6 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetTopOuterWindowID(), aLoadInfo->GetFrameOuterWindowID(), aLoadInfo->GetBrowsingContextID(), - aLoadInfo->GetFrameBrowsingContextID(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetIsDocshellReload(), aLoadInfo->GetSendCSPViolationEvents(), aLoadInfo->GetOriginAttributes(), @@ -635,8 +634,7 @@ nsresult LoadInfoArgsToLoadInfo( loadInfoArgs.forceInheritPrincipalDropped(), loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), loadInfoArgs.parentOuterWindowID(), loadInfoArgs.topOuterWindowID(), loadInfoArgs.frameOuterWindowID(), - loadInfoArgs.browsingContextID(), loadInfoArgs.frameBrowsingContextID(), - loadInfoArgs.initialSecurityCheckDone(), + loadInfoArgs.browsingContextID(), loadInfoArgs.initialSecurityCheckDone(), loadInfoArgs.isInThirdPartyContext(), loadInfoArgs.isDocshellReload(), loadInfoArgs.sendCSPViolationEvents(), loadInfoArgs.originAttributes(), redirectChainIncludingInternalRedirects, redirectChain, diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 0e381e396378..a35b8ce525b7 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -80,7 +80,6 @@ LoadInfo::LoadInfo( mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), - mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), mIsDocshellReload(false), @@ -231,9 +230,6 @@ LoadInfo::LoadInfo( nsCOMPtr outerWindow = do_GetInterface(docShell); if (outerWindow) { mFrameOuterWindowID = outerWindow->WindowID(); - - RefPtr bc = outerWindow->GetBrowsingContext(); - mFrameBrowsingContextID = bc ? bc->Id() : 0; } } } @@ -366,7 +362,6 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), - mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), // NB: TYPE_DOCUMENT implies !third-party. mIsDocshellReload(false), @@ -505,7 +500,7 @@ LoadInfo::LoadInfo( bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, + uint64_t aBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyContext, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -548,7 +543,6 @@ LoadInfo::LoadInfo( mTopOuterWindowID(aTopOuterWindowID), mFrameOuterWindowID(aFrameOuterWindowID), mBrowsingContextID(aBrowsingContextID), - mFrameBrowsingContextID(aFrameBrowsingContextID), mInitialSecurityCheckDone(aInitialSecurityCheckDone), mIsThirdPartyContext(aIsThirdPartyContext), mIsDocshellReload(aIsDocshellReload), @@ -999,24 +993,12 @@ LoadInfo::GetBrowsingContextID(uint64_t* aResult) { return NS_OK; } -NS_IMETHODIMP -LoadInfo::GetFrameBrowsingContextID(uint64_t* aResult) { - *aResult = mFrameBrowsingContextID; - return NS_OK; -} - NS_IMETHODIMP LoadInfo::GetBrowsingContext(dom::BrowsingContext** aResult) { *aResult = BrowsingContext::Get(mBrowsingContextID).take(); return NS_OK; } -NS_IMETHODIMP -LoadInfo::GetFrameBrowsingContext(dom::BrowsingContext** aResult) { - *aResult = BrowsingContext::Get(mFrameBrowsingContextID).take(); - return NS_OK; -} - NS_IMETHODIMP LoadInfo::GetScriptableOriginAttributes( JSContext* aCx, JS::MutableHandle aOriginAttributes) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 15c016d5f850..851602553ebe 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -111,7 +111,7 @@ class LoadInfo final : public nsILoadInfo { bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, + uint64_t aBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyRequest, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -184,7 +184,6 @@ class LoadInfo final : public nsILoadInfo { uint64_t mTopOuterWindowID; uint64_t mFrameOuterWindowID; uint64_t mBrowsingContextID; - uint64_t mFrameBrowsingContextID; bool mInitialSecurityCheckDone; bool mIsThirdPartyContext; bool mIsDocshellReload; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 9c98c654fd60..6a8ba66c1a47 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -634,13 +634,6 @@ interface nsILoadInfo : nsISupports [infallible] readonly attribute unsigned long long browsingContextID; readonly attribute BrowsingContext browsingContext; - /** - * Like `frameOuterWindowID`, however returning the BrowsingContextID - * instead. - */ - [infallible] readonly attribute unsigned long long frameBrowsingContextID; - readonly attribute BrowsingContext frameBrowsingContext; - /** * Resets the PrincipalToInherit to a freshly created NullPrincipal * which inherits the origin attributes from the loadInfo. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 08a92c60b5e7..267f9ea22aaa 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -64,7 +64,6 @@ struct LoadInfoArgs uint64_t topOuterWindowID; uint64_t frameOuterWindowID; uint64_t browsingContextID; - uint64_t frameBrowsingContextID; bool initialSecurityCheckDone; bool isInThirdPartyContext; bool isDocshellReload; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 5fb40d79a1f0..e48e97e624a8 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -2450,20 +2450,15 @@ nsresult nsHttpChannel::ContinueProcessResponse1() { } rv = NS_OK; - if (!mCanceled) { - // notify "http-on-may-change-process" observers - gHttpHandler->OnMayChangeProcess(this); + if (mRedirectTabPromise && !mCanceled) { + MOZ_ASSERT(!mOnStartRequestCalled); - if (mRedirectTabPromise) { - MOZ_ASSERT(!mOnStartRequestCalled); - - PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; - } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); + PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); } // No process switch needed, continue as normal. @@ -7126,8 +7121,6 @@ NS_IMETHODIMP nsHttpChannel::SwitchProcessTo(dom::Promise *aTabPromise, nsresult nsHttpChannel::StartCrossProcessRedirect() { nsresult rv; - LOG(("nsHttpChannel::StartCrossProcessRedirect [this=%p]", this)); - rv = CheckRedirectLimit(nsIChannelEventSink::REDIRECT_INTERNAL); NS_ENSURE_SUCCESS(rv, rv); @@ -7264,18 +7257,13 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { // before we check for redirects, check if the load should be shifted into a // new process. rv = NS_OK; - if (!mCanceled) { - // notify "http-on-may-change-process" observers - gHttpHandler->OnMayChangeProcess(this); - - if (mRedirectTabPromise) { - PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; - } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); + if (mRedirectTabPromise && !mCanceled) { + PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); } // No process change is needed, so continue on to ContinueOnStartRequest1. diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index 1e7dd003bac3..d2eb2e08a90e 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -368,10 +368,6 @@ class nsHttpHandler final : public nsIHttpProtocolHandler, NotifyObservers(chan, NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC); } - void OnMayChangeProcess(nsIHttpChannel *chan) { - NotifyObservers(chan, NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC); - } - // Generates the host:port string for use in the Host: header as well as the // CONNECT line for proxies. This handles IPv6 literals correctly. static MOZ_MUST_USE nsresult GenerateHostPort(const nsCString &host, diff --git a/netwerk/protocol/http/nsIHttpProtocolHandler.idl b/netwerk/protocol/http/nsIHttpProtocolHandler.idl index 6abe8e8276bb..6132608011ae 100644 --- a/netwerk/protocol/http/nsIHttpProtocolHandler.idl +++ b/netwerk/protocol/http/nsIHttpProtocolHandler.idl @@ -123,14 +123,6 @@ interface nsIHttpProtocolHandler : nsIProxiedProtocolHandler */ #define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response" -/** - * The observer of this topic is notified before before the response for a HTTP - * load is available. The "subject" of the notification is the nsIHttpChannel - * instance. Observers may call "switchProcessTo" to perform a process switch - * while this is being run. - */ -#define NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC "http-on-may-change-process" - /** * Before an HTTP request corresponding to a channel with the LOAD_DOCUMENT_URI * flag is sent to the server, this observer topic is notified. The observer of diff --git a/netwerk/test/browser/browser_cross_process_redirect.js b/netwerk/test/browser/browser_cross_process_redirect.js index 602d78f0f904..28985bdd90c6 100644 --- a/netwerk/test/browser/browser_cross_process_redirect.js +++ b/netwerk/test/browser/browser_cross_process_redirect.js @@ -23,7 +23,9 @@ function ProcessChooser(tabParent, from, to, rejectPromise = false) { this.rejectPromise = rejectPromise; this.registered = true; - Services.obs.addObserver(this, "http-on-may-change-process"); + Services.obs.addObserver(this, "http-on-examine-response"); + Services.obs.addObserver(this, "http-on-examine-merged-response"); + Services.obs.addObserver(this, "http-on-examine-cached-response"); } ProcessChooser.prototype = { @@ -32,7 +34,9 @@ ProcessChooser.prototype = { return; } this.registered = false; - Services.obs.removeObserver(this, "http-on-may-change-process"); + Services.obs.removeObserver(this, "http-on-examine-response"); + Services.obs.removeObserver(this, "http-on-examine-merged-response"); + Services.obs.removeObserver(this, "http-on-examine-cached-response"); }, examine(aChannel) { @@ -79,7 +83,9 @@ ProcessChooser.prototype = { observe(aSubject, aTopic, aData) { switch (aTopic) { - case "http-on-may-change-process": + case "http-on-examine-response": + case "http-on-examine-cached-response": + case "http-on-examine-merged-response": this.examine(aSubject.QueryInterface(Ci.nsIHttpChannel)); break; default: diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp index 7a8bbe3330a4..98fa6c90daf7 100644 --- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -579,9 +579,8 @@ nsWebBrowser::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier, - int32_t aHistoryIndex) { - return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier, aHistoryIndex); +nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier) { + return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier); } NS_IMETHODIMP diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser.ini b/toolkit/components/remotebrowserutils/tests/browser/browser.ini index 06834883e246..b55376c4d462 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser.ini +++ b/toolkit/components/remotebrowserutils/tests/browser/browser.ini @@ -4,8 +4,6 @@ support-files = dummy_page.html print_postdata.sjs 307redirect.sjs - head.js [browser_RemoteWebNavigation.js] [browser_httpResponseProcessSelection.js] -[browser_httpToFileHistory.js] diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js index 1f0f0031093c..859555b9764a 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js +++ b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js @@ -2,6 +2,22 @@ const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); let PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; +function fileURL(filename) { + let ifile = getChromeDir(getResolvedURI(gTestPath)); + ifile.append(filename); + return Services.io.newFileURI(ifile).spec; +} + +function httpURL(filename, host = "https://example.com/") { + let root = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", host); + return root + filename; +} + +function add307(url, host = "https://example.com/") { + return httpURL("307redirect.sjs?" + url, host); +} + async function performLoad(browser, opts, action) { let loadedPromise = BrowserTestUtils.browserLoaded( browser, false, opts.url, opts.maybeErrorPage); diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js deleted file mode 100644 index 495a6979d4cc..000000000000 --- a/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js +++ /dev/null @@ -1,99 +0,0 @@ -const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); - -const PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; -const HISTORY = [ - {url: httpURL("dummy_page.html")}, - {url: fileURL("dummy_page.html")}, - {url: httpURL("dummy_page.html")}, -]; - -function reversed(list) { - let copy = list.slice(); - copy.reverse(); - return copy; -} - -function butLast(list) { - let copy = list.slice(); - copy.pop(); - return copy; -} - -async function runTest() { - await BrowserTestUtils.withNewTab({gBrowser}, async function(aBrowser) { - // Perform initial load of each URL in the history. - let count = 0; - let index = -1; - for (let {url} of HISTORY) { - BrowserTestUtils.loadURI(aBrowser, url); - await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { - return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; - }); - - count++; - index++; - await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { - docShell.QueryInterface(Ci.nsIWebNavigation); - - is(docShell.sessionHistory.count, count, "Initial Navigation Count Match"); - is(docShell.sessionHistory.index, index, "Initial Navigation Index Match"); - - let real = Services.io.newURI(content.location.href); - let expect = Services.io.newURI(url); - is(real.scheme, expect.scheme, "Initial Navigation URL Scheme"); - }); - } - - // Go back to the first entry. - for (let {url} of reversed(HISTORY).slice(1)) { - ContentTask.spawn(aBrowser, {}, () => { content.history.back(); }); - await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { - return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; - }); - - index--; - await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { - docShell.QueryInterface(Ci.nsIWebNavigation); - - is(docShell.sessionHistory.count, count, "Go Back Count Match"); - is(docShell.sessionHistory.index, index, "Go Back Index Match"); - - let real = Services.io.newURI(content.location.href); - let expect = Services.io.newURI(url); - is(real.scheme, expect.scheme, "Go Back URL Scheme"); - }); - } - - // Go forward to the last entry. - for (let {url} of HISTORY.slice(1)) { - ContentTask.spawn(aBrowser, {}, () => { content.history.forward(); }); - await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { - return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; - }); - - index++; - await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { - docShell.QueryInterface(Ci.nsIWebNavigation); - - is(docShell.sessionHistory.count, count, "Go Forward Count Match"); - is(docShell.sessionHistory.index, index, "Go Forward Index Match"); - - let real = Services.io.newURI(content.location.href); - let expect = Services.io.newURI(url); - is(real.scheme, expect.scheme, "Go Forward URL Scheme"); - }); - } - }); -} - - -add_task(async function prefDisabled() { - await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, false]]}); - await runTest(); -}); - - -add_task(async function prefEnabled() { - await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, true]]}); - await runTest(); -}); diff --git a/toolkit/components/remotebrowserutils/tests/browser/head.js b/toolkit/components/remotebrowserutils/tests/browser/head.js deleted file mode 100644 index 8242eb9602a9..000000000000 --- a/toolkit/components/remotebrowserutils/tests/browser/head.js +++ /dev/null @@ -1,15 +0,0 @@ -function fileURL(filename) { - let ifile = getChromeDir(getResolvedURI(gTestPath)); - ifile.append(filename); - return Services.io.newFileURI(ifile).spec; -} - -function httpURL(filename, host = "https://example.com/") { - let root = getRootDirectory(gTestPath) - .replace("chrome://mochitests/content/", host); - return root + filename; -} - -function add307(url, host = "https://example.com/") { - return httpURL("307redirect.sjs?" + url, host); -} diff --git a/toolkit/modules/E10SUtils.jsm b/toolkit/modules/E10SUtils.jsm index f95a4e724cf0..594f0dab1d19 100644 --- a/toolkit/modules/E10SUtils.jsm +++ b/toolkit/modules/E10SUtils.jsm @@ -323,20 +323,6 @@ var E10SUtils = { return true; } - let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); - let sessionHistory = webNav.sessionHistory; - if (!aHasPostData && - Services.appinfo.remoteType == WEB_REMOTE_TYPE && - sessionHistory.count == 1 && - webNav.currentURI.spec == "about:newtab") { - // This is possibly a preloaded browser and we're about to navigate away for - // the first time. On the child side there is no way to tell for sure if that - // is the case, so let's redirect this request to the parent to decide if a new - // process is needed. But we don't currently properly handle POST data in - // redirects (bug 1457520), so if there is POST data, don't return false here. - return false; - } - // If we are performing HTTP response process selection, and are loading an // HTTP URI, we can start the load in the current process, and then perform // the switch later-on using the RedirectProcessChooser mechanism. @@ -361,6 +347,8 @@ var E10SUtils = { } // Allow history load if loaded in this process before. + let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); + let sessionHistory = webNav.sessionHistory; let requestedIndex = sessionHistory.legacySHistory.requestedIndex; if (requestedIndex >= 0) { if (sessionHistory.legacySHistory.getEntryAtIndex(requestedIndex).loadedInThisProcess) { @@ -374,6 +362,18 @@ var E10SUtils = { this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI); } + if (!aHasPostData && + Services.appinfo.remoteType == WEB_REMOTE_TYPE && + sessionHistory.count == 1 && + webNav.currentURI.spec == "about:newtab") { + // This is possibly a preloaded browser and we're about to navigate away for + // the first time. On the child side there is no way to tell for sure if that + // is the case, so let's redirect this request to the parent to decide if a new + // process is needed. But we don't currently properly handle POST data in + // redirects (bug 1457520), so if there is POST data, don't return false here. + return false; + } + // If the URI can be loaded in the current process then continue return this.shouldLoadURIInThisProcess(aURI); }, diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm index 60b158a9845d..110aabbb835a 100644 --- a/toolkit/modules/sessionstore/SessionHistory.jsm +++ b/toolkit/modules/sessionstore/SessionHistory.jsm @@ -76,12 +76,7 @@ var SessionHistoryInternal = { let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); let history = webNavigation.sessionHistory; - let data = { - entries: [], - userContextId: loadContext.originAttributes.userContextId, - requestedIndex: history.legacySHistory.requestedIndex + 1, - }; - + let data = {entries: [], userContextId: loadContext.originAttributes.userContextId }; // We want to keep track how many entries we *could* have collected and // how many we skipped, so we can sanitiy-check the current history index // and also determine whether we need to get any fallback data or not. From 541421178945a78b3f17581b5f4b9bebbf32dc80 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:12:49 +0000 Subject: [PATCH 44/84] Bug 1522637 - Part 1: Disable in tests for allowLinkedWebInFileUriProcess, r=bobowen Differential Revision: https://phabricator.services.mozilla.com/D18602 --HG-- extra : source : 5988b8e7d17c0f01aa3e3eeb967004aef66ddaa5 --- .../test/tabs/browser_new_web_tab_in_file_process_pref.js | 1 + dom/ipc/WindowGlobalChild.h | 1 + 2 files changed, 2 insertions(+) diff --git a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js index fa3166099640..31948fe20feb 100644 --- a/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js +++ b/browser/base/content/test/tabs/browser_new_web_tab_in_file_process_pref.js @@ -24,6 +24,7 @@ add_task(async function() { await SpecialPowers.pushPrefEnv( {set: [["browser.tabs.remote.separateFileUriProcess", true], ["browser.tabs.remote.allowLinkedWebInFileUriProcess", true], + ["browser.tabs.remote.useHTTPResponseProcessSelection", false], ["dom.ipc.processCount.file", 2]]}); // Open file:// page. diff --git a/dom/ipc/WindowGlobalChild.h b/dom/ipc/WindowGlobalChild.h index 2910e75b8fd3..5f1fe5b953ce 100644 --- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -20,6 +20,7 @@ namespace dom { class BrowsingContext; class WindowGlobalParent; class JSWindowActorChild; +class TabChild; /** * Actor for a single nsGlobalWindowInner. This actor is used to communicate From 9f36101095c84b1260d9a4460ff599533ee17a52 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:12:51 +0000 Subject: [PATCH 45/84] Bug 1522637 - Part 2: Include BrowsingContextID in LoadInfo for subdocument loads, r=valentin Depends on D18602 Differential Revision: https://phabricator.services.mozilla.com/D18603 --HG-- extra : source : 5eeda2ba8e7965fccf3e17a8d1fd059872b2c2e8 --- .../components/sessionstore/SessionStore.jsm | 14 ++++++++----- ipc/glue/BackgroundUtils.cpp | 4 +++- netwerk/base/LoadInfo.cpp | 20 ++++++++++++++++++- netwerk/base/LoadInfo.h | 3 ++- netwerk/base/nsILoadInfo.idl | 7 +++++++ netwerk/ipc/NeckoChannelParams.ipdlh | 1 + 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index a3d092977e0a..5b3580ad8bf0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -2323,13 +2323,17 @@ var SessionStoreInternal = { return; // Not a document load. } - let browsingContext = aChannel.loadInfo.browsingContext; - if (!browsingContext) { - return; // Not loading in a browsing context. + let cpType = aChannel.loadInfo.externalContentPolicyType; + let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT; + if (!toplevel) { + return; // Not loading a toplevel document. } - if (browsingContext.parent) { - return; // Not a toplevel load, can't flip procs. + let browsingContext = toplevel + ? aChannel.loadInfo.browsingContext + : aChannel.loadInfo.frameBrowsingContext; + if (!browsingContext) { + return; // Not loading in a browsing context. } // Get principal for a document already loaded in the BrowsingContext. diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 9c7ed8a07ae9..85250564d2c2 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -477,6 +477,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetTopOuterWindowID(), aLoadInfo->GetFrameOuterWindowID(), aLoadInfo->GetBrowsingContextID(), + aLoadInfo->GetFrameBrowsingContextID(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetIsDocshellReload(), aLoadInfo->GetSendCSPViolationEvents(), aLoadInfo->GetOriginAttributes(), @@ -634,7 +635,8 @@ nsresult LoadInfoArgsToLoadInfo( loadInfoArgs.forceInheritPrincipalDropped(), loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), loadInfoArgs.parentOuterWindowID(), loadInfoArgs.topOuterWindowID(), loadInfoArgs.frameOuterWindowID(), - loadInfoArgs.browsingContextID(), loadInfoArgs.initialSecurityCheckDone(), + loadInfoArgs.browsingContextID(), loadInfoArgs.frameBrowsingContextID(), + loadInfoArgs.initialSecurityCheckDone(), loadInfoArgs.isInThirdPartyContext(), loadInfoArgs.isDocshellReload(), loadInfoArgs.sendCSPViolationEvents(), loadInfoArgs.originAttributes(), redirectChainIncludingInternalRedirects, redirectChain, diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index a35b8ce525b7..0e381e396378 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -80,6 +80,7 @@ LoadInfo::LoadInfo( mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), + mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), mIsDocshellReload(false), @@ -230,6 +231,9 @@ LoadInfo::LoadInfo( nsCOMPtr outerWindow = do_GetInterface(docShell); if (outerWindow) { mFrameOuterWindowID = outerWindow->WindowID(); + + RefPtr bc = outerWindow->GetBrowsingContext(); + mFrameBrowsingContextID = bc ? bc->Id() : 0; } } } @@ -362,6 +366,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, mTopOuterWindowID(0), mFrameOuterWindowID(0), mBrowsingContextID(0), + mFrameBrowsingContextID(0), mInitialSecurityCheckDone(false), mIsThirdPartyContext(false), // NB: TYPE_DOCUMENT implies !third-party. mIsDocshellReload(false), @@ -500,7 +505,7 @@ LoadInfo::LoadInfo( bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, + uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyContext, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -543,6 +548,7 @@ LoadInfo::LoadInfo( mTopOuterWindowID(aTopOuterWindowID), mFrameOuterWindowID(aFrameOuterWindowID), mBrowsingContextID(aBrowsingContextID), + mFrameBrowsingContextID(aFrameBrowsingContextID), mInitialSecurityCheckDone(aInitialSecurityCheckDone), mIsThirdPartyContext(aIsThirdPartyContext), mIsDocshellReload(aIsDocshellReload), @@ -993,12 +999,24 @@ LoadInfo::GetBrowsingContextID(uint64_t* aResult) { return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetFrameBrowsingContextID(uint64_t* aResult) { + *aResult = mFrameBrowsingContextID; + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetBrowsingContext(dom::BrowsingContext** aResult) { *aResult = BrowsingContext::Get(mBrowsingContextID).take(); return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetFrameBrowsingContext(dom::BrowsingContext** aResult) { + *aResult = BrowsingContext::Get(mFrameBrowsingContextID).take(); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetScriptableOriginAttributes( JSContext* aCx, JS::MutableHandle aOriginAttributes) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 851602553ebe..15c016d5f850 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -111,7 +111,7 @@ class LoadInfo final : public nsILoadInfo { bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, uint64_t aTopOuterWindowID, uint64_t aFrameOuterWindowID, - uint64_t aBrowsingContextID, + uint64_t aBrowsingContextID, uint64_t aFrameBrowsingContextID, bool aInitialSecurityCheckDone, bool aIsThirdPartyRequest, bool aIsDocshellReload, bool aSendCSPViolationEvents, const OriginAttributes& aOriginAttributes, @@ -184,6 +184,7 @@ class LoadInfo final : public nsILoadInfo { uint64_t mTopOuterWindowID; uint64_t mFrameOuterWindowID; uint64_t mBrowsingContextID; + uint64_t mFrameBrowsingContextID; bool mInitialSecurityCheckDone; bool mIsThirdPartyContext; bool mIsDocshellReload; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 6a8ba66c1a47..9c98c654fd60 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -634,6 +634,13 @@ interface nsILoadInfo : nsISupports [infallible] readonly attribute unsigned long long browsingContextID; readonly attribute BrowsingContext browsingContext; + /** + * Like `frameOuterWindowID`, however returning the BrowsingContextID + * instead. + */ + [infallible] readonly attribute unsigned long long frameBrowsingContextID; + readonly attribute BrowsingContext frameBrowsingContext; + /** * Resets the PrincipalToInherit to a freshly created NullPrincipal * which inherits the origin attributes from the loadInfo. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 267f9ea22aaa..08a92c60b5e7 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -64,6 +64,7 @@ struct LoadInfoArgs uint64_t topOuterWindowID; uint64_t frameOuterWindowID; uint64_t browsingContextID; + uint64_t frameBrowsingContextID; bool initialSecurityCheckDone; bool isInThirdPartyContext; bool isDocshellReload; From 6ded246a08dfbf2287086a3b86e9a9f10acdec0e Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:36:02 +0000 Subject: [PATCH 46/84] Bug 1522637 - Part 3: Send history index when resuming redirected loads, r=qdot Depends on D18603 Differential Revision: https://phabricator.services.mozilla.com/D18604 --HG-- extra : source : 6b4d010964ec9e2175e7ba02991d083fab128c49 --- .../sessionstore/ContentRestore.jsm | 3 +- .../components/sessionstore/SessionStore.jsm | 8 ++++ browser/components/sessionstore/TabState.jsm | 4 ++ docshell/base/nsDocShell.cpp | 38 ++++++++++++++----- docshell/base/nsIWebNavigation.idl | 6 ++- docshell/shistory/nsISHistory.idl | 8 ++++ docshell/shistory/nsSHistory.cpp | 6 +++ toolkit/components/browser/nsWebBrowser.cpp | 5 ++- .../modules/sessionstore/SessionHistory.jsm | 7 +++- 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/browser/components/sessionstore/ContentRestore.jsm b/browser/components/sessionstore/ContentRestore.jsm index b9d2b8449758..ce339b25a306 100644 --- a/browser/components/sessionstore/ContentRestore.jsm +++ b/browser/components/sessionstore/ContentRestore.jsm @@ -186,7 +186,8 @@ ContentRestoreInternal.prototype = { // If the load was started in another process, and the in-flight channel // was redirected into this process, resume that load within our process. if (loadArguments.redirectLoadSwitchId) { - webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId); + webNavigation.resumeRedirectedLoad(loadArguments.redirectLoadSwitchId, + loadArguments.redirectHistoryIndex); return true; } diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 5b3580ad8bf0..49b111ecd7c0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3235,6 +3235,14 @@ var SessionStoreInternal = { tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length)); } else { options.loadArguments = loadArguments; + + // If we're resuming a load which has been redirected from another + // process, record the history index which is currently being requested. + // It has to be offset by 1 to get back to native history indices from + // SessionStore history indicies. + if (loadArguments.redirectLoadSwitchId) { + loadArguments.redirectHistoryIndex = tabState.requestedIndex - 1; + } } // Need to reset restoring tabs. diff --git a/browser/components/sessionstore/TabState.jsm b/browser/components/sessionstore/TabState.jsm index 442e51362cd4..054bf7a68f9c 100644 --- a/browser/components/sessionstore/TabState.jsm +++ b/browser/components/sessionstore/TabState.jsm @@ -184,6 +184,10 @@ var TabStateInternal = { if (value.hasOwnProperty("index")) { tabData.index = value.index; } + + if (value.hasOwnProperty("requestedIndex")) { + tabData.requestedIndex = value.requestedIndex; + } } else { tabData[key] = value; } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 600955aa18be..ff67dd438ab3 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -12993,21 +12993,39 @@ nsDocShell::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier) { +nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) { RefPtr self = this; RefPtr cpcl = ChildProcessChannelListener::GetSingleton(); // Call into InternalLoad with the pending channel when it is received. - cpcl->RegisterCallback(aIdentifier, [self](nsIChildChannel* aChannel) { - RefPtr loadState; - nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( - aChannel, getter_AddRefs(loadState)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - self->InternalLoad(loadState, nullptr, nullptr); - }); + cpcl->RegisterCallback( + aIdentifier, [self, aHistoryIndex](nsIChildChannel* aChannel) { + RefPtr loadState; + nsresult rv = nsDocShellLoadState::CreateFromPendingChannel( + aChannel, getter_AddRefs(loadState)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + // If we're performing a history load, locate the correct history entry, + // and set the relevant bits on our loadState. + if (aHistoryIndex >= 0) { + nsCOMPtr legacySHistory = + self->mSessionHistory->LegacySHistory(); + + nsCOMPtr entry; + rv = legacySHistory->GetEntryAtIndex(aHistoryIndex, + getter_AddRefs(entry)); + if (NS_SUCCEEDED(rv)) { + legacySHistory->InternalSetRequestedIndex(aHistoryIndex); + loadState->SetLoadType(LOAD_HISTORY); + loadState->SetSHEntry(entry); + } + } + + self->InternalLoad(loadState, nullptr, nullptr); + }); return NS_OK; } diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl index e7e38809de7b..cabae3f31d0f 100644 --- a/docshell/base/nsIWebNavigation.idl +++ b/docshell/base/nsIWebNavigation.idl @@ -342,6 +342,10 @@ interface nsIWebNavigation : nsISupports /** * Resume a load which has been redirected from another process. + * + * A negative |aHistoryIndex| value corresponds to a non-history load being + * resumed. */ - void resumeRedirectedLoad(in unsigned long long aLoadIdentifier); + void resumeRedirectedLoad(in unsigned long long aLoadIdentifier, + in long aHistoryIndex); }; diff --git a/docshell/shistory/nsISHistory.idl b/docshell/shistory/nsISHistory.idl index 73747d978986..429947d77124 100644 --- a/docshell/shistory/nsISHistory.idl +++ b/docshell/shistory/nsISHistory.idl @@ -52,6 +52,14 @@ interface nsISHistory: nsISupports */ [infallible] readonly attribute long requestedIndex; + /** + * Artifically set the |requestedIndex| for this nsISHEntry to the given + * index. This is used when resuming a cross-process load from a different + * process. + */ + [noscript, notxpcom] + void internalSetRequestedIndex(in long aRequestedIndex); + /** * Get the history entry at a given index. Returns non-null on success. * diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index e5ab98e0a839..2ebe5eab1e3d 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -626,6 +626,12 @@ nsSHistory::GetRequestedIndex(int32_t* aResult) { return NS_OK; } +NS_IMETHODIMP_(void) +nsSHistory::InternalSetRequestedIndex(int32_t aRequestedIndex) { + MOZ_ASSERT(aRequestedIndex >= -1 && aRequestedIndex < Length()); + mRequestedIndex = aRequestedIndex; +} + NS_IMETHODIMP nsSHistory::GetEntryAtIndex(int32_t aIndex, nsISHEntry** aResult) { NS_ENSURE_ARG_POINTER(aResult); diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp index 98fa6c90daf7..7a8bbe3330a4 100644 --- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -579,8 +579,9 @@ nsWebBrowser::SetOriginAttributesBeforeLoading( } NS_IMETHODIMP -nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier) { - return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier); +nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier, + int32_t aHistoryIndex) { + return mDocShellAsNav->ResumeRedirectedLoad(aIdentifier, aHistoryIndex); } NS_IMETHODIMP diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm index 110aabbb835a..60b158a9845d 100644 --- a/toolkit/modules/sessionstore/SessionHistory.jsm +++ b/toolkit/modules/sessionstore/SessionHistory.jsm @@ -76,7 +76,12 @@ var SessionHistoryInternal = { let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); let history = webNavigation.sessionHistory; - let data = {entries: [], userContextId: loadContext.originAttributes.userContextId }; + let data = { + entries: [], + userContextId: loadContext.originAttributes.userContextId, + requestedIndex: history.legacySHistory.requestedIndex + 1, + }; + // We want to keep track how many entries we *could* have collected and // how many we skipped, so we can sanitiy-check the current history index // and also determine whether we need to get any fallback data or not. From 507211a3ab5fb07c6c1599f750195e84eb8f1ff5 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:01 +0000 Subject: [PATCH 47/84] Bug 1522637 - Part 4: Support browsers in globals without gMultiProcessBrowser, r=qdot Depends on D18604 Differential Revision: https://phabricator.services.mozilla.com/D18605 --HG-- extra : source : 8f494271ec06babf4ee70bb58a3a967e25d74c82 --- .../components/sessionstore/SessionStore.jsm | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 49b111ecd7c0..3e920df6cee0 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -2286,6 +2286,8 @@ var SessionStoreInternal = { * processes. */ async _doProcessSwitch(aBrowser, aRemoteType, aChannel, aSwitchId) { + debug(`[process-switch]: performing switch from ${aBrowser.remoteType} to ${aRemoteType}`); + // Don't try to switch tabs before delayed startup is completed. await aBrowser.ownerGlobal.delayedStartupPromise; @@ -2309,7 +2311,9 @@ var SessionStoreInternal = { } // Tell our caller to redirect the load into this newly created process. - return aBrowser.frameLoader.tabParent; + let tabParent = aBrowser.frameLoader.tabParent; + debug(`[process-switch]: new tabID: ${tabParent.tabId}`); + return tabParent; }, // Examine the channel response to see if we should change the process @@ -2323,17 +2327,21 @@ var SessionStoreInternal = { return; // Not a document load. } + // Check that this is a toplevel document load. let cpType = aChannel.loadInfo.externalContentPolicyType; let toplevel = cpType == Ci.nsIContentPolicy.TYPE_DOCUMENT; if (!toplevel) { - return; // Not loading a toplevel document. + debug(`[process-switch]: non-toplevel - ignoring`); + return; } + // Check that the document has a corresponding BrowsingContext. let browsingContext = toplevel ? aChannel.loadInfo.browsingContext : aChannel.loadInfo.frameBrowsingContext; if (!browsingContext) { - return; // Not loading in a browsing context. + debug(`[process-switch]: no BrowsingContext - ignoring`); + return; } // Get principal for a document already loaded in the BrowsingContext. @@ -2342,34 +2350,60 @@ var SessionStoreInternal = { currentPrincipal = browsingContext.currentWindowGlobal.documentPrincipal; } - let parentChannel = aChannel.notificationCallbacks - .getInterface(Ci.nsIParentChannel); - if (!parentChannel) { - return; // Not an actor channel + // Ensure we have an nsIParentChannel listener for a remote load. + let parentChannel; + try { + parentChannel = aChannel.notificationCallbacks + .getInterface(Ci.nsIParentChannel); + } catch (e) { + debug(`[process-switch]: No nsIParentChannel callback - ignoring`); + return; } - let tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsITabParent); - if (!tabParent || !tabParent.ownerElement) { - console.warn("warning: Missing tabParent"); - return; // Not an embedded browsing context + // Ensure we have a nsITabParent for our remote load. + let tabParent; + try { + tabParent = parentChannel.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsITabParent); + } catch (e) { + debug(`[process-switch]: No nsITabParent for channel - ignoring`); + return; } + // Ensure we're loaded in a regular tabbrowser environment, and can swap processes. let browser = tabParent.ownerElement; - if (browser.tagName !== "browser") { - console.warn("warning: Not a xul:browser element:", browser.tagName); - return; // Not a vanilla xul:browser element performing embedding. + if (!browser) { + debug(`[process-switch]: TabParent has no ownerElement - ignoring`); } + let tabbrowser = browser.ownerGlobal.gBrowser; + if (!tabbrowser) { + debug(`[process-switch]: cannot find tabbrowser for loading tab - ignoring`); + return; + } + + let tab = tabbrowser.getTabForBrowser(browser); + if (!tab) { + debug(`[process-switch]: not a normal tab, so cannot swap processes - ignoring`); + return; + } + + // Determine the process type the load should be performed in. let resultPrincipal = Services.scriptSecurityManager.getChannelResultPrincipal(aChannel); - let useRemoteTabs = browser.ownerGlobal.gMultiProcessBrowser; let remoteType = E10SUtils.getRemoteTypeForPrincipal(resultPrincipal, - useRemoteTabs, + true, browser.remoteType, currentPrincipal); if (browser.remoteType == remoteType) { - return; // Already in compatible process. + debug(`[process-switch]: type (${remoteType}) is compatible - ignoring`); + return; + } + + if (remoteType == E10SUtils.NOT_REMOTE || + browser.remoteType == E10SUtils.NOT_REMOTE) { + debug(`[process-switch]: non-remote source/target - ignoring`); + return; } // ------------------------------------------------------------------------ From daeb7ef4b82cb8ce6ea2471e41685ffb21ab7925 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:03 +0000 Subject: [PATCH 48/84] Bug 1522637 - Part 5: Add tests for history navigations between http and file URIs with new pref, r=qdot Depends on D18605 Differential Revision: https://phabricator.services.mozilla.com/D18606 --HG-- extra : source : 6e0d4b6b1c93b5211ebbf264190cae7d271b7ae2 --- .../tests/browser/browser.ini | 2 + .../browser_httpResponseProcessSelection.js | 16 --- .../browser/browser_httpToFileHistory.js | 99 +++++++++++++++++++ .../remotebrowserutils/tests/browser/head.js | 15 +++ 4 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js create mode 100644 toolkit/components/remotebrowserutils/tests/browser/head.js diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser.ini b/toolkit/components/remotebrowserutils/tests/browser/browser.ini index b55376c4d462..06834883e246 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser.ini +++ b/toolkit/components/remotebrowserutils/tests/browser/browser.ini @@ -4,6 +4,8 @@ support-files = dummy_page.html print_postdata.sjs 307redirect.sjs + head.js [browser_RemoteWebNavigation.js] [browser_httpResponseProcessSelection.js] +[browser_httpToFileHistory.js] diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js index 859555b9764a..1f0f0031093c 100644 --- a/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js +++ b/toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js @@ -2,22 +2,6 @@ const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); let PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; -function fileURL(filename) { - let ifile = getChromeDir(getResolvedURI(gTestPath)); - ifile.append(filename); - return Services.io.newFileURI(ifile).spec; -} - -function httpURL(filename, host = "https://example.com/") { - let root = getRootDirectory(gTestPath) - .replace("chrome://mochitests/content/", host); - return root + filename; -} - -function add307(url, host = "https://example.com/") { - return httpURL("307redirect.sjs?" + url, host); -} - async function performLoad(browser, opts, action) { let loadedPromise = BrowserTestUtils.browserLoaded( browser, false, opts.url, opts.maybeErrorPage); diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js b/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js new file mode 100644 index 000000000000..495a6979d4cc --- /dev/null +++ b/toolkit/components/remotebrowserutils/tests/browser/browser_httpToFileHistory.js @@ -0,0 +1,99 @@ +const {E10SUtils} = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm"); + +const PREF_NAME = "browser.tabs.remote.useHTTPResponseProcessSelection"; +const HISTORY = [ + {url: httpURL("dummy_page.html")}, + {url: fileURL("dummy_page.html")}, + {url: httpURL("dummy_page.html")}, +]; + +function reversed(list) { + let copy = list.slice(); + copy.reverse(); + return copy; +} + +function butLast(list) { + let copy = list.slice(); + copy.pop(); + return copy; +} + +async function runTest() { + await BrowserTestUtils.withNewTab({gBrowser}, async function(aBrowser) { + // Perform initial load of each URL in the history. + let count = 0; + let index = -1; + for (let {url} of HISTORY) { + BrowserTestUtils.loadURI(aBrowser, url); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + count++; + index++; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Initial Navigation Count Match"); + is(docShell.sessionHistory.index, index, "Initial Navigation Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Initial Navigation URL Scheme"); + }); + } + + // Go back to the first entry. + for (let {url} of reversed(HISTORY).slice(1)) { + ContentTask.spawn(aBrowser, {}, () => { content.history.back(); }); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + index--; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Go Back Count Match"); + is(docShell.sessionHistory.index, index, "Go Back Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Go Back URL Scheme"); + }); + } + + // Go forward to the last entry. + for (let {url} of HISTORY.slice(1)) { + ContentTask.spawn(aBrowser, {}, () => { content.history.forward(); }); + await BrowserTestUtils.browserLoaded(aBrowser, false, loaded => { + return Services.io.newURI(loaded).scheme == Services.io.newURI(url).scheme; + }); + + index++; + await ContentTask.spawn(aBrowser, {count, index, url}, async function({count, index, url}) { + docShell.QueryInterface(Ci.nsIWebNavigation); + + is(docShell.sessionHistory.count, count, "Go Forward Count Match"); + is(docShell.sessionHistory.index, index, "Go Forward Index Match"); + + let real = Services.io.newURI(content.location.href); + let expect = Services.io.newURI(url); + is(real.scheme, expect.scheme, "Go Forward URL Scheme"); + }); + } + }); +} + + +add_task(async function prefDisabled() { + await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, false]]}); + await runTest(); +}); + + +add_task(async function prefEnabled() { + await SpecialPowers.pushPrefEnv({set: [[PREF_NAME, true]]}); + await runTest(); +}); diff --git a/toolkit/components/remotebrowserutils/tests/browser/head.js b/toolkit/components/remotebrowserutils/tests/browser/head.js new file mode 100644 index 000000000000..8242eb9602a9 --- /dev/null +++ b/toolkit/components/remotebrowserutils/tests/browser/head.js @@ -0,0 +1,15 @@ +function fileURL(filename) { + let ifile = getChromeDir(getResolvedURI(gTestPath)); + ifile.append(filename); + return Services.io.newFileURI(ifile).spec; +} + +function httpURL(filename, host = "https://example.com/") { + let root = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content/", host); + return root + filename; +} + +function add307(url, host = "https://example.com/") { + return httpURL("307redirect.sjs?" + url, host); +} From 49c54952a4488a294e5ff6f825f473981f585ed8 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:05 +0000 Subject: [PATCH 49/84] Bug 1522637 - Part 6: Enable httpResponseProcessSelection by default, r=qdot Depends on D18606 Differential Revision: https://phabricator.services.mozilla.com/D18607 --HG-- extra : source : 41ca0b87537e8a6ca2049d6a0be20d1071aeac09 --- browser/app/profile/firefox.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index a07a61ca2257..3f09bb66e776 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -483,6 +483,9 @@ pref("browser.tabs.newanimations", false); pref("browser.tabs.remote.separatePrivilegedContentProcess", true); #endif +// Turn on HTTP response process selection. +pref("browser.tabs.remote.useHTTPResponseProcessSelection", true); + pref("browser.ctrlTab.recentlyUsedOrder", true); // By default, do not export HTML at shutdown. From a2bc82eb15c1b05020c47e475f8d2f744d10693c Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:37:06 +0000 Subject: [PATCH 50/84] Bug 1522637 - Part 7: Perform process switches separtely from on-examine-response, r=valentin Issues were occuring where a process swap would be decided upon during on-examine-response, but before the swap could be handled by the channel, the channel was redirected. This new code takes the mildly hacky approach of simply using a separate observer notification which is fired at the correct time. A better solution may be to use a dedicated service for responding to these events, however that was not implemented for this initial patch. Depends on D18607 Differential Revision: https://phabricator.services.mozilla.com/D19691 --HG-- extra : source : 3d24e8e81c02af9d1edec7571afecefb0d2f1eb4 --- .../components/sessionstore/SessionStore.jsm | 12 ++---- netwerk/protocol/http/nsHttpChannel.cpp | 38 ++++++++++++------- netwerk/protocol/http/nsHttpHandler.h | 4 ++ .../protocol/http/nsIHttpProtocolHandler.idl | 8 ++++ .../browser/browser_cross_process_redirect.js | 12 ++---- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index 3e920df6cee0..c0370612cfc9 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -48,9 +48,7 @@ const OBSERVING = [ "quit-application", "browser:purge-session-history", "browser:purge-session-history-for-domain", "idle-daily", "clear-origin-attributes-data", - "http-on-examine-response", - "http-on-examine-merged-response", - "http-on-examine-cached-response", + "http-on-may-change-process", ]; // XUL Window properties to (re)store @@ -814,10 +812,8 @@ var SessionStoreInternal = { this._forgetTabsWithUserContextId(userContextId); } break; - case "http-on-examine-response": - case "http-on-examine-cached-response": - case "http-on-examine-merged-response": - this.onExamineResponse(aSubject); + case "http-on-may-change-process": + this.onMayChangeProcess(aSubject); break; } }, @@ -2318,7 +2314,7 @@ var SessionStoreInternal = { // Examine the channel response to see if we should change the process // performing the given load. - onExamineResponse(aChannel) { + onMayChangeProcess(aChannel) { if (!E10SUtils.useHttpResponseProcessSelection()) { return; } diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index e48e97e624a8..5fb40d79a1f0 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -2450,15 +2450,20 @@ nsresult nsHttpChannel::ContinueProcessResponse1() { } rv = NS_OK; - if (mRedirectTabPromise && !mCanceled) { - MOZ_ASSERT(!mOnStartRequestCalled); + if (!mCanceled) { + // notify "http-on-may-change-process" observers + gHttpHandler->OnMayChangeProcess(this); - PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; + if (mRedirectTabPromise) { + MOZ_ASSERT(!mOnStartRequestCalled); + + PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse2); } // No process switch needed, continue as normal. @@ -7121,6 +7126,8 @@ NS_IMETHODIMP nsHttpChannel::SwitchProcessTo(dom::Promise *aTabPromise, nsresult nsHttpChannel::StartCrossProcessRedirect() { nsresult rv; + LOG(("nsHttpChannel::StartCrossProcessRedirect [this=%p]", this)); + rv = CheckRedirectLimit(nsIChannelEventSink::REDIRECT_INTERNAL); NS_ENSURE_SUCCESS(rv, rv); @@ -7257,13 +7264,18 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { // before we check for redirects, check if the load should be shifted into a // new process. rv = NS_OK; - if (mRedirectTabPromise && !mCanceled) { - PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); - rv = StartCrossProcessRedirect(); - if (NS_SUCCEEDED(rv)) { - return NS_OK; + if (!mCanceled) { + // notify "http-on-may-change-process" observers + gHttpHandler->OnMayChangeProcess(this); + + if (mRedirectTabPromise) { + PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); + rv = StartCrossProcessRedirect(); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } + PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); } - PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest1); } // No process change is needed, so continue on to ContinueOnStartRequest1. diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index d2eb2e08a90e..1e7dd003bac3 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -368,6 +368,10 @@ class nsHttpHandler final : public nsIHttpProtocolHandler, NotifyObservers(chan, NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC); } + void OnMayChangeProcess(nsIHttpChannel *chan) { + NotifyObservers(chan, NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC); + } + // Generates the host:port string for use in the Host: header as well as the // CONNECT line for proxies. This handles IPv6 literals correctly. static MOZ_MUST_USE nsresult GenerateHostPort(const nsCString &host, diff --git a/netwerk/protocol/http/nsIHttpProtocolHandler.idl b/netwerk/protocol/http/nsIHttpProtocolHandler.idl index 6132608011ae..6abe8e8276bb 100644 --- a/netwerk/protocol/http/nsIHttpProtocolHandler.idl +++ b/netwerk/protocol/http/nsIHttpProtocolHandler.idl @@ -123,6 +123,14 @@ interface nsIHttpProtocolHandler : nsIProxiedProtocolHandler */ #define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response" +/** + * The observer of this topic is notified before before the response for a HTTP + * load is available. The "subject" of the notification is the nsIHttpChannel + * instance. Observers may call "switchProcessTo" to perform a process switch + * while this is being run. + */ +#define NS_HTTP_ON_MAY_CHANGE_PROCESS_TOPIC "http-on-may-change-process" + /** * Before an HTTP request corresponding to a channel with the LOAD_DOCUMENT_URI * flag is sent to the server, this observer topic is notified. The observer of diff --git a/netwerk/test/browser/browser_cross_process_redirect.js b/netwerk/test/browser/browser_cross_process_redirect.js index 28985bdd90c6..602d78f0f904 100644 --- a/netwerk/test/browser/browser_cross_process_redirect.js +++ b/netwerk/test/browser/browser_cross_process_redirect.js @@ -23,9 +23,7 @@ function ProcessChooser(tabParent, from, to, rejectPromise = false) { this.rejectPromise = rejectPromise; this.registered = true; - Services.obs.addObserver(this, "http-on-examine-response"); - Services.obs.addObserver(this, "http-on-examine-merged-response"); - Services.obs.addObserver(this, "http-on-examine-cached-response"); + Services.obs.addObserver(this, "http-on-may-change-process"); } ProcessChooser.prototype = { @@ -34,9 +32,7 @@ ProcessChooser.prototype = { return; } this.registered = false; - Services.obs.removeObserver(this, "http-on-examine-response"); - Services.obs.removeObserver(this, "http-on-examine-merged-response"); - Services.obs.removeObserver(this, "http-on-examine-cached-response"); + Services.obs.removeObserver(this, "http-on-may-change-process"); }, examine(aChannel) { @@ -83,9 +79,7 @@ ProcessChooser.prototype = { observe(aSubject, aTopic, aData) { switch (aTopic) { - case "http-on-examine-response": - case "http-on-examine-cached-response": - case "http-on-examine-merged-response": + case "http-on-may-change-process": this.examine(aSubject.QueryInterface(Ci.nsIHttpChannel)); break; default: From de50cd0883602dddcb6361f49e90926dd09fe909 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 15:14:10 +0000 Subject: [PATCH 51/84] Bug 1522637 - Part 8: Perform the preloaded document swap before checking for HTTP loads, r=mconley For HTTP loads from the preloaded document, no process swap was occuring if the preloaded document was loaded in a 'web' process. This caused test failures, and has potentially undesireable behaviour. This patch just moves the check for preloaded document swaps to before the check for http parent process interception, forcing a swap like normal. Depends on D19691 Differential Revision: https://phabricator.services.mozilla.com/D19692 --HG-- extra : source : f7ab0e6e739bd54b66b8aaa6219c7dba78f37eb1 --- toolkit/modules/E10SUtils.jsm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/toolkit/modules/E10SUtils.jsm b/toolkit/modules/E10SUtils.jsm index 594f0dab1d19..f95a4e724cf0 100644 --- a/toolkit/modules/E10SUtils.jsm +++ b/toolkit/modules/E10SUtils.jsm @@ -323,6 +323,20 @@ var E10SUtils = { return true; } + let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); + let sessionHistory = webNav.sessionHistory; + if (!aHasPostData && + Services.appinfo.remoteType == WEB_REMOTE_TYPE && + sessionHistory.count == 1 && + webNav.currentURI.spec == "about:newtab") { + // This is possibly a preloaded browser and we're about to navigate away for + // the first time. On the child side there is no way to tell for sure if that + // is the case, so let's redirect this request to the parent to decide if a new + // process is needed. But we don't currently properly handle POST data in + // redirects (bug 1457520), so if there is POST data, don't return false here. + return false; + } + // If we are performing HTTP response process selection, and are loading an // HTTP URI, we can start the load in the current process, and then perform // the switch later-on using the RedirectProcessChooser mechanism. @@ -347,8 +361,6 @@ var E10SUtils = { } // Allow history load if loaded in this process before. - let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); - let sessionHistory = webNav.sessionHistory; let requestedIndex = sessionHistory.legacySHistory.requestedIndex; if (requestedIndex >= 0) { if (sessionHistory.legacySHistory.getEntryAtIndex(requestedIndex).loadedInThisProcess) { @@ -362,18 +374,6 @@ var E10SUtils = { this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI); } - if (!aHasPostData && - Services.appinfo.remoteType == WEB_REMOTE_TYPE && - sessionHistory.count == 1 && - webNav.currentURI.spec == "about:newtab") { - // This is possibly a preloaded browser and we're about to navigate away for - // the first time. On the child side there is no way to tell for sure if that - // is the case, so let's redirect this request to the parent to decide if a new - // process is needed. But we don't currently properly handle POST data in - // redirects (bug 1457520), so if there is POST data, don't return false here. - return false; - } - // If the URI can be loaded in the current process then continue return this.shouldLoadURIInThisProcess(aURI); }, From efbf371fda00a77841c6cd03cd959a638d6a149e Mon Sep 17 00:00:00 2001 From: Dorel Luca Date: Thu, 14 Feb 2019 20:43:45 +0200 Subject: [PATCH 52/84] Backed out changeset f3a52e8d6861 (bug 1526875) for Browser-chrome failures. CLOSED TREE --- intl/l10n/FluentSyntax.jsm | 1930 ------------------------------------ intl/l10n/moz.build | 1 - 2 files changed, 1931 deletions(-) delete mode 100644 intl/l10n/FluentSyntax.jsm diff --git a/intl/l10n/FluentSyntax.jsm b/intl/l10n/FluentSyntax.jsm deleted file mode 100644 index 28c349e4af99..000000000000 --- a/intl/l10n/FluentSyntax.jsm +++ /dev/null @@ -1,1930 +0,0 @@ -/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ - -/* Copyright 2019 Mozilla Foundation and others - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/* fluent-syntax@0.10.0 */ - -/* - * Base class for all Fluent AST nodes. - * - * All productions described in the ASDL subclass BaseNode, including Span and - * Annotation. - * - */ -class BaseNode { - constructor() {} -} - -/* - * Base class for AST nodes which can have Spans. - */ -class SyntaxNode extends BaseNode { - addSpan(start, end) { - this.span = new Span(start, end); - } -} - -class Resource extends SyntaxNode { - constructor(body = []) { - super(); - this.type = "Resource"; - this.body = body; - } -} - -/* - * An abstract base class for useful elements of Resource.body. - */ -class Entry extends SyntaxNode {} - -class Message extends Entry { - constructor(id, value = null, attributes = [], comment = null) { - super(); - this.type = "Message"; - this.id = id; - this.value = value; - this.attributes = attributes; - this.comment = comment; - } -} - -class Term extends Entry { - constructor(id, value, attributes = [], comment = null) { - super(); - this.type = "Term"; - this.id = id; - this.value = value; - this.attributes = attributes; - this.comment = comment; - } -} - -class VariantList extends SyntaxNode { - constructor(variants) { - super(); - this.type = "VariantList"; - this.variants = variants; - } -} - -class Pattern extends SyntaxNode { - constructor(elements) { - super(); - this.type = "Pattern"; - this.elements = elements; - } -} - -/* - * An abstract base class for elements of Patterns. - */ -class PatternElement extends SyntaxNode {} - -class TextElement extends PatternElement { - constructor(value) { - super(); - this.type = "TextElement"; - this.value = value; - } -} - -class Placeable extends PatternElement { - constructor(expression) { - super(); - this.type = "Placeable"; - this.expression = expression; - } -} - -/* - * An abstract base class for expressions. - */ -class Expression extends SyntaxNode {} - -class StringLiteral extends Expression { - constructor(raw, value) { - super(); - this.type = "StringLiteral"; - this.raw = raw; - this.value = value; - } -} - -class NumberLiteral extends Expression { - constructor(value) { - super(); - this.type = "NumberLiteral"; - this.value = value; - } -} - -class MessageReference extends Expression { - constructor(id) { - super(); - this.type = "MessageReference"; - this.id = id; - } -} - -class TermReference extends Expression { - constructor(id) { - super(); - this.type = "TermReference"; - this.id = id; - } -} - -class VariableReference extends Expression { - constructor(id) { - super(); - this.type = "VariableReference"; - this.id = id; - } -} - -class FunctionReference extends Expression { - constructor(id) { - super(); - this.type = "FunctionReference"; - this.id = id; - } -} - -class SelectExpression extends Expression { - constructor(selector, variants) { - super(); - this.type = "SelectExpression"; - this.selector = selector; - this.variants = variants; - } -} - -class AttributeExpression extends Expression { - constructor(ref, name) { - super(); - this.type = "AttributeExpression"; - this.ref = ref; - this.name = name; - } -} - -class VariantExpression extends Expression { - constructor(ref, key) { - super(); - this.type = "VariantExpression"; - this.ref = ref; - this.key = key; - } -} - -class CallExpression extends Expression { - constructor(callee, positional = [], named = []) { - super(); - this.type = "CallExpression"; - this.callee = callee; - this.positional = positional; - this.named = named; - } -} - -class Attribute extends SyntaxNode { - constructor(id, value) { - super(); - this.type = "Attribute"; - this.id = id; - this.value = value; - } -} - -class Variant extends SyntaxNode { - constructor(key, value, def = false) { - super(); - this.type = "Variant"; - this.key = key; - this.value = value; - this.default = def; - } -} - -class NamedArgument extends SyntaxNode { - constructor(name, value) { - super(); - this.type = "NamedArgument"; - this.name = name; - this.value = value; - } -} - -class Identifier extends SyntaxNode { - constructor(name) { - super(); - this.type = "Identifier"; - this.name = name; - } -} - -class BaseComment extends Entry { - constructor(content) { - super(); - this.type = "BaseComment"; - this.content = content; - } -} - -class Comment extends BaseComment { - constructor(content) { - super(content); - this.type = "Comment"; - } -} - -class GroupComment extends BaseComment { - constructor(content) { - super(content); - this.type = "GroupComment"; - } -} -class ResourceComment extends BaseComment { - constructor(content) { - super(content); - this.type = "ResourceComment"; - } -} - -class Junk extends SyntaxNode { - constructor(content) { - super(); - this.type = "Junk"; - this.annotations = []; - this.content = content; - } - - addAnnotation(annot) { - this.annotations.push(annot); - } -} - -class Span extends BaseNode { - constructor(start, end) { - super(); - this.type = "Span"; - this.start = start; - this.end = end; - } -} - -class Annotation extends SyntaxNode { - constructor(code, args = [], message) { - super(); - this.type = "Annotation"; - this.code = code; - this.args = args; - this.message = message; - } -} - -const ast = ({ - Resource: Resource, - Entry: Entry, - Message: Message, - Term: Term, - VariantList: VariantList, - Pattern: Pattern, - PatternElement: PatternElement, - TextElement: TextElement, - Placeable: Placeable, - Expression: Expression, - StringLiteral: StringLiteral, - NumberLiteral: NumberLiteral, - MessageReference: MessageReference, - TermReference: TermReference, - VariableReference: VariableReference, - FunctionReference: FunctionReference, - SelectExpression: SelectExpression, - AttributeExpression: AttributeExpression, - VariantExpression: VariantExpression, - CallExpression: CallExpression, - Attribute: Attribute, - Variant: Variant, - NamedArgument: NamedArgument, - Identifier: Identifier, - BaseComment: BaseComment, - Comment: Comment, - GroupComment: GroupComment, - ResourceComment: ResourceComment, - Junk: Junk, - Span: Span, - Annotation: Annotation -}); - -class ParseError extends Error { - constructor(code, ...args) { - super(); - this.code = code; - this.args = args; - this.message = getErrorMessage(code, args); - } -} - -/* eslint-disable complexity */ -function getErrorMessage(code, args) { - switch (code) { - case "E0001": - return "Generic error"; - case "E0002": - return "Expected an entry start"; - case "E0003": { - const [token] = args; - return `Expected token: "${token}"`; - } - case "E0004": { - const [range] = args; - return `Expected a character from range: "${range}"`; - } - case "E0005": { - const [id] = args; - return `Expected message "${id}" to have a value or attributes`; - } - case "E0006": { - const [id] = args; - return `Expected term "-${id}" to have a value`; - } - case "E0007": - return "Keyword cannot end with a whitespace"; - case "E0008": - return "The callee has to be an upper-case identifier or a term"; - case "E0009": - return "The key has to be a simple identifier"; - case "E0010": - return "Expected one of the variants to be marked as default (*)"; - case "E0011": - return 'Expected at least one variant after "->"'; - case "E0012": - return "Expected value"; - case "E0013": - return "Expected variant key"; - case "E0014": - return "Expected literal"; - case "E0015": - return "Only one variant can be marked as default (*)"; - case "E0016": - return "Message references cannot be used as selectors"; - case "E0017": - return "Terms cannot be used as selectors"; - case "E0018": - return "Attributes of messages cannot be used as selectors"; - case "E0019": - return "Attributes of terms cannot be used as placeables"; - case "E0020": - return "Unterminated string expression"; - case "E0021": - return "Positional arguments must not follow named arguments"; - case "E0022": - return "Named arguments must be unique"; - case "E0024": - return "Cannot access variants of a message."; - case "E0025": { - const [char] = args; - return `Unknown escape sequence: \\${char}.`; - } - case "E0026": { - const [sequence] = args; - return `Invalid Unicode escape sequence: ${sequence}.`; - } - case "E0027": - return "Unbalanced closing brace in TextElement."; - case "E0028": - return "Expected an inline expression"; - default: - return code; - } -} - -function includes(arr, elem) { - return arr.indexOf(elem) > -1; -} - -/* eslint no-magic-numbers: "off" */ - -class ParserStream { - constructor(string) { - this.string = string; - this.index = 0; - this.peekOffset = 0; - } - - charAt(offset) { - // When the cursor is at CRLF, return LF but don't move the cursor. - // The cursor still points to the EOL position, which in this case is the - // beginning of the compound CRLF sequence. This ensures slices of - // [inclusive, exclusive) continue to work properly. - if (this.string[offset] === "\r" - && this.string[offset + 1] === "\n") { - return "\n"; - } - - return this.string[offset]; - } - - get currentChar() { - return this.charAt(this.index); - } - - get currentPeek() { - return this.charAt(this.index + this.peekOffset); - } - - next() { - this.peekOffset = 0; - // Skip over the CRLF as if it was a single character. - if (this.string[this.index] === "\r" - && this.string[this.index + 1] === "\n") { - this.index++; - } - this.index++; - return this.string[this.index]; - } - - peek() { - // Skip over the CRLF as if it was a single character. - if (this.string[this.index + this.peekOffset] === "\r" - && this.string[this.index + this.peekOffset + 1] === "\n") { - this.peekOffset++; - } - this.peekOffset++; - return this.string[this.index + this.peekOffset]; - } - - resetPeek(offset = 0) { - this.peekOffset = offset; - } - - skipToPeek() { - this.index += this.peekOffset; - this.peekOffset = 0; - } -} - -const EOL = "\n"; -const EOF = undefined; -const SPECIAL_LINE_START_CHARS = ["}", ".", "[", "*"]; - -class FluentParserStream extends ParserStream { - peekBlankInline() { - const start = this.index + this.peekOffset; - while (this.currentPeek === " ") { - this.peek(); - } - return this.string.slice(start, this.index + this.peekOffset); - } - - skipBlankInline() { - const blank = this.peekBlankInline(); - this.skipToPeek(); - return blank; - } - - peekBlankBlock() { - let blank = ""; - while (true) { - const lineStart = this.peekOffset; - this.peekBlankInline(); - if (this.currentPeek === EOL) { - blank += EOL; - this.peek(); - continue; - } - if (this.currentPeek === EOF) { - // Treat the blank line at EOF as a blank block. - return blank; - } - // Any other char; reset to column 1 on this line. - this.resetPeek(lineStart); - return blank; - } - } - - skipBlankBlock() { - const blank = this.peekBlankBlock(); - this.skipToPeek(); - return blank; - } - - peekBlank() { - while (this.currentPeek === " " || this.currentPeek === EOL) { - this.peek(); - } - } - - skipBlank() { - this.peekBlank(); - this.skipToPeek(); - } - - expectChar(ch) { - if (this.currentChar === ch) { - this.next(); - return true; - } - - throw new ParseError("E0003", ch); - } - - expectLineEnd() { - if (this.currentChar === EOF) { - // EOF is a valid line end in Fluent. - return true; - } - - if (this.currentChar === EOL) { - this.next(); - return true; - } - - // Unicode Character 'SYMBOL FOR NEWLINE' (U+2424) - throw new ParseError("E0003", "\u2424"); - } - - takeChar(f) { - const ch = this.currentChar; - if (ch === EOF) { - return EOF; - } - if (f(ch)) { - this.next(); - return ch; - } - return null; - } - - isCharIdStart(ch) { - if (ch === EOF) { - return false; - } - - const cc = ch.charCodeAt(0); - return (cc >= 97 && cc <= 122) || // a-z - (cc >= 65 && cc <= 90); // A-Z - } - - isIdentifierStart() { - return this.isCharIdStart(this.currentPeek); - } - - isNumberStart() { - const ch = this.currentChar === "-" - ? this.peek() - : this.currentChar; - - if (ch === EOF) { - this.resetPeek(); - return false; - } - - const cc = ch.charCodeAt(0); - const isDigit = cc >= 48 && cc <= 57; // 0-9 - this.resetPeek(); - return isDigit; - } - - isCharPatternContinuation(ch) { - if (ch === EOF) { - return false; - } - - return !includes(SPECIAL_LINE_START_CHARS, ch); - } - - isValueStart() { - // Inline Patterns may start with any char. - const ch = this.currentPeek; - return ch !== EOL && ch !== EOF; - } - - isValueContinuation() { - const column1 = this.peekOffset; - this.peekBlankInline(); - - if (this.currentPeek === "{") { - this.resetPeek(column1); - return true; - } - - if (this.peekOffset - column1 === 0) { - return false; - } - - if (this.isCharPatternContinuation(this.currentPeek)) { - this.resetPeek(column1); - return true; - } - - return false; - } - - // -1 - any - // 0 - comment - // 1 - group comment - // 2 - resource comment - isNextLineComment(level = -1) { - if (this.currentChar !== EOL) { - return false; - } - - let i = 0; - - while (i <= level || (level === -1 && i < 3)) { - if (this.peek() !== "#") { - if (i <= level && level !== -1) { - this.resetPeek(); - return false; - } - break; - } - i++; - } - - // The first char after #, ## or ###. - const ch = this.peek(); - if (ch === " " || ch === EOL) { - this.resetPeek(); - return true; - } - - this.resetPeek(); - return false; - } - - isVariantStart() { - const currentPeekOffset = this.peekOffset; - if (this.currentPeek === "*") { - this.peek(); - } - if (this.currentPeek === "[") { - this.resetPeek(currentPeekOffset); - return true; - } - this.resetPeek(currentPeekOffset); - return false; - } - - isAttributeStart() { - return this.currentPeek === "."; - } - - skipToNextEntryStart(junkStart) { - let lastNewline = this.string.lastIndexOf(EOL, this.index); - if (junkStart < lastNewline) { - // Last seen newline is _after_ the junk start. It's safe to rewind - // without the risk of resuming at the same broken entry. - this.index = lastNewline; - } - while (this.currentChar) { - // We're only interested in beginnings of line. - if (this.currentChar !== EOL) { - this.next(); - continue; - } - - // Break if the first char in this line looks like an entry start. - const first = this.next(); - if (this.isCharIdStart(first) || first === "-" || first === "#") { - break; - } - } - } - - takeIDStart() { - if (this.isCharIdStart(this.currentChar)) { - const ret = this.currentChar; - this.next(); - return ret; - } - - throw new ParseError("E0004", "a-zA-Z"); - } - - takeIDChar() { - const closure = ch => { - const cc = ch.charCodeAt(0); - return ((cc >= 97 && cc <= 122) || // a-z - (cc >= 65 && cc <= 90) || // A-Z - (cc >= 48 && cc <= 57) || // 0-9 - cc === 95 || cc === 45); // _- - }; - - return this.takeChar(closure); - } - - takeDigit() { - const closure = ch => { - const cc = ch.charCodeAt(0); - return (cc >= 48 && cc <= 57); // 0-9 - }; - - return this.takeChar(closure); - } - - takeHexDigit() { - const closure = ch => { - const cc = ch.charCodeAt(0); - return (cc >= 48 && cc <= 57) // 0-9 - || (cc >= 65 && cc <= 70) // A-F - || (cc >= 97 && cc <= 102); // a-f - }; - - return this.takeChar(closure); - } -} - -/* eslint no-magic-numbers: [0] */ - - -const trailingWSRe = /[ \t\n\r]+$/; - - -function withSpan(fn) { - return function(ps, ...args) { - if (!this.withSpans) { - return fn.call(this, ps, ...args); - } - - const start = ps.index; - const node = fn.call(this, ps, ...args); - - // Don't re-add the span if the node already has it. This may happen when - // one decorated function calls another decorated function. - if (node.span) { - return node; - } - - const end = ps.index; - node.addSpan(start, end); - return node; - }; -} - - -class FluentParser { - constructor({ - withSpans = true, - } = {}) { - this.withSpans = withSpans; - - // Poor man's decorators. - const methodNames = [ - "getComment", "getMessage", "getTerm", "getAttribute", "getIdentifier", - "getVariant", "getNumber", "getPattern", "getVariantList", - "getTextElement", "getPlaceable", "getExpression", - "getInlineExpression", "getCallArgument", "getString", - "getSimpleExpression", "getLiteral", - ]; - for (const name of methodNames) { - this[name] = withSpan(this[name]); - } - } - - parse(source) { - const ps = new FluentParserStream(source); - ps.skipBlankBlock(); - - const entries = []; - let lastComment = null; - - while (ps.currentChar) { - const entry = this.getEntryOrJunk(ps); - const blankLines = ps.skipBlankBlock(); - - // Regular Comments require special logic. Comments may be attached to - // Messages or Terms if they are followed immediately by them. However - // they should parse as standalone when they're followed by Junk. - // Consequently, we only attach Comments once we know that the Message - // or the Term parsed successfully. - if (entry.type === "Comment" - && blankLines.length === 0 - && ps.currentChar) { - // Stash the comment and decide what to do with it in the next pass. - lastComment = entry; - continue; - } - - if (lastComment) { - if (entry.type === "Message" || entry.type === "Term") { - entry.comment = lastComment; - if (this.withSpans) { - entry.span.start = entry.comment.span.start; - } - } else { - entries.push(lastComment); - } - // In either case, the stashed comment has been dealt with; clear it. - lastComment = null; - } - - // No special logic for other types of entries. - entries.push(entry); - } - - const res = new Resource(entries); - - if (this.withSpans) { - res.addSpan(0, ps.index); - } - - return res; - } - - /* - * Parse the first Message or Term in `source`. - * - * Skip all encountered comments and start parsing at the first Message or - * Term start. Return Junk if the parsing is not successful. - * - * Preceding comments are ignored unless they contain syntax errors - * themselves, in which case Junk for the invalid comment is returned. - */ - parseEntry(source) { - const ps = new FluentParserStream(source); - ps.skipBlankBlock(); - - while (ps.currentChar === "#") { - const skipped = this.getEntryOrJunk(ps); - if (skipped.type === "Junk") { - // Don't skip Junk comments. - return skipped; - } - ps.skipBlankBlock(); - } - - return this.getEntryOrJunk(ps); - } - - getEntryOrJunk(ps) { - const entryStartPos = ps.index; - - try { - const entry = this.getEntry(ps); - ps.expectLineEnd(); - return entry; - } catch (err) { - if (!(err instanceof ParseError)) { - throw err; - } - - let errorIndex = ps.index; - ps.skipToNextEntryStart(entryStartPos); - const nextEntryStart = ps.index; - if (nextEntryStart < errorIndex) { - // The position of the error must be inside of the Junk's span. - errorIndex = nextEntryStart; - } - - // Create a Junk instance - const slice = ps.string.substring(entryStartPos, nextEntryStart); - const junk = new Junk(slice); - if (this.withSpans) { - junk.addSpan(entryStartPos, nextEntryStart); - } - const annot = new Annotation(err.code, err.args, err.message); - annot.addSpan(errorIndex, errorIndex); - junk.addAnnotation(annot); - return junk; - } - } - - getEntry(ps) { - if (ps.currentChar === "#") { - return this.getComment(ps); - } - - if (ps.currentChar === "-") { - return this.getTerm(ps); - } - - if (ps.isIdentifierStart()) { - return this.getMessage(ps); - } - - throw new ParseError("E0002"); - } - - getComment(ps) { - // 0 - comment - // 1 - group comment - // 2 - resource comment - let level = -1; - let content = ""; - - while (true) { - let i = -1; - while (ps.currentChar === "#" && (i < (level === -1 ? 2 : level))) { - ps.next(); - i++; - } - - if (level === -1) { - level = i; - } - - if (ps.currentChar !== EOL) { - ps.expectChar(" "); - let ch; - while ((ch = ps.takeChar(x => x !== EOL))) { - content += ch; - } - } - - if (ps.isNextLineComment(level)) { - content += ps.currentChar; - ps.next(); - } else { - break; - } - } - - let Comment$$1; - switch (level) { - case 0: - Comment$$1 = Comment; - break; - case 1: - Comment$$1 = GroupComment; - break; - case 2: - Comment$$1 = ResourceComment; - break; - } - return new Comment$$1(content); - } - - getMessage(ps) { - const id = this.getIdentifier(ps); - - ps.skipBlankInline(); - ps.expectChar("="); - - const value = this.maybeGetPattern(ps); - const attrs = this.getAttributes(ps); - - if (value === null && attrs.length === 0) { - throw new ParseError("E0005", id.name); - } - - return new Message(id, value, attrs); - } - - getTerm(ps) { - ps.expectChar("-"); - const id = this.getIdentifier(ps); - - ps.skipBlankInline(); - ps.expectChar("="); - - // Syntax 0.8 compat: VariantLists are supported but deprecated. They can - // only be found as values of Terms. Nested VariantLists are not allowed. - const value = this.maybeGetVariantList(ps) || this.maybeGetPattern(ps); - if (value === null) { - throw new ParseError("E0006", id.name); - } - - const attrs = this.getAttributes(ps); - return new Term(id, value, attrs); - } - - getAttribute(ps) { - ps.expectChar("."); - - const key = this.getIdentifier(ps); - - ps.skipBlankInline(); - ps.expectChar("="); - - const value = this.maybeGetPattern(ps); - if (value === null) { - throw new ParseError("E0012"); - } - - return new Attribute(key, value); - } - - getAttributes(ps) { - const attrs = []; - ps.peekBlank(); - while (ps.isAttributeStart()) { - ps.skipToPeek(); - const attr = this.getAttribute(ps); - attrs.push(attr); - ps.peekBlank(); - } - return attrs; - } - - getIdentifier(ps) { - let name = ps.takeIDStart(); - - let ch; - while ((ch = ps.takeIDChar())) { - name += ch; - } - - return new Identifier(name); - } - - getVariantKey(ps) { - const ch = ps.currentChar; - - if (ch === EOF) { - throw new ParseError("E0013"); - } - - const cc = ch.charCodeAt(0); - - if ((cc >= 48 && cc <= 57) || cc === 45) { // 0-9, - - return this.getNumber(ps); - } - - return this.getIdentifier(ps); - } - - getVariant(ps, {hasDefault}) { - let defaultIndex = false; - - if (ps.currentChar === "*") { - if (hasDefault) { - throw new ParseError("E0015"); - } - ps.next(); - defaultIndex = true; - } - - ps.expectChar("["); - - ps.skipBlank(); - - const key = this.getVariantKey(ps); - - ps.skipBlank(); - ps.expectChar("]"); - - const value = this.maybeGetPattern(ps); - if (value === null) { - throw new ParseError("E0012"); - } - - return new Variant(key, value, defaultIndex); - } - - getVariants(ps) { - const variants = []; - let hasDefault = false; - - ps.skipBlank(); - while (ps.isVariantStart()) { - const variant = this.getVariant(ps, {hasDefault}); - - if (variant.default) { - hasDefault = true; - } - - variants.push(variant); - ps.expectLineEnd(); - ps.skipBlank(); - } - - if (variants.length === 0) { - throw new ParseError("E0011"); - } - - if (!hasDefault) { - throw new ParseError("E0010"); - } - - return variants; - } - - getDigits(ps) { - let num = ""; - - let ch; - while ((ch = ps.takeDigit())) { - num += ch; - } - - if (num.length === 0) { - throw new ParseError("E0004", "0-9"); - } - - return num; - } - - getNumber(ps) { - let num = ""; - - if (ps.currentChar === "-") { - num += "-"; - ps.next(); - } - - num = `${num}${this.getDigits(ps)}`; - - if (ps.currentChar === ".") { - num += "."; - ps.next(); - num = `${num}${this.getDigits(ps)}`; - } - - return new NumberLiteral(num); - } - - // maybeGetPattern distinguishes between patterns which start on the same line - // as the identifier (a.k.a. inline signleline patterns and inline multiline - // patterns) and patterns which start on a new line (a.k.a. block multiline - // patterns). The distinction is important for the dedentation logic: the - // indent of the first line of a block pattern must be taken into account when - // calculating the maximum common indent. - maybeGetPattern(ps) { - ps.peekBlankInline(); - if (ps.isValueStart()) { - ps.skipToPeek(); - return this.getPattern(ps, {isBlock: false}); - } - - ps.peekBlankBlock(); - if (ps.isValueContinuation()) { - ps.skipToPeek(); - return this.getPattern(ps, {isBlock: true}); - } - - return null; - } - - // Deprecated in Syntax 0.8. VariantLists are only allowed as values of Terms. - // Values of Messages, Attributes and Variants must be Patterns. This method - // is only used in getTerm. - maybeGetVariantList(ps) { - ps.peekBlank(); - if (ps.currentPeek === "{") { - const start = ps.peekOffset; - ps.peek(); - ps.peekBlankInline(); - if (ps.currentPeek === EOL) { - ps.peekBlank(); - if (ps.isVariantStart()) { - ps.resetPeek(start); - ps.skipToPeek(); - return this.getVariantList(ps); - } - } - } - - ps.resetPeek(); - return null; - } - - getVariantList(ps) { - ps.expectChar("{"); - var variants = this.getVariants(ps); - ps.expectChar("}"); - return new VariantList(variants); - } - - getPattern(ps, {isBlock}) { - const elements = []; - if (isBlock) { - // A block pattern is a pattern which starts on a new line. Store and - // measure the indent of this first line for the dedentation logic. - const blankStart = ps.index; - const firstIndent = ps.skipBlankInline(); - elements.push(this.getIndent(ps, firstIndent, blankStart)); - var commonIndentLength = firstIndent.length; - } else { - var commonIndentLength = Infinity; - } - - let ch; - elements: while ((ch = ps.currentChar)) { - switch (ch) { - case EOL: { - const blankStart = ps.index; - const blankLines = ps.peekBlankBlock(); - if (ps.isValueContinuation()) { - ps.skipToPeek(); - const indent = ps.skipBlankInline(); - commonIndentLength = Math.min(commonIndentLength, indent.length); - elements.push(this.getIndent(ps, blankLines + indent, blankStart)); - continue elements; - } - - // The end condition for getPattern's while loop is a newline - // which is not followed by a valid pattern continuation. - ps.resetPeek(); - break elements; - } - case "{": - elements.push(this.getPlaceable(ps)); - continue elements; - case "}": - throw new ParseError("E0027"); - default: - const element = this.getTextElement(ps); - elements.push(element); - } - } - - const dedented = this.dedent(elements, commonIndentLength); - return new Pattern(dedented); - } - - // Create a token representing an indent. It's not part of the AST and it will - // be trimmed and merged into adjacent TextElements, or turned into a new - // TextElement, if it's surrounded by two Placeables. - getIndent(ps, value, start) { - return { - type: "Indent", - span: {start, end: ps.index}, - value, - }; - } - - // Dedent a list of elements by removing the maximum common indent from the - // beginning of text lines. The common indent is calculated in getPattern. - dedent(elements, commonIndent) { - const trimmed = []; - - for (let element of elements) { - if (element.type === "Placeable") { - trimmed.push(element); - continue; - } - - if (element.type === "Indent") { - // Strip common indent. - element.value = element.value.slice( - 0, element.value.length - commonIndent); - if (element.value.length === 0) { - continue; - } - } - - let prev = trimmed[trimmed.length - 1]; - if (prev && prev.type === "TextElement") { - // Join adjacent TextElements by replacing them with their sum. - const sum = new TextElement(prev.value + element.value); - if (this.withSpans) { - sum.addSpan(prev.span.start, element.span.end); - } - trimmed[trimmed.length - 1] = sum; - continue; - } - - if (element.type === "Indent") { - // If the indent hasn't been merged into a preceding TextElement, - // convert it into a new TextElement. - const textElement = new TextElement(element.value); - if (this.withSpans) { - textElement.addSpan(element.span.start, element.span.end); - } - element = textElement; - } - - trimmed.push(element); - } - - // Trim trailing whitespace from the Pattern. - const lastElement = trimmed[trimmed.length - 1]; - if (lastElement.type === "TextElement") { - lastElement.value = lastElement.value.replace(trailingWSRe, ""); - if (lastElement.value.length === 0) { - trimmed.pop(); - } - } - - return trimmed; - } - - getTextElement(ps) { - let buffer = ""; - - let ch; - while ((ch = ps.currentChar)) { - if (ch === "{" || ch === "}") { - return new TextElement(buffer); - } - - if (ch === EOL) { - return new TextElement(buffer); - } - - buffer += ch; - ps.next(); - } - - return new TextElement(buffer); - } - - getEscapeSequence(ps) { - const next = ps.currentChar; - - switch (next) { - case "\\": - case "\"": - ps.next(); - return [`\\${next}`, next]; - case "u": - return this.getUnicodeEscapeSequence(ps, next, 4); - case "U": - return this.getUnicodeEscapeSequence(ps, next, 6); - default: - throw new ParseError("E0025", next); - } - } - - getUnicodeEscapeSequence(ps, u, digits) { - ps.expectChar(u); - - let sequence = ""; - for (let i = 0; i < digits; i++) { - const ch = ps.takeHexDigit(); - - if (!ch) { - throw new ParseError( - "E0026", `\\${u}${sequence}${ps.currentChar}`); - } - - sequence += ch; - } - - const codepoint = parseInt(sequence, 16); - const unescaped = codepoint <= 0xD7FF || 0xE000 <= codepoint - // It's a Unicode scalar value. - ? String.fromCodePoint(codepoint) - // Escape sequences reresenting surrogate code points are well-formed - // but invalid in Fluent. Replace them with U+FFFD REPLACEMENT - // CHARACTER. - : "�"; - return [`\\${u}${sequence}`, unescaped]; - } - - getPlaceable(ps) { - ps.expectChar("{"); - ps.skipBlank(); - const expression = this.getExpression(ps); - ps.expectChar("}"); - return new Placeable(expression); - } - - getExpression(ps) { - const selector = this.getInlineExpression(ps); - ps.skipBlank(); - - if (ps.currentChar === "-") { - if (ps.peek() !== ">") { - ps.resetPeek(); - return selector; - } - - if (selector.type === "MessageReference") { - throw new ParseError("E0016"); - } - - if (selector.type === "AttributeExpression" - && selector.ref.type === "MessageReference") { - throw new ParseError("E0018"); - } - - if (selector.type === "TermReference" - || selector.type === "VariantExpression") { - throw new ParseError("E0017"); - } - - if (selector.type === "CallExpression" - && selector.callee.type === "TermReference") { - throw new ParseError("E0017"); - } - - ps.next(); - ps.next(); - - ps.skipBlankInline(); - ps.expectLineEnd(); - - const variants = this.getVariants(ps); - return new SelectExpression(selector, variants); - } - - if (selector.type === "AttributeExpression" - && selector.ref.type === "TermReference") { - throw new ParseError("E0019"); - } - - if (selector.type === "CallExpression" - && selector.callee.type === "AttributeExpression") { - throw new ParseError("E0019"); - } - - return selector; - } - - getInlineExpression(ps) { - if (ps.currentChar === "{") { - return this.getPlaceable(ps); - } - - let expr = this.getSimpleExpression(ps); - switch (expr.type) { - case "NumberLiteral": - case "StringLiteral": - case "VariableReference": - return expr; - case "MessageReference": { - if (ps.currentChar === ".") { - ps.next(); - const attr = this.getIdentifier(ps); - return new AttributeExpression(expr, attr); - } - - if (ps.currentChar === "(") { - // It's a Function. Ensure it's all upper-case. - if (!/^[A-Z][A-Z_?-]*$/.test(expr.id.name)) { - throw new ParseError("E0008"); - } - - const func = new FunctionReference(expr.id); - if (this.withSpans) { - func.addSpan(expr.span.start, expr.span.end); - } - return new CallExpression(func, ...this.getCallArguments(ps)); - } - - return expr; - } - case "TermReference": { - if (ps.currentChar === "[") { - ps.next(); - const key = this.getVariantKey(ps); - ps.expectChar("]"); - return new VariantExpression(expr, key); - } - - if (ps.currentChar === ".") { - ps.next(); - const attr = this.getIdentifier(ps); - expr = new AttributeExpression(expr, attr); - } - - if (ps.currentChar === "(") { - return new CallExpression(expr, ...this.getCallArguments(ps)); - } - - return expr; - } - default: - throw new ParseError("E0028"); - } - } - - getSimpleExpression(ps) { - if (ps.isNumberStart()) { - return this.getNumber(ps); - } - - if (ps.currentChar === '"') { - return this.getString(ps); - } - - if (ps.currentChar === "$") { - ps.next(); - const id = this.getIdentifier(ps); - return new VariableReference(id); - } - - if (ps.currentChar === "-") { - ps.next(); - const id = this.getIdentifier(ps); - return new TermReference(id); - } - - if (ps.isIdentifierStart()) { - const id = this.getIdentifier(ps); - return new MessageReference(id); - } - - throw new ParseError("E0028"); - } - - getCallArgument(ps) { - const exp = this.getInlineExpression(ps); - - ps.skipBlank(); - - if (ps.currentChar !== ":") { - return exp; - } - - if (exp.type !== "MessageReference") { - throw new ParseError("E0009"); - } - - ps.next(); - ps.skipBlank(); - - const value = this.getLiteral(ps); - return new NamedArgument(exp.id, value); - } - - getCallArguments(ps) { - const positional = []; - const named = []; - const argumentNames = new Set(); - - ps.expectChar("("); - ps.skipBlank(); - - while (true) { - if (ps.currentChar === ")") { - break; - } - - const arg = this.getCallArgument(ps); - if (arg.type === "NamedArgument") { - if (argumentNames.has(arg.name.name)) { - throw new ParseError("E0022"); - } - named.push(arg); - argumentNames.add(arg.name.name); - } else if (argumentNames.size > 0) { - throw new ParseError("E0021"); - } else { - positional.push(arg); - } - - ps.skipBlank(); - - if (ps.currentChar === ",") { - ps.next(); - ps.skipBlank(); - continue; - } - - break; - } - - ps.expectChar(")"); - return [positional, named]; - } - - getString(ps) { - let raw = ""; - let value = ""; - - ps.expectChar("\""); - - let ch; - while ((ch = ps.takeChar(x => x !== '"' && x !== EOL))) { - if (ch === "\\") { - const [sequence, unescaped] = this.getEscapeSequence(ps); - raw += sequence; - value += unescaped; - } else { - raw += ch; - value += ch; - } - } - - if (ps.currentChar === EOL) { - throw new ParseError("E0020"); - } - - ps.expectChar("\""); - - return new StringLiteral(raw, value); - } - - getLiteral(ps) { - if (ps.isNumberStart()) { - return this.getNumber(ps); - } - - if (ps.currentChar === '"') { - return this.getString(ps); - } - - throw new ParseError("E0014"); - } -} - -function indent(content) { - return content.split("\n").join("\n "); -} - -function includesNewLine(elem) { - return elem.type === "TextElement" && includes(elem.value, "\n"); -} - -function isSelectExpr(elem) { - return elem.type === "Placeable" - && elem.expression.type === "SelectExpression"; -} - -// Bit masks representing the state of the serializer. -const HAS_ENTRIES = 1; - -class FluentSerializer { - constructor({ withJunk = false } = {}) { - this.withJunk = withJunk; - } - - serialize(resource) { - if (resource.type !== "Resource") { - throw new Error(`Unknown resource type: ${resource.type}`); - } - - let state = 0; - const parts = []; - - for (const entry of resource.body) { - if (entry.type !== "Junk" || this.withJunk) { - parts.push(this.serializeEntry(entry, state)); - if (!(state & HAS_ENTRIES)) { - state |= HAS_ENTRIES; - } - } - } - - return parts.join(""); - } - - serializeEntry(entry, state = 0) { - switch (entry.type) { - case "Message": - return serializeMessage(entry); - case "Term": - return serializeTerm(entry); - case "Comment": - if (state & HAS_ENTRIES) { - return `\n${serializeComment(entry, "#")}\n`; - } - return `${serializeComment(entry, "#")}\n`; - case "GroupComment": - if (state & HAS_ENTRIES) { - return `\n${serializeComment(entry, "##")}\n`; - } - return `${serializeComment(entry, "##")}\n`; - case "ResourceComment": - if (state & HAS_ENTRIES) { - return `\n${serializeComment(entry, "###")}\n`; - } - return `${serializeComment(entry, "###")}\n`; - case "Junk": - return serializeJunk(entry); - default : - throw new Error(`Unknown entry type: ${entry.type}`); - } - } - - serializeExpression(expr) { - return serializeExpression(expr); - } -} - - -function serializeComment(comment, prefix = "#") { - const prefixed = comment.content.split("\n").map( - line => line.length ? `${prefix} ${line}` : prefix - ).join("\n"); - // Add the trailing newline. - return `${prefixed}\n`; -} - - -function serializeJunk(junk) { - return junk.content; -} - - -function serializeMessage(message) { - const parts = []; - - if (message.comment) { - parts.push(serializeComment(message.comment)); - } - - parts.push(`${message.id.name} =`); - - if (message.value) { - parts.push(serializeValue(message.value)); - } - - for (const attribute of message.attributes) { - parts.push(serializeAttribute(attribute)); - } - - parts.push("\n"); - return parts.join(""); -} - - -function serializeTerm(term) { - const parts = []; - - if (term.comment) { - parts.push(serializeComment(term.comment)); - } - - parts.push(`-${term.id.name} =`); - parts.push(serializeValue(term.value)); - - for (const attribute of term.attributes) { - parts.push(serializeAttribute(attribute)); - } - - parts.push("\n"); - return parts.join(""); -} - - -function serializeAttribute(attribute) { - const value = indent(serializeValue(attribute.value)); - return `\n .${attribute.id.name} =${value}`; -} - - -function serializeValue(value) { - switch (value.type) { - case "Pattern": - return serializePattern(value); - case "VariantList": - return serializeVariantList(value); - default: - throw new Error(`Unknown value type: ${value.type}`); - } -} - - -function serializePattern(pattern) { - const content = pattern.elements.map(serializeElement).join(""); - const startOnNewLine = - pattern.elements.some(isSelectExpr) || - pattern.elements.some(includesNewLine); - - if (startOnNewLine) { - return `\n ${indent(content)}`; - } - - return ` ${content}`; -} - - -function serializeVariantList(varlist) { - const content = varlist.variants.map(serializeVariant).join(""); - return `\n {${indent(content)}\n }`; -} - - -function serializeVariant(variant) { - const key = serializeVariantKey(variant.key); - const value = indent(serializeValue(variant.value)); - - if (variant.default) { - return `\n *[${key}]${value}`; - } - - return `\n [${key}]${value}`; -} - - -function serializeElement(element) { - switch (element.type) { - case "TextElement": - return element.value; - case "Placeable": - return serializePlaceable(element); - default: - throw new Error(`Unknown element type: ${element.type}`); - } -} - - -function serializePlaceable(placeable) { - const expr = placeable.expression; - - switch (expr.type) { - case "Placeable": - return `{${serializePlaceable(expr)}}`; - case "SelectExpression": - // Special-case select expression to control the whitespace around the - // opening and the closing brace. - return `{ ${serializeSelectExpression(expr)}}`; - default: - return `{ ${serializeExpression(expr)} }`; - } -} - - -function serializeExpression(expr) { - switch (expr.type) { - case "StringLiteral": - return `"${expr.raw}"`; - case "NumberLiteral": - return expr.value; - case "MessageReference": - case "FunctionReference": - return expr.id.name; - case "TermReference": - return `-${expr.id.name}`; - case "VariableReference": - return `$${expr.id.name}`; - case "AttributeExpression": - return serializeAttributeExpression(expr); - case "VariantExpression": - return serializeVariantExpression(expr); - case "CallExpression": - return serializeCallExpression(expr); - case "SelectExpression": - return serializeSelectExpression(expr); - case "Placeable": - return serializePlaceable(expr); - default: - throw new Error(`Unknown expression type: ${expr.type}`); - } -} - - -function serializeSelectExpression(expr) { - const parts = []; - const selector = `${serializeExpression(expr.selector)} ->`; - parts.push(selector); - - for (const variant of expr.variants) { - parts.push(serializeVariant(variant)); - } - - parts.push("\n"); - return parts.join(""); -} - - -function serializeAttributeExpression(expr) { - const ref = serializeExpression(expr.ref); - return `${ref}.${expr.name.name}`; -} - - -function serializeVariantExpression(expr) { - const ref = serializeExpression(expr.ref); - const key = serializeVariantKey(expr.key); - return `${ref}[${key}]`; -} - - -function serializeCallExpression(expr) { - const callee = serializeExpression(expr.callee); - const positional = expr.positional.map(serializeExpression).join(", "); - const named = expr.named.map(serializeNamedArgument).join(", "); - if (expr.positional.length > 0 && expr.named.length > 0) { - return `${callee}(${positional}, ${named})`; - } - return `${callee}(${positional || named})`; -} - - -function serializeNamedArgument(arg) { - const value = serializeExpression(arg.value); - return `${arg.name.name}: ${value}`; -} - - -function serializeVariantKey(key) { - switch (key.type) { - case "Identifier": - return key.name; - default: - return serializeExpression(key); - } -} - -/* eslint object-shorthand: "off", - no-unused-vars: "off", - no-redeclare: "off", - comma-dangle: "off", - no-labels: "off" */ - -this.EXPORTED_SYMBOLS = [ - "FluentParser", - "FluentSerializer", - ...Object.keys(ast), -]; diff --git a/intl/l10n/moz.build b/intl/l10n/moz.build index 719e89ed6196..85be6e0f9ce7 100644 --- a/intl/l10n/moz.build +++ b/intl/l10n/moz.build @@ -7,7 +7,6 @@ EXTRA_JS_MODULES += [ 'DOMLocalization.jsm', 'Fluent.jsm', - 'FluentSyntax.jsm', 'L10nRegistry.jsm', 'Localization.jsm', ] From 72ca9e0f17cc4312ed9866b02196b95e0f0c45c4 Mon Sep 17 00:00:00 2001 From: Dorel Luca Date: Thu, 14 Feb 2019 20:44:38 +0200 Subject: [PATCH 53/84] Backed out changeset fe264afc03aa (bug 1511224) for Fetch failures. CLOSED TREE --- build/mozconfig.common | 1 - build/mozconfig.nasm | 11 --------- media/ffvpx/config_win64.asm | 2 +- taskcluster/ci/build/windows.yml | 33 -------------------------- taskcluster/ci/fetch/toolchains.yml | 8 ------- taskcluster/ci/toolchain/clang.yml | 2 +- taskcluster/ci/toolchain/kind.yml | 1 - taskcluster/ci/toolchain/nasm.yml | 18 -------------- taskcluster/scripts/misc/build-nasm.sh | 25 ------------------- 9 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 build/mozconfig.nasm delete mode 100644 taskcluster/ci/toolchain/nasm.yml delete mode 100755 taskcluster/scripts/misc/build-nasm.sh diff --git a/build/mozconfig.common b/build/mozconfig.common index 2951948a18dd..308795ff549c 100644 --- a/build/mozconfig.common +++ b/build/mozconfig.common @@ -19,7 +19,6 @@ MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0} ac_add_options --enable-js-shell -. "$topsrcdir/build/mozconfig.nasm" . "$topsrcdir/build/mozconfig.node" . "$topsrcdir/build/mozconfig.automation" . "$topsrcdir/build/mozconfig.rust" diff --git a/build/mozconfig.nasm b/build/mozconfig.nasm deleted file mode 100644 index 9db9ba2b0303..000000000000 --- a/build/mozconfig.nasm +++ /dev/null @@ -1,11 +0,0 @@ -# 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/. - -case "$(uname -s)" in -MINGW*) - export NASM=$topsrcdir/nasm/nasm.exe - ;; -*) - ;; -esac diff --git a/media/ffvpx/config_win64.asm b/media/ffvpx/config_win64.asm index 64e1c6dfb62d..fecfee4988a5 100644 --- a/media/ffvpx/config_win64.asm +++ b/media/ffvpx/config_win64.asm @@ -54,7 +54,7 @@ %define HAVE_SSE42 1 %define HAVE_SSSE3 1 %define HAVE_XOP 1 -%define HAVE_CPUNOP 0 +%define HAVE_CPUNOP 1 %define HAVE_I686 1 %define HAVE_MIPSFPU 0 %define HAVE_MIPS32R2 0 diff --git a/taskcluster/ci/build/windows.yml b/taskcluster/ci/build/windows.yml index 9063ccd89bfb..89aba43c7cd6 100755 --- a/taskcluster/ci/build/windows.yml +++ b/taskcluster/ci/build/windows.yml @@ -34,7 +34,6 @@ win32/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32/opt: @@ -68,7 +67,6 @@ win32/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32/pgo: @@ -102,7 +100,6 @@ win32/pgo: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64/debug: @@ -136,7 +133,6 @@ win64/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-fuzzing/debug: @@ -172,7 +168,6 @@ win64-fuzzing/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-plain/debug: @@ -206,7 +201,6 @@ win64-plain/debug: - win64-clang-cl - win64-rust - win64-node - - win64-nasm - win64-cbindgen win64/opt: @@ -240,7 +234,6 @@ win64/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-plain/opt: @@ -274,7 +267,6 @@ win64-plain/opt: toolchains: - win64-clang-cl - win64-rust - - win64-nasm - win64-node - win64-cbindgen @@ -322,7 +314,6 @@ win32-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-nightly/opt: @@ -362,7 +353,6 @@ win64-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64/pgo: @@ -396,7 +386,6 @@ win64/pgo: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-add-on-devel/opt: @@ -430,7 +419,6 @@ win32-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-add-on-devel/opt: @@ -464,7 +452,6 @@ win64-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-noopt/debug: @@ -497,7 +484,6 @@ win64-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-noopt/debug: @@ -530,7 +516,6 @@ win32-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-rusttests/opt: @@ -568,7 +553,6 @@ win32-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-rusttests/debug: @@ -606,7 +590,6 @@ win32-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-rusttests/opt: @@ -639,7 +622,6 @@ win64-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-rusttests/debug: @@ -672,7 +654,6 @@ win64-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-ccov/debug: @@ -709,7 +690,6 @@ win64-ccov/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node fetches: toolchain: @@ -746,7 +726,6 @@ win64-asan/debug: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-asan/opt: @@ -781,7 +760,6 @@ win64-asan/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-asan-reporter-nightly/opt: @@ -824,7 +802,6 @@ win64-asan-reporter-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-asan-fuzzing/opt: @@ -858,7 +835,6 @@ win64-asan-fuzzing/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-devedition-nightly/opt: @@ -906,7 +882,6 @@ win32-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-devedition-nightly/opt: @@ -947,7 +922,6 @@ win64-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-msvc/debug: @@ -979,7 +953,6 @@ win32-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-msvc/opt: @@ -1012,7 +985,6 @@ win32-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-msvc/debug: @@ -1044,7 +1016,6 @@ win64-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-msvc/opt: @@ -1077,7 +1048,6 @@ win64-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-aarch64/debug: @@ -1113,7 +1083,6 @@ win64-aarch64/debug: - win64-aarch64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-aarch64/opt: @@ -1149,7 +1118,6 @@ win64-aarch64/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win64-aarch64-nightly/opt: @@ -1189,7 +1157,6 @@ win64-aarch64-nightly/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache - - win64-nasm - win64-node win32-mingwclang/opt: diff --git a/taskcluster/ci/fetch/toolchains.yml b/taskcluster/ci/fetch/toolchains.yml index 505d3167aa9a..c67fa0de1c63 100644 --- a/taskcluster/ci/fetch/toolchains.yml +++ b/taskcluster/ci/fetch/toolchains.yml @@ -173,14 +173,6 @@ mpfr-3.1.5: sig-url: "{url}.asc" key-path: build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key -nasm-2.14.02: - description: nasm 2.14.02 source code - fetch: - type: static-url - url: https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.xz - sha256: e24ade3e928f7253aa8c14aa44726d1edf3f98643f87c9d72ec1df44b26be8f5 - size: 827620 - wix-3.1.1: description: wix 3.1.1 binary release # WIX doesn't use a wrapping toplevel DIR, so we should really repackage it when diff --git a/taskcluster/ci/toolchain/clang.yml b/taskcluster/ci/toolchain/clang.yml index a68385e362de..af6ef32554a8 100644 --- a/taskcluster/ci/toolchain/clang.yml +++ b/taskcluster/ci/toolchain/clang.yml @@ -60,7 +60,7 @@ linux64-clang-trunk-mingw-x64: description: "MinGW-Clang Trunk x64 toolchain build" treeherder: symbol: TMW(clang-x64) - tier: 1 + tier: 2 run: script: build-clang-trunk-mingw.sh arguments: [ diff --git a/taskcluster/ci/toolchain/kind.yml b/taskcluster/ci/toolchain/kind.yml index 57af10e234c1..2e7ce5b92da5 100644 --- a/taskcluster/ci/toolchain/kind.yml +++ b/taskcluster/ci/toolchain/kind.yml @@ -35,7 +35,6 @@ jobs-from: - mingw.yml - minidump_stackwalk.yml - misc.yml - - nasm.yml - node.yml - rust.yml - rust-size.yml diff --git a/taskcluster/ci/toolchain/nasm.yml b/taskcluster/ci/toolchain/nasm.yml deleted file mode 100644 index 5313ac6a5196..000000000000 --- a/taskcluster/ci/toolchain/nasm.yml +++ /dev/null @@ -1,18 +0,0 @@ -win64-nasm: - description: "nasm win64 build" - treeherder: - symbol: TW64(nasm) - worker-type: aws-provisioner-v1/gecko-{level}-b-linux - worker: - docker-image: {in-tree: mingw32-build} - max-run-time: 1800 - run: - script: build-nasm.sh - resources: - - 'taskcluster/scripts/misc/tooltool-download.sh' - toolchain-artifact: public/build/nasm.tar.bz2 - toolchains: - - linux64-clang-trunk-mingw-x64 - fetches: - fetch: - - nasm-2.14.02 diff --git a/taskcluster/scripts/misc/build-nasm.sh b/taskcluster/scripts/misc/build-nasm.sh deleted file mode 100755 index c7673ea20cbb..000000000000 --- a/taskcluster/scripts/misc/build-nasm.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -x -e -v - -case "$(uname -s)" in - Linux) - WORKSPACE=$HOME/workspace - UPLOAD_DIR=$HOME/artifacts - COMPRESS_EXT=bz2 - ;; -esac - -cd $WORKSPACE/build/src - -. taskcluster/scripts/misc/tooltool-download.sh -export PATH="$WORKSPACE/build/src/clang/bin:$PATH" - -cd $WORKSPACE/build/nasm-2.14.02 -./configure CC=x86_64-w64-mingw32-clang AR=llvm-ar RANLIB=llvm-ranlib --host=x86_64-w64-mingw32 -make -j$(nproc) - -mkdir nasm -mv nasm.exe nasm/ -tar -acf nasm.tar.$COMPRESS_EXT nasm -mkdir -p "$UPLOAD_DIR" -cp nasm.tar.$COMPRESS_EXT "$UPLOAD_DIR" From 67115dd61baffb913ab76606c1789a34ac25c244 Mon Sep 17 00:00:00 2001 From: Dorel Luca Date: Thu, 14 Feb 2019 20:45:26 +0200 Subject: [PATCH 54/84] Backed out changeset 2d4b8d90cbd7 (bug 1400344) for Spider monkey failrues. CLOSED TREE --HG-- rename : ipc/mscom/ApartmentRegion.h => ipc/mscom/COMApartmentRegion.h rename : ipc/mscom/ProcessRuntime.cpp => ipc/mscom/MainThreadRuntime.cpp rename : ipc/mscom/ProcessRuntime.h => ipc/mscom/MainThreadRuntime.h --- accessible/windows/msaa/LazyInstantiator.cpp | 4 +- browser/app/winlauncher/LaunchUnelevated.cpp | 2 +- dom/ipc/ContentProcess.h | 4 +- dom/media/ipc/RDDProcessImpl.h | 2 +- dom/plugins/ipc/PluginProcessChild.h | 4 +- gfx/ipc/GPUProcessImpl.h | 4 +- ipc/mscom/ApartmentRegion.h | 94 -------- ipc/mscom/COMApartmentRegion.h | 53 +++++ ipc/mscom/EnsureMTA.h | 1 + ipc/mscom/MainThreadClientInfo.cpp | 133 +++++++++++ ipc/mscom/MainThreadClientInfo.h | 52 +++++ ...ocessRuntime.cpp => MainThreadRuntime.cpp} | 213 ++++++++---------- ipc/mscom/MainThreadRuntime.h | 58 +++++ ipc/mscom/ProcessRuntime.h | 61 ----- ipc/mscom/Ptr.h | 2 - ipc/mscom/moz.build | 12 +- ipc/mscom/mozglue/ProcessRuntimeShared.cpp | 33 --- ipc/mscom/mozglue/ProcessRuntimeShared.h | 54 ----- ipc/mscom/mozglue/moz.build | 21 -- mozglue/build/moz.build | 3 - toolkit/xre/nsAppRunner.cpp | 4 +- widget/windows/JumpListBuilder.cpp | 2 +- 22 files changed, 404 insertions(+), 412 deletions(-) delete mode 100644 ipc/mscom/ApartmentRegion.h create mode 100644 ipc/mscom/COMApartmentRegion.h create mode 100644 ipc/mscom/MainThreadClientInfo.cpp create mode 100644 ipc/mscom/MainThreadClientInfo.h rename ipc/mscom/{ProcessRuntime.cpp => MainThreadRuntime.cpp} (52%) create mode 100644 ipc/mscom/MainThreadRuntime.h delete mode 100644 ipc/mscom/ProcessRuntime.h delete mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.cpp delete mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.h delete mode 100644 ipc/mscom/mozglue/moz.build diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp index a82a2738d446..f376e40d1621 100644 --- a/accessible/windows/msaa/LazyInstantiator.cpp +++ b/accessible/windows/msaa/LazyInstantiator.cpp @@ -11,7 +11,7 @@ #include "mozilla/a11y/Compatibility.h" #include "mozilla/a11y/Platform.h" #include "mozilla/Assertions.h" -#include "mozilla/mscom/ProcessRuntime.h" +#include "mozilla/mscom/MainThreadRuntime.h" #include "mozilla/mscom/Registration.h" #include "mozilla/UniquePtr.h" #include "nsAccessibilityService.h" @@ -313,7 +313,7 @@ LazyInstantiator::MaybeResolveRoot() { } if (GetAccService() || - ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) { + ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) { mWeakRootAccWrap = ResolveRootAccWrap(); if (!mWeakRootAccWrap) { return E_POINTER; diff --git a/browser/app/winlauncher/LaunchUnelevated.cpp b/browser/app/winlauncher/LaunchUnelevated.cpp index 38ee8e66986b..b0ba54df7908 100644 --- a/browser/app/winlauncher/LaunchUnelevated.cpp +++ b/browser/app/winlauncher/LaunchUnelevated.cpp @@ -9,7 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/LauncherResult.h" -#include "mozilla/mscom/ApartmentRegion.h" +#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/RefPtr.h" #include "nsWindowsHelpers.h" diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h index c6b2a58684b8..eb9a908328dd 100644 --- a/dom/ipc/ContentProcess.h +++ b/dom/ipc/ContentProcess.h @@ -12,7 +12,7 @@ #include "ContentChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/ProcessRuntime.h" +# include "mozilla/mscom/MainThreadRuntime.h" #endif namespace mozilla { @@ -39,7 +39,7 @@ class ContentProcess : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::ProcessRuntime mCOMRuntime; + mozilla::mscom::MainThreadRuntime mCOMRuntime; #endif DISALLOW_EVIL_CONSTRUCTORS(ContentProcess); diff --git a/dom/media/ipc/RDDProcessImpl.h b/dom/media/ipc/RDDProcessImpl.h index 8c044132da34..a75f1934758e 100644 --- a/dom/media/ipc/RDDProcessImpl.h +++ b/dom/media/ipc/RDDProcessImpl.h @@ -8,7 +8,7 @@ #include "mozilla/ipc/ProcessChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/ProcessRuntime.h" +# include "mozilla/mscom/MainThreadRuntime.h" #endif #include "RDDParent.h" diff --git a/dom/plugins/ipc/PluginProcessChild.h b/dom/plugins/ipc/PluginProcessChild.h index b715f0d649a0..48d3bc066a76 100644 --- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -11,7 +11,7 @@ #include "mozilla/plugins/PluginModuleChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/ProcessRuntime.h" +# include "mozilla/mscom/MainThreadRuntime.h" #endif namespace mozilla { @@ -40,7 +40,7 @@ class PluginProcessChild : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) /* Drag-and-drop depends on the host initializing COM. * This object initializes and configures COM. */ - mozilla::mscom::ProcessRuntime mCOMRuntime; + mozilla::mscom::MainThreadRuntime mCOMRuntime; #endif PluginModuleChild mPlugin; diff --git a/gfx/ipc/GPUProcessImpl.h b/gfx/ipc/GPUProcessImpl.h index a205e2b2333b..a76aeb406b33 100644 --- a/gfx/ipc/GPUProcessImpl.h +++ b/gfx/ipc/GPUProcessImpl.h @@ -10,7 +10,7 @@ #include "GPUParent.h" #if defined(XP_WIN) -# include "mozilla/mscom/ProcessRuntime.h" +# include "mozilla/mscom/MainThreadRuntime.h" #endif namespace mozilla { @@ -33,7 +33,7 @@ class GPUProcessImpl final : public ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::ProcessRuntime mCOMRuntime; + mozilla::mscom::MainThreadRuntime mCOMRuntime; #endif }; diff --git a/ipc/mscom/ApartmentRegion.h b/ipc/mscom/ApartmentRegion.h deleted file mode 100644 index dc56e3fc9676..000000000000 --- a/ipc/mscom/ApartmentRegion.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_ApartmentRegion_h -#define mozilla_mscom_ApartmentRegion_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include - -namespace mozilla { -namespace mscom { - -class MOZ_NON_TEMPORARY_CLASS ApartmentRegion { - public: - /** - * This constructor is to be used when we want to instantiate the object but - * we do not yet know which type of apartment we want. Call Init() to - * complete initialization. - */ - ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} - - explicit ApartmentRegion(COINIT aAptType) - : mInitResult(::CoInitializeEx(nullptr, aAptType)) { - // If this fires then we're probably mixing apartments on the same thread - MOZ_ASSERT(IsValid()); - } - - ~ApartmentRegion() { - if (IsValid()) { - ::CoUninitialize(); - } - } - - explicit operator bool() const { return IsValid(); } - - bool IsValidOutermost() const { return mInitResult == S_OK; } - - bool IsValid() const { return SUCCEEDED(mInitResult); } - - bool Init(COINIT aAptType) { - MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); - mInitResult = ::CoInitializeEx(nullptr, aAptType); - MOZ_ASSERT(IsValid()); - return IsValid(); - } - - HRESULT - GetHResult() const { return mInitResult; } - - private: - ApartmentRegion(const ApartmentRegion&) = delete; - ApartmentRegion& operator=(const ApartmentRegion&) = delete; - ApartmentRegion(ApartmentRegion&&) = delete; - ApartmentRegion& operator=(ApartmentRegion&&) = delete; - - HRESULT mInitResult; -}; - -template -class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT { - public: - ApartmentRegionT() : mAptRgn(T) {} - - ~ApartmentRegionT() = default; - - explicit operator bool() const { return mAptRgn.IsValid(); } - - bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); } - - bool IsValid() const { return mAptRgn.IsValid(); } - - HRESULT GetHResult() const { return mAptRgn.GetHResult(); } - - private: - ApartmentRegionT(const ApartmentRegionT&) = delete; - ApartmentRegionT& operator=(const ApartmentRegionT&) = delete; - ApartmentRegionT(ApartmentRegionT&&) = delete; - ApartmentRegionT& operator=(ApartmentRegionT&&) = delete; - - ApartmentRegion mAptRgn; -}; - -typedef ApartmentRegionT STARegion; -typedef ApartmentRegionT MTARegion; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_ApartmentRegion_h diff --git a/ipc/mscom/COMApartmentRegion.h b/ipc/mscom/COMApartmentRegion.h new file mode 100644 index 000000000000..9fbd8c87967d --- /dev/null +++ b/ipc/mscom/COMApartmentRegion.h @@ -0,0 +1,53 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_COMApartmentRegion_h +#define mozilla_mscom_COMApartmentRegion_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include + +namespace mozilla { +namespace mscom { + +template +class MOZ_NON_TEMPORARY_CLASS COMApartmentRegion { + public: + COMApartmentRegion() : mInitResult(::CoInitializeEx(nullptr, T)) { + // If this fires then we're probably mixing apartments on the same thread + MOZ_ASSERT(IsValid()); + } + + ~COMApartmentRegion() { + if (IsValid()) { + ::CoUninitialize(); + } + } + + bool IsValidOutermost() const { return mInitResult == S_OK; } + + bool IsValid() const { return SUCCEEDED(mInitResult); } + + HRESULT GetHResult() const { return mInitResult; } + + private: + COMApartmentRegion(const COMApartmentRegion&) = delete; + COMApartmentRegion& operator=(const COMApartmentRegion&) = delete; + COMApartmentRegion(COMApartmentRegion&&) = delete; + COMApartmentRegion& operator=(COMApartmentRegion&&) = delete; + + HRESULT mInitResult; +}; + +typedef COMApartmentRegion STARegion; +typedef COMApartmentRegion MTARegion; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_COMApartmentRegion_h diff --git a/ipc/mscom/EnsureMTA.h b/ipc/mscom/EnsureMTA.h index 7719b0f324c6..690d55101e2b 100644 --- a/ipc/mscom/EnsureMTA.h +++ b/ipc/mscom/EnsureMTA.h @@ -11,6 +11,7 @@ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/Unused.h" +#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/mscom/Utils.h" #include "nsCOMPtr.h" #include "nsIThread.h" diff --git a/ipc/mscom/MainThreadClientInfo.cpp b/ipc/mscom/MainThreadClientInfo.cpp new file mode 100644 index 000000000000..d163d05dbf8a --- /dev/null +++ b/ipc/mscom/MainThreadClientInfo.cpp @@ -0,0 +1,133 @@ +/* -*- 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 "MainThreadClientInfo.h" + +#include "MainThreadUtils.h" +#include "mozilla/Assertions.h" + +#include + +namespace mozilla { +namespace mscom { + +/* static */ +HRESULT +MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) { + MOZ_ASSERT(aOutObj && NS_IsMainThread()); + *aOutObj = nullptr; + + RefPtr obj(new MainThreadClientInfo()); + + RefPtr prevFilter; + HRESULT hr = ::CoRegisterMessageFilter(obj.get(), getter_AddRefs(prevFilter)); + if (FAILED(hr)) { + return hr; + } + + obj->mPrevFilter = prevFilter.forget(); + + obj.forget(aOutObj); + return S_OK; +} + +DWORD +MainThreadClientInfo::GetLastRemoteCallThreadId() const { + MOZ_ASSERT(NS_IsMainThread()); + return mLastRemoteCallTid; +} + +HRESULT +MainThreadClientInfo::QueryInterface(REFIID aIid, void** aOutInterface) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!aOutInterface) { + return E_INVALIDARG; + } + + if (aIid == IID_IUnknown || aIid == IID_IMessageFilter) { + RefPtr filter(this); + filter.forget(aOutInterface); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG +MainThreadClientInfo::AddRef() { + MOZ_ASSERT(NS_IsMainThread()); + + return ++mRefCnt; +} + +ULONG +MainThreadClientInfo::Release() { + MOZ_ASSERT(NS_IsMainThread()); + + ULONG newCount = --mRefCnt; + if (!newCount) { + delete this; + } + return newCount; +} + +DWORD +MainThreadClientInfo::HandleInComingCall(DWORD aCallType, HTASK aCallerTid, + DWORD aTickCount, + LPINTERFACEINFO aInterfaceInfo) { + MOZ_ASSERT(NS_IsMainThread()); + + // aCallerTid is an HTASK for historical reasons but is actually just a + // regular DWORD Thread ID. + mLastRemoteCallTid = + static_cast(reinterpret_cast(aCallerTid)); + + if (!mPrevFilter) { + return SERVERCALL_ISHANDLED; + } + + return mPrevFilter->HandleInComingCall(aCallType, aCallerTid, aTickCount, + aInterfaceInfo); +} + +DWORD +MainThreadClientInfo::RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, + DWORD aRejectType) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!mPrevFilter) { + return 0; + } + + return mPrevFilter->RetryRejectedCall(aCalleeTid, aTickCount, aRejectType); +} + +DWORD +MainThreadClientInfo::MessagePending(HTASK aCalleeTid, DWORD aTickCount, + DWORD aPendingType) { + MOZ_ASSERT(NS_IsMainThread()); + + if (!mPrevFilter) { + return PENDINGMSG_WAITNOPROCESS; + } + + return mPrevFilter->MessagePending(aCalleeTid, aTickCount, aPendingType); +} + +MainThreadClientInfo::MainThreadClientInfo() + : mRefCnt(0), mLastRemoteCallTid(0) { + MOZ_ASSERT(NS_IsMainThread()); +} + +void MainThreadClientInfo::Detach() { + MOZ_ASSERT(NS_IsMainThread()); + ::CoRegisterMessageFilter(mPrevFilter, nullptr); + mPrevFilter = nullptr; +} + +} // namespace mscom +} // namespace mozilla diff --git a/ipc/mscom/MainThreadClientInfo.h b/ipc/mscom/MainThreadClientInfo.h new file mode 100644 index 000000000000..e762ec9b00a2 --- /dev/null +++ b/ipc/mscom/MainThreadClientInfo.h @@ -0,0 +1,52 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_MainThreadClientInfo +#define mozilla_mscom_MainThreadClientInfo + +#include "mozilla/RefPtr.h" +#include "nsString.h" + +#include + +namespace mozilla { +namespace mscom { + +class MainThreadClientInfo final : public IMessageFilter { + public: + static HRESULT Create(MainThreadClientInfo** aOutObj); + + DWORD GetLastRemoteCallThreadId() const; + void Detach(); + + STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + STDMETHODIMP_(DWORD) + HandleInComingCall(DWORD aCallType, HTASK aCallerTid, DWORD aTickCount, + LPINTERFACEINFO aInterfaceInfo) override; + STDMETHODIMP_(DWORD) + RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, + DWORD aRejectType) override; + STDMETHODIMP_(DWORD) + MessagePending(HTASK aCalleeTid, DWORD aTickCount, + DWORD aPendingType) override; + + private: + MainThreadClientInfo(); + ~MainThreadClientInfo() = default; + + private: + ULONG mRefCnt; + RefPtr mPrevFilter; + DWORD mLastRemoteCallTid; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_MainThreadClientInfo diff --git a/ipc/mscom/ProcessRuntime.cpp b/ipc/mscom/MainThreadRuntime.cpp similarity index 52% rename from ipc/mscom/ProcessRuntime.cpp rename to ipc/mscom/MainThreadRuntime.cpp index ffbb9261d6d0..bce1701e4891 100644 --- a/ipc/mscom/ProcessRuntime.cpp +++ b/ipc/mscom/MainThreadRuntime.cpp @@ -4,25 +4,21 @@ * 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 "mozilla/mscom/ProcessRuntime.h" +#include "mozilla/mscom/MainThreadRuntime.h" -#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#if defined(ACCESSIBILITY) # include "mozilla/a11y/Compatibility.h" -#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#endif +#include "mozilla/ArrayUtils.h" #include "mozilla/Assertions.h" -#include "mozilla/DynamicallyLinkedFunctionPtr.h" -#include "mozilla/mscom/ProcessRuntimeShared.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" -#include "mozilla/Unused.h" -#include "mozilla/Vector.h" #include "mozilla/WindowsVersion.h" +#if defined(ACCESSIBILITY) +# include "nsExceptionHandler.h" +#endif // defined(ACCESSIBILITY) #include "nsWindowsHelpers.h" - -#if defined(MOZILLA_INTERNAL_API) -# include "mozilla/mscom/EnsureMTA.h" -# include "nsThreadManager.h" -#endif // defined(MOZILLA_INTERNAL_API) +#include "nsXULAppAPI.h" #include #include @@ -32,65 +28,27 @@ // This API from oleaut32.dll is not declared in Windows SDK headers extern "C" void __cdecl SetOaNoCache(void); -#if (_WIN32_WINNT < 0x0602) -BOOL WINAPI GetProcessMitigationPolicy( - HANDLE hProcess, PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, - SIZE_T dwLength); -#endif // (_WIN32_WINNT < 0x0602) - namespace mozilla { namespace mscom { -ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType) - : mInitResult(CO_E_NOTINITIALIZED), - mIsParentProcess(aProcessType == GeckoProcessType_Default) -#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +MainThreadRuntime* MainThreadRuntime::sInstance = nullptr; + +MainThreadRuntime::MainThreadRuntime() + : mInitResult(E_UNEXPECTED) +#if defined(ACCESSIBILITY) , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId()) -#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#endif // defined(ACCESSIBILITY) { -#if defined(MOZILLA_INTERNAL_API) - // If our process is running under Win32k lockdown, we cannot initialize - // COM with single-threaded apartments. This is because STAs create a hidden - // window, which implicitly requires user32 and Win32k, which are blocked. - // Instead we start a multi-threaded apartment and conduct our process-wide - // COM initialization on that MTA background thread. - if (IsWin32kLockedDown()) { - // It is possible that we're running so early that we might need to start - // the thread manager ourselves. - nsresult rv = nsThreadManager::get().Init(); - MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); - if (NS_FAILED(rv)) { - return; - } - - EnsureMTA([this]() -> void { InitInsideApartment(); }); - return; - } -#endif // defined(MOZILLA_INTERNAL_API) - - // Otherwise we initialize a single-threaded apartment on the current thread. - mAptRegion.Init(COINIT_APARTMENTTHREADED); - // We must be the outermost COM initialization on this thread. The COM runtime // cannot be configured once we start manipulating objects - MOZ_ASSERT(mAptRegion.IsValidOutermost()); - if (!mAptRegion.IsValidOutermost()) { - mInitResult = mAptRegion.GetHResult(); + MOZ_ASSERT(mStaRegion.IsValidOutermost()); + if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) { return; } - InitInsideApartment(); -} - -void ProcessRuntime::InitInsideApartment() { - ProcessInitLock lock; - if (lock.IsInitialized()) { - // COM has already been initialized by a previous ProcessRuntime instance - return; - } - - // We are required to initialize security prior to configuring global options. + // We are required to initialize security in order to configure global + // options. mInitResult = InitializeSecurity(); MOZ_ASSERT(SUCCEEDED(mInitResult)); if (FAILED(mInitResult)) { @@ -118,25 +76,58 @@ void ProcessRuntime::InitInsideApartment() { return; } - lock.SetInitialized(); + if (XRE_IsParentProcess()) { + MainThreadClientInfo::Create(getter_AddRefs(mClientInfo)); + } + + MOZ_ASSERT(!sInstance); + sInstance = this; +} + +MainThreadRuntime::~MainThreadRuntime() { + if (mClientInfo) { + mClientInfo->Detach(); + } + + MOZ_ASSERT(sInstance == this); + if (sInstance == this) { + sInstance = nullptr; + } } /* static */ DWORD -ProcessRuntime::GetClientThreadId() { - DWORD callerTid; - HRESULT hr = ::CoGetCallerTID(&callerTid); - // Don't return callerTid unless the call succeeded and returned S_FALSE, - // indicating that the caller originates from a different process. - if (hr != S_FALSE) { +MainThreadRuntime::GetClientThreadId() { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(XRE_IsParentProcess(), "Unsupported outside of parent process"); + if (!XRE_IsParentProcess()) { return 0; } - return callerTid; + // Don't check for a calling executable if the caller is in-process. + // We verify this by asking COM for a call context. If none exists, then + // we must be a local call. + RefPtr serverSecurity; + if (FAILED(::CoGetCallContext(IID_IServerSecurity, + getter_AddRefs(serverSecurity)))) { + return 0; + } + + MOZ_ASSERT(sInstance); + if (!sInstance) { + return 0; + } + + MOZ_ASSERT(sInstance->mClientInfo); + if (!sInstance->mClientInfo) { + return 0; + } + + return sInstance->mClientInfo->GetLastRemoteCallThreadId(); } HRESULT -ProcessRuntime::InitializeSecurity() { +MainThreadRuntime::InitializeSecurity() { HANDLE rawToken = nullptr; BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken); if (!ok) { @@ -195,7 +186,7 @@ ProcessRuntime::InitializeSecurity() { BYTE appContainersSid[SECURITY_MAX_SID_SIZE]; DWORD appContainersSidSize = sizeof(appContainersSid); - if (mIsParentProcess && IsWin8OrLater()) { + if (XRE_IsParentProcess() && IsWin8OrLater()) { if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr, appContainersSid, &appContainersSidSize)) { return HRESULT_FROM_WIN32(::GetLastError()); @@ -204,43 +195,38 @@ ProcessRuntime::InitializeSecurity() { // Grant access to SYSTEM, Administrators, the user, and when running as the // browser process on Windows 8+, all app containers. - const size_t kMaxInlineEntries = 4; - mozilla::Vector entries; + EXPLICIT_ACCESS entries[] = { + {COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(systemSid)}}, + {COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}, + {COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(tokenUser.User.Sid)}}, + // appContainersSid must be the last entry in this array! + {COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, + reinterpret_cast(appContainersSid)}}}; - Unused << entries.append(EXPLICIT_ACCESS_W{ - COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(systemSid)}}); - - Unused << entries.append(EXPLICIT_ACCESS_W{ - COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}); - - Unused << entries.append(EXPLICIT_ACCESS_W{ - COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(tokenUser.User.Sid)}}); - - if (mIsParentProcess && IsWin8OrLater()) { - Unused << entries.append( - EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, - reinterpret_cast(appContainersSid)}}); + ULONG numEntries = ArrayLength(entries); + if (!XRE_IsParentProcess() || !IsWin8OrLater()) { + // Exclude appContainersSid on Windows 7 and non-parent processes. + --numEntries; } PACL rawDacl = nullptr; - win32Error = - ::SetEntriesInAclW(entries.length(), entries.begin(), nullptr, &rawDacl); + win32Error = ::SetEntriesInAcl(numEntries, entries, nullptr, &rawDacl); if (win32Error != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(win32Error); } @@ -265,26 +251,5 @@ ProcessRuntime::InitializeSecurity() { RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr); } -#if defined(MOZILLA_INTERNAL_API) - -/* static */ bool -ProcessRuntime::IsWin32kLockedDown() { - static const DynamicallyLinkedFunctionPtr - pGetProcessMitigationPolicy(L"kernel32.dll", "GetProcessMitigationPolicy"); - if (!pGetProcessMitigationPolicy) { - return false; - } - - PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY polInfo; - if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), - ProcessSystemCallDisablePolicy, &polInfo, sizeof(polInfo))) { - return false; - } - - return polInfo.DisallowWin32kSystemCalls; -} - -#endif // defined(MOZILLA_INTERNAL_API) - } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/MainThreadRuntime.h b/ipc/mscom/MainThreadRuntime.h new file mode 100644 index 000000000000..00cae6c1965e --- /dev/null +++ b/ipc/mscom/MainThreadRuntime.h @@ -0,0 +1,58 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_MainThreadRuntime_h +#define mozilla_mscom_MainThreadRuntime_h + +#include "mozilla/Attributes.h" +#if defined(ACCESSIBILITY) +# include "mozilla/mscom/ActivationContext.h" +#endif // defined(ACCESSIBILITY) +#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/MainThreadClientInfo.h" +#include "mozilla/RefPtr.h" + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS MainThreadRuntime { + public: + MainThreadRuntime(); + ~MainThreadRuntime(); + + explicit operator bool() const { + return mStaRegion.IsValidOutermost() && SUCCEEDED(mInitResult); + } + + MainThreadRuntime(MainThreadRuntime&) = delete; + MainThreadRuntime(MainThreadRuntime&&) = delete; + MainThreadRuntime& operator=(MainThreadRuntime&) = delete; + MainThreadRuntime& operator=(MainThreadRuntime&&) = delete; + + /** + * @return 0 if call is in-process or resolving the calling thread failed, + * otherwise contains the thread id of the calling thread. + */ + static DWORD GetClientThreadId(); + + private: + HRESULT InitializeSecurity(); + + HRESULT mInitResult; +#if defined(ACCESSIBILITY) + ActivationContextRegion mActCtxRgn; +#endif // defined(ACCESSIBILITY) + STARegion mStaRegion; + + RefPtr mClientInfo; + + static MainThreadRuntime* sInstance; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_MainThreadRuntime_h diff --git a/ipc/mscom/ProcessRuntime.h b/ipc/mscom/ProcessRuntime.h deleted file mode 100644 index 3d27e8f43d82..000000000000 --- a/ipc/mscom/ProcessRuntime.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_ProcessRuntime_h -#define mozilla_mscom_ProcessRuntime_h - -#include "mozilla/Attributes.h" -#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) -# include "mozilla/mscom/ActivationContext.h" -#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) -#include "mozilla/mscom/ApartmentRegion.h" -#include "nsXULAppAPI.h" - -namespace mozilla { -namespace mscom { - -class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final { - public: -#if defined(MOZILLA_INTERNAL_API) - ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {} -#endif // defined(MOZILLA_INTERNAL_API) - - explicit ProcessRuntime(GeckoProcessType aProcessType); - ~ProcessRuntime() = default; - - explicit operator bool() const { return SUCCEEDED(mInitResult); } - - ProcessRuntime(ProcessRuntime&) = delete; - ProcessRuntime(ProcessRuntime&&) = delete; - ProcessRuntime& operator=(ProcessRuntime&) = delete; - ProcessRuntime& operator=(ProcessRuntime&&) = delete; - - /** - * @return 0 if call is in-process or resolving the calling thread failed, - * otherwise contains the thread id of the calling thread. - */ - static DWORD GetClientThreadId(); - - private: - void InitInsideApartment(); - HRESULT InitializeSecurity(); - -#if defined(MOZILLA_INTERNAL_API) - static bool IsWin32kLockedDown(); -#endif // defined(MOZILLA_INTERNAL_API) - - HRESULT mInitResult; - bool mIsParentProcess; -#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) - ActivationContextRegion mActCtxRgn; -#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) - ApartmentRegion mAptRegion; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_ProcessRuntime_h diff --git a/ipc/mscom/Ptr.h b/ipc/mscom/Ptr.h index 98cbef684f94..9df05b4a0b79 100644 --- a/ipc/mscom/Ptr.h +++ b/ipc/mscom/Ptr.h @@ -16,8 +16,6 @@ #include "nsThreadUtils.h" #include "nsXULAppAPI.h" -#include - /** * The glue code in mozilla::mscom often needs to pass around interface pointers * belonging to a different apartment from the current one. We must not touch diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index 71a3cb05f8d5..5f425ceb806b 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -7,22 +7,19 @@ EXPORTS.mozilla.mscom += [ 'Aggregation.h', 'AgileReference.h', - 'ApartmentRegion.h', 'AsyncInvoker.h', + 'COMApartmentRegion.h', 'COMPtrHolder.h', 'EnsureMTA.h', + 'MainThreadClientInfo.h', + 'MainThreadRuntime.h', 'Objref.h', 'PassthruProxy.h', - 'ProcessRuntime.h', 'ProxyStream.h', 'Ptr.h', 'Utils.h', ] -DIRS += [ - 'mozglue', -] - SOURCES += [ 'VTableBuilder.c', ] @@ -30,9 +27,10 @@ SOURCES += [ UNIFIED_SOURCES += [ 'AgileReference.cpp', 'EnsureMTA.cpp', + 'MainThreadClientInfo.cpp', + 'MainThreadRuntime.cpp', 'Objref.cpp', 'PassthruProxy.cpp', - 'ProcessRuntime.cpp', 'ProxyStream.cpp', 'RegistrationAnnotator.cpp', 'Utils.cpp', diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp deleted file mode 100644 index 517918f2d87c..000000000000 --- a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- 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 "mozilla/mscom/ProcessRuntimeShared.h" -#include "MozglueUtils.h" - -// We allow multiple ProcessRuntime instances to exist simultaneously (even -// on separate threads), but only one should be doing the process-wide -// initialization. These variables provide that mutual exclusion. -static mozilla::glue::Win32SRWLock gLock; -static bool gIsProcessInitialized = false; - -namespace mozilla { -namespace mscom { -namespace detail { - -MFBT_API bool& -BeginProcessRuntimeInit() { - gLock.LockExclusive(); - return gIsProcessInitialized; -} - -MFBT_API void -EndProcessRuntimeInit() { - gLock.UnlockExclusive(); -} - -} // namespace detail -} // namespace mscom -} // namespace mozilla diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.h b/ipc/mscom/mozglue/ProcessRuntimeShared.h deleted file mode 100644 index a42b1b818e54..000000000000 --- a/ipc/mscom/mozglue/ProcessRuntimeShared.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_ProcessRuntimeShared_h -#define mozilla_mscom_ProcessRuntimeShared_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" -#include "mozilla/Types.h" - -namespace mozilla { -namespace mscom { -namespace detail { - -MFBT_API bool& BeginProcessRuntimeInit(); -MFBT_API void EndProcessRuntimeInit(); - -} // namespace detail - -class MOZ_RAII ProcessInitLock final { - public: - ProcessInitLock() - : mIsProcessInitialized(detail::BeginProcessRuntimeInit()) { - } - - ~ProcessInitLock() { - detail::EndProcessRuntimeInit(); - } - - bool IsInitialized() const { - return mIsProcessInitialized; - } - - void SetInitialized() { - MOZ_ASSERT(!mIsProcessInitialized); - mIsProcessInitialized = true; - } - - ProcessInitLock(const ProcessInitLock&) = delete; - ProcessInitLock(ProcessInitLock&&) = delete; - ProcessInitLock operator=(const ProcessInitLock&) = delete; - ProcessInitLock operator=(ProcessInitLock&&) = delete; - - private: - bool& mIsProcessInitialized; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_ProcessRuntimeShared_h diff --git a/ipc/mscom/mozglue/moz.build b/ipc/mscom/mozglue/moz.build deleted file mode 100644 index 2d444a2e50af..000000000000 --- a/ipc/mscom/mozglue/moz.build +++ /dev/null @@ -1,21 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -Library('mscom-mozglue') - -EXPORTS.mozilla.mscom += [ - 'ProcessRuntimeShared.h', -] - -LOCAL_INCLUDES += [ - '/mozglue/build', -] - -DEFINES['IMPL_MFBT'] = True - -UNIFIED_SOURCES += [ - 'ProcessRuntimeShared.cpp', -] diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index aa4e8710de96..4a5a18c659a4 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -36,9 +36,6 @@ if CONFIG['OS_TARGET'] == 'WINNT': 'user32.dll', ] RCINCLUDE = 'mozglue.rc' - USE_LIBS += [ - 'mscom-mozglue', - ] if CONFIG['MOZ_PGO'] and CONFIG['CC_TYPE'] == 'clang-cl': SOURCES += ['cygprofile.cpp'] diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 9454ea1dd871..fc91477d20cb 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -110,7 +110,7 @@ # include "cairo/cairo-features.h" # include "mozilla/WindowsDllBlocklist.h" # include "mozilla/WinHeaderOnlyUtils.h" -# include "mozilla/mscom/ProcessRuntime.h" +# include "mozilla/mscom/MainThreadRuntime.h" # include "mozilla/widget/AudioSession.h" # if defined(MOZ_LAUNCHER_PROCESS) @@ -4803,7 +4803,7 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) { // trivial COM is run in the application. Since these settings may affect // stability, we should instantiate COM ASAP so that we can ensure that these // global settings are configured before anything can interfere. - mozilla::mscom::ProcessRuntime msCOMRuntime; + mozilla::mscom::MainThreadRuntime msCOMRuntime; #endif // init diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp index 32cd7d03be41..48c419828a36 100644 --- a/widget/windows/JumpListBuilder.cpp +++ b/widget/windows/JumpListBuilder.cpp @@ -23,7 +23,7 @@ #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "mozilla/dom/Promise.h" -#include "mozilla/mscom/ApartmentRegion.h" +#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/mscom/EnsureMTA.h" #include From 84c01f89309732eaf6ac4079383991a7e62397fa Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Thu, 14 Feb 2019 18:56:20 +0000 Subject: [PATCH 55/84] Bug 1400344: Rename mscom::MainThreadRuntime to mscom::ProcessRuntime and make it aware of Win32k lockdown and of multiple instantiations; r=Jamie This patch takes care of a bunch of issues and does some cleanup: * We rename mscom::MainThreadRuntime to mscom::ProcessRuntime, as the latter is a more accurate name going forward. * We make ProcessRuntime aware of the Win32k Lockdown process mitigation policy. When Win32k is disabled, we perform process-wide COM initialization in the multi-threaded apartment (since we cannot create an STA window). * We refactor the mscom apartment region stuff to enable the Win32k lockdown pieces in ProcessRuntime. * We move some Gecko-specific stuff into MOZILLA_INTERNAL_API guards so that ProcessRuntime is usable outside of xul.dll (I will be needing it for the launcher process). * Another thing that might happen with the launcher process is that, under error conditions in the launcher, we create a ProcessRuntime object on a background thread for the purposes of telemetry logging, but we also allow the main thread to proceed to start as the browser. This could result in a scenario where the main thread, as the browser process, is attempting to instantiate its ProcessRuntime and ends up racing with the launcher process's telemetry thread which has its own ProcessRuntime. To account for this situation, we add mutual exclusion to the process-wide initialization code. We host this part inside mozglue since that state is shared between both firefox.exe and xul.dll. * We clean up ProcessRuntime::InitializeSecurity by using Vector to set up the EXPLICIT_ACCESS entries. * We remove mscom::MainThreadClientInfo and replace it with a direct call to CoGetCallerTID * We revise all references to this class to use the new name. Differential Revision: https://phabricator.services.mozilla.com/D19551 --HG-- rename : ipc/mscom/COMApartmentRegion.h => ipc/mscom/ApartmentRegion.h rename : ipc/mscom/MainThreadRuntime.cpp => ipc/mscom/ProcessRuntime.cpp rename : ipc/mscom/MainThreadRuntime.h => ipc/mscom/ProcessRuntime.h extra : moz-landing-system : lando --- accessible/windows/msaa/LazyInstantiator.cpp | 4 +- browser/app/winlauncher/LaunchUnelevated.cpp | 2 +- dom/ipc/ContentProcess.h | 4 +- dom/media/ipc/RDDProcessImpl.h | 2 +- dom/plugins/ipc/PluginProcessChild.h | 4 +- gfx/ipc/GPUProcessImpl.h | 4 +- ipc/mscom/ApartmentRegion.h | 94 ++++++++ ipc/mscom/COMApartmentRegion.h | 53 ----- ipc/mscom/EnsureMTA.h | 1 - ipc/mscom/MainThreadClientInfo.cpp | 133 ----------- ipc/mscom/MainThreadClientInfo.h | 52 ----- ipc/mscom/MainThreadRuntime.h | 58 ----- ...inThreadRuntime.cpp => ProcessRuntime.cpp} | 213 ++++++++++-------- ipc/mscom/ProcessRuntime.h | 61 +++++ ipc/mscom/Ptr.h | 2 + ipc/mscom/moz.build | 12 +- ipc/mscom/mozglue/ProcessRuntimeShared.cpp | 33 +++ ipc/mscom/mozglue/ProcessRuntimeShared.h | 54 +++++ ipc/mscom/mozglue/moz.build | 21 ++ mozglue/build/moz.build | 3 + toolkit/xre/nsAppRunner.cpp | 4 +- widget/windows/JumpListBuilder.cpp | 2 +- 22 files changed, 412 insertions(+), 404 deletions(-) create mode 100644 ipc/mscom/ApartmentRegion.h delete mode 100644 ipc/mscom/COMApartmentRegion.h delete mode 100644 ipc/mscom/MainThreadClientInfo.cpp delete mode 100644 ipc/mscom/MainThreadClientInfo.h delete mode 100644 ipc/mscom/MainThreadRuntime.h rename ipc/mscom/{MainThreadRuntime.cpp => ProcessRuntime.cpp} (52%) create mode 100644 ipc/mscom/ProcessRuntime.h create mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.cpp create mode 100644 ipc/mscom/mozglue/ProcessRuntimeShared.h create mode 100644 ipc/mscom/mozglue/moz.build diff --git a/accessible/windows/msaa/LazyInstantiator.cpp b/accessible/windows/msaa/LazyInstantiator.cpp index f376e40d1621..a82a2738d446 100644 --- a/accessible/windows/msaa/LazyInstantiator.cpp +++ b/accessible/windows/msaa/LazyInstantiator.cpp @@ -11,7 +11,7 @@ #include "mozilla/a11y/Compatibility.h" #include "mozilla/a11y/Platform.h" #include "mozilla/Assertions.h" -#include "mozilla/mscom/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" #include "mozilla/mscom/Registration.h" #include "mozilla/UniquePtr.h" #include "nsAccessibilityService.h" @@ -313,7 +313,7 @@ LazyInstantiator::MaybeResolveRoot() { } if (GetAccService() || - ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) { + ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) { mWeakRootAccWrap = ResolveRootAccWrap(); if (!mWeakRootAccWrap) { return E_POINTER; diff --git a/browser/app/winlauncher/LaunchUnelevated.cpp b/browser/app/winlauncher/LaunchUnelevated.cpp index b0ba54df7908..38ee8e66986b 100644 --- a/browser/app/winlauncher/LaunchUnelevated.cpp +++ b/browser/app/winlauncher/LaunchUnelevated.cpp @@ -9,7 +9,7 @@ #include "mozilla/Assertions.h" #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/LauncherResult.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/RefPtr.h" #include "nsWindowsHelpers.h" diff --git a/dom/ipc/ContentProcess.h b/dom/ipc/ContentProcess.h index eb9a908328dd..c6b2a58684b8 100644 --- a/dom/ipc/ContentProcess.h +++ b/dom/ipc/ContentProcess.h @@ -12,7 +12,7 @@ #include "ContentChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -39,7 +39,7 @@ class ContentProcess : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif DISALLOW_EVIL_CONSTRUCTORS(ContentProcess); diff --git a/dom/media/ipc/RDDProcessImpl.h b/dom/media/ipc/RDDProcessImpl.h index a75f1934758e..8c044132da34 100644 --- a/dom/media/ipc/RDDProcessImpl.h +++ b/dom/media/ipc/RDDProcessImpl.h @@ -8,7 +8,7 @@ #include "mozilla/ipc/ProcessChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif #include "RDDParent.h" diff --git a/dom/plugins/ipc/PluginProcessChild.h b/dom/plugins/ipc/PluginProcessChild.h index 48d3bc066a76..b715f0d649a0 100644 --- a/dom/plugins/ipc/PluginProcessChild.h +++ b/dom/plugins/ipc/PluginProcessChild.h @@ -11,7 +11,7 @@ #include "mozilla/plugins/PluginModuleChild.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -40,7 +40,7 @@ class PluginProcessChild : public mozilla::ipc::ProcessChild { #if defined(XP_WIN) /* Drag-and-drop depends on the host initializing COM. * This object initializes and configures COM. */ - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif PluginModuleChild mPlugin; diff --git a/gfx/ipc/GPUProcessImpl.h b/gfx/ipc/GPUProcessImpl.h index a76aeb406b33..a205e2b2333b 100644 --- a/gfx/ipc/GPUProcessImpl.h +++ b/gfx/ipc/GPUProcessImpl.h @@ -10,7 +10,7 @@ #include "GPUParent.h" #if defined(XP_WIN) -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" #endif namespace mozilla { @@ -33,7 +33,7 @@ class GPUProcessImpl final : public ipc::ProcessChild { #if defined(XP_WIN) // This object initializes and configures COM. - mozilla::mscom::MainThreadRuntime mCOMRuntime; + mozilla::mscom::ProcessRuntime mCOMRuntime; #endif }; diff --git a/ipc/mscom/ApartmentRegion.h b/ipc/mscom/ApartmentRegion.h new file mode 100644 index 000000000000..dc56e3fc9676 --- /dev/null +++ b/ipc/mscom/ApartmentRegion.h @@ -0,0 +1,94 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ApartmentRegion_h +#define mozilla_mscom_ApartmentRegion_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ApartmentRegion { + public: + /** + * This constructor is to be used when we want to instantiate the object but + * we do not yet know which type of apartment we want. Call Init() to + * complete initialization. + */ + ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} + + explicit ApartmentRegion(COINIT aAptType) + : mInitResult(::CoInitializeEx(nullptr, aAptType)) { + // If this fires then we're probably mixing apartments on the same thread + MOZ_ASSERT(IsValid()); + } + + ~ApartmentRegion() { + if (IsValid()) { + ::CoUninitialize(); + } + } + + explicit operator bool() const { return IsValid(); } + + bool IsValidOutermost() const { return mInitResult == S_OK; } + + bool IsValid() const { return SUCCEEDED(mInitResult); } + + bool Init(COINIT aAptType) { + MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); + mInitResult = ::CoInitializeEx(nullptr, aAptType); + MOZ_ASSERT(IsValid()); + return IsValid(); + } + + HRESULT + GetHResult() const { return mInitResult; } + + private: + ApartmentRegion(const ApartmentRegion&) = delete; + ApartmentRegion& operator=(const ApartmentRegion&) = delete; + ApartmentRegion(ApartmentRegion&&) = delete; + ApartmentRegion& operator=(ApartmentRegion&&) = delete; + + HRESULT mInitResult; +}; + +template +class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT { + public: + ApartmentRegionT() : mAptRgn(T) {} + + ~ApartmentRegionT() = default; + + explicit operator bool() const { return mAptRgn.IsValid(); } + + bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); } + + bool IsValid() const { return mAptRgn.IsValid(); } + + HRESULT GetHResult() const { return mAptRgn.GetHResult(); } + + private: + ApartmentRegionT(const ApartmentRegionT&) = delete; + ApartmentRegionT& operator=(const ApartmentRegionT&) = delete; + ApartmentRegionT(ApartmentRegionT&&) = delete; + ApartmentRegionT& operator=(ApartmentRegionT&&) = delete; + + ApartmentRegion mAptRgn; +}; + +typedef ApartmentRegionT STARegion; +typedef ApartmentRegionT MTARegion; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ApartmentRegion_h diff --git a/ipc/mscom/COMApartmentRegion.h b/ipc/mscom/COMApartmentRegion.h deleted file mode 100644 index 9fbd8c87967d..000000000000 --- a/ipc/mscom/COMApartmentRegion.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_COMApartmentRegion_h -#define mozilla_mscom_COMApartmentRegion_h - -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include - -namespace mozilla { -namespace mscom { - -template -class MOZ_NON_TEMPORARY_CLASS COMApartmentRegion { - public: - COMApartmentRegion() : mInitResult(::CoInitializeEx(nullptr, T)) { - // If this fires then we're probably mixing apartments on the same thread - MOZ_ASSERT(IsValid()); - } - - ~COMApartmentRegion() { - if (IsValid()) { - ::CoUninitialize(); - } - } - - bool IsValidOutermost() const { return mInitResult == S_OK; } - - bool IsValid() const { return SUCCEEDED(mInitResult); } - - HRESULT GetHResult() const { return mInitResult; } - - private: - COMApartmentRegion(const COMApartmentRegion&) = delete; - COMApartmentRegion& operator=(const COMApartmentRegion&) = delete; - COMApartmentRegion(COMApartmentRegion&&) = delete; - COMApartmentRegion& operator=(COMApartmentRegion&&) = delete; - - HRESULT mInitResult; -}; - -typedef COMApartmentRegion STARegion; -typedef COMApartmentRegion MTARegion; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_COMApartmentRegion_h diff --git a/ipc/mscom/EnsureMTA.h b/ipc/mscom/EnsureMTA.h index 690d55101e2b..7719b0f324c6 100644 --- a/ipc/mscom/EnsureMTA.h +++ b/ipc/mscom/EnsureMTA.h @@ -11,7 +11,6 @@ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/Unused.h" -#include "mozilla/mscom/COMApartmentRegion.h" #include "mozilla/mscom/Utils.h" #include "nsCOMPtr.h" #include "nsIThread.h" diff --git a/ipc/mscom/MainThreadClientInfo.cpp b/ipc/mscom/MainThreadClientInfo.cpp deleted file mode 100644 index d163d05dbf8a..000000000000 --- a/ipc/mscom/MainThreadClientInfo.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- 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 "MainThreadClientInfo.h" - -#include "MainThreadUtils.h" -#include "mozilla/Assertions.h" - -#include - -namespace mozilla { -namespace mscom { - -/* static */ -HRESULT -MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) { - MOZ_ASSERT(aOutObj && NS_IsMainThread()); - *aOutObj = nullptr; - - RefPtr obj(new MainThreadClientInfo()); - - RefPtr prevFilter; - HRESULT hr = ::CoRegisterMessageFilter(obj.get(), getter_AddRefs(prevFilter)); - if (FAILED(hr)) { - return hr; - } - - obj->mPrevFilter = prevFilter.forget(); - - obj.forget(aOutObj); - return S_OK; -} - -DWORD -MainThreadClientInfo::GetLastRemoteCallThreadId() const { - MOZ_ASSERT(NS_IsMainThread()); - return mLastRemoteCallTid; -} - -HRESULT -MainThreadClientInfo::QueryInterface(REFIID aIid, void** aOutInterface) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!aOutInterface) { - return E_INVALIDARG; - } - - if (aIid == IID_IUnknown || aIid == IID_IMessageFilter) { - RefPtr filter(this); - filter.forget(aOutInterface); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG -MainThreadClientInfo::AddRef() { - MOZ_ASSERT(NS_IsMainThread()); - - return ++mRefCnt; -} - -ULONG -MainThreadClientInfo::Release() { - MOZ_ASSERT(NS_IsMainThread()); - - ULONG newCount = --mRefCnt; - if (!newCount) { - delete this; - } - return newCount; -} - -DWORD -MainThreadClientInfo::HandleInComingCall(DWORD aCallType, HTASK aCallerTid, - DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) { - MOZ_ASSERT(NS_IsMainThread()); - - // aCallerTid is an HTASK for historical reasons but is actually just a - // regular DWORD Thread ID. - mLastRemoteCallTid = - static_cast(reinterpret_cast(aCallerTid)); - - if (!mPrevFilter) { - return SERVERCALL_ISHANDLED; - } - - return mPrevFilter->HandleInComingCall(aCallType, aCallerTid, aTickCount, - aInterfaceInfo); -} - -DWORD -MainThreadClientInfo::RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return 0; - } - - return mPrevFilter->RetryRejectedCall(aCalleeTid, aTickCount, aRejectType); -} - -DWORD -MainThreadClientInfo::MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrevFilter) { - return PENDINGMSG_WAITNOPROCESS; - } - - return mPrevFilter->MessagePending(aCalleeTid, aTickCount, aPendingType); -} - -MainThreadClientInfo::MainThreadClientInfo() - : mRefCnt(0), mLastRemoteCallTid(0) { - MOZ_ASSERT(NS_IsMainThread()); -} - -void MainThreadClientInfo::Detach() { - MOZ_ASSERT(NS_IsMainThread()); - ::CoRegisterMessageFilter(mPrevFilter, nullptr); - mPrevFilter = nullptr; -} - -} // namespace mscom -} // namespace mozilla diff --git a/ipc/mscom/MainThreadClientInfo.h b/ipc/mscom/MainThreadClientInfo.h deleted file mode 100644 index e762ec9b00a2..000000000000 --- a/ipc/mscom/MainThreadClientInfo.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_MainThreadClientInfo -#define mozilla_mscom_MainThreadClientInfo - -#include "mozilla/RefPtr.h" -#include "nsString.h" - -#include - -namespace mozilla { -namespace mscom { - -class MainThreadClientInfo final : public IMessageFilter { - public: - static HRESULT Create(MainThreadClientInfo** aOutObj); - - DWORD GetLastRemoteCallThreadId() const; - void Detach(); - - STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - STDMETHODIMP_(DWORD) - HandleInComingCall(DWORD aCallType, HTASK aCallerTid, DWORD aTickCount, - LPINTERFACEINFO aInterfaceInfo) override; - STDMETHODIMP_(DWORD) - RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount, - DWORD aRejectType) override; - STDMETHODIMP_(DWORD) - MessagePending(HTASK aCalleeTid, DWORD aTickCount, - DWORD aPendingType) override; - - private: - MainThreadClientInfo(); - ~MainThreadClientInfo() = default; - - private: - ULONG mRefCnt; - RefPtr mPrevFilter; - DWORD mLastRemoteCallTid; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadClientInfo diff --git a/ipc/mscom/MainThreadRuntime.h b/ipc/mscom/MainThreadRuntime.h deleted file mode 100644 index 00cae6c1965e..000000000000 --- a/ipc/mscom/MainThreadRuntime.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_mscom_MainThreadRuntime_h -#define mozilla_mscom_MainThreadRuntime_h - -#include "mozilla/Attributes.h" -#if defined(ACCESSIBILITY) -# include "mozilla/mscom/ActivationContext.h" -#endif // defined(ACCESSIBILITY) -#include "mozilla/mscom/COMApartmentRegion.h" -#include "mozilla/mscom/MainThreadClientInfo.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { -namespace mscom { - -class MOZ_NON_TEMPORARY_CLASS MainThreadRuntime { - public: - MainThreadRuntime(); - ~MainThreadRuntime(); - - explicit operator bool() const { - return mStaRegion.IsValidOutermost() && SUCCEEDED(mInitResult); - } - - MainThreadRuntime(MainThreadRuntime&) = delete; - MainThreadRuntime(MainThreadRuntime&&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&) = delete; - MainThreadRuntime& operator=(MainThreadRuntime&&) = delete; - - /** - * @return 0 if call is in-process or resolving the calling thread failed, - * otherwise contains the thread id of the calling thread. - */ - static DWORD GetClientThreadId(); - - private: - HRESULT InitializeSecurity(); - - HRESULT mInitResult; -#if defined(ACCESSIBILITY) - ActivationContextRegion mActCtxRgn; -#endif // defined(ACCESSIBILITY) - STARegion mStaRegion; - - RefPtr mClientInfo; - - static MainThreadRuntime* sInstance; -}; - -} // namespace mscom -} // namespace mozilla - -#endif // mozilla_mscom_MainThreadRuntime_h diff --git a/ipc/mscom/MainThreadRuntime.cpp b/ipc/mscom/ProcessRuntime.cpp similarity index 52% rename from ipc/mscom/MainThreadRuntime.cpp rename to ipc/mscom/ProcessRuntime.cpp index bce1701e4891..ffbb9261d6d0 100644 --- a/ipc/mscom/MainThreadRuntime.cpp +++ b/ipc/mscom/ProcessRuntime.cpp @@ -4,21 +4,25 @@ * 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 "mozilla/mscom/MainThreadRuntime.h" +#include "mozilla/mscom/ProcessRuntime.h" -#if defined(ACCESSIBILITY) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) # include "mozilla/a11y/Compatibility.h" -#endif -#include "mozilla/ArrayUtils.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) #include "mozilla/Assertions.h" +#include "mozilla/DynamicallyLinkedFunctionPtr.h" +#include "mozilla/mscom/ProcessRuntimeShared.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" +#include "mozilla/Unused.h" +#include "mozilla/Vector.h" #include "mozilla/WindowsVersion.h" -#if defined(ACCESSIBILITY) -# include "nsExceptionHandler.h" -#endif // defined(ACCESSIBILITY) #include "nsWindowsHelpers.h" -#include "nsXULAppAPI.h" + +#if defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/EnsureMTA.h" +# include "nsThreadManager.h" +#endif // defined(MOZILLA_INTERNAL_API) #include #include @@ -28,27 +32,65 @@ // This API from oleaut32.dll is not declared in Windows SDK headers extern "C" void __cdecl SetOaNoCache(void); +#if (_WIN32_WINNT < 0x0602) +BOOL WINAPI GetProcessMitigationPolicy( + HANDLE hProcess, PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, + SIZE_T dwLength); +#endif // (_WIN32_WINNT < 0x0602) + namespace mozilla { namespace mscom { -MainThreadRuntime* MainThreadRuntime::sInstance = nullptr; - -MainThreadRuntime::MainThreadRuntime() - : mInitResult(E_UNEXPECTED) -#if defined(ACCESSIBILITY) +ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType) + : mInitResult(CO_E_NOTINITIALIZED), + mIsParentProcess(aProcessType == GeckoProcessType_Default) +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId()) -#endif // defined(ACCESSIBILITY) +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) { +#if defined(MOZILLA_INTERNAL_API) + // If our process is running under Win32k lockdown, we cannot initialize + // COM with single-threaded apartments. This is because STAs create a hidden + // window, which implicitly requires user32 and Win32k, which are blocked. + // Instead we start a multi-threaded apartment and conduct our process-wide + // COM initialization on that MTA background thread. + if (IsWin32kLockedDown()) { + // It is possible that we're running so early that we might need to start + // the thread manager ourselves. + nsresult rv = nsThreadManager::get().Init(); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + if (NS_FAILED(rv)) { + return; + } + + EnsureMTA([this]() -> void { InitInsideApartment(); }); + return; + } +#endif // defined(MOZILLA_INTERNAL_API) + + // Otherwise we initialize a single-threaded apartment on the current thread. + mAptRegion.Init(COINIT_APARTMENTTHREADED); + // We must be the outermost COM initialization on this thread. The COM runtime // cannot be configured once we start manipulating objects - MOZ_ASSERT(mStaRegion.IsValidOutermost()); - if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) { + MOZ_ASSERT(mAptRegion.IsValidOutermost()); + if (!mAptRegion.IsValidOutermost()) { + mInitResult = mAptRegion.GetHResult(); return; } - // We are required to initialize security in order to configure global - // options. + InitInsideApartment(); +} + +void ProcessRuntime::InitInsideApartment() { + ProcessInitLock lock; + if (lock.IsInitialized()) { + // COM has already been initialized by a previous ProcessRuntime instance + return; + } + + // We are required to initialize security prior to configuring global options. mInitResult = InitializeSecurity(); MOZ_ASSERT(SUCCEEDED(mInitResult)); if (FAILED(mInitResult)) { @@ -76,58 +118,25 @@ MainThreadRuntime::MainThreadRuntime() return; } - if (XRE_IsParentProcess()) { - MainThreadClientInfo::Create(getter_AddRefs(mClientInfo)); - } - - MOZ_ASSERT(!sInstance); - sInstance = this; -} - -MainThreadRuntime::~MainThreadRuntime() { - if (mClientInfo) { - mClientInfo->Detach(); - } - - MOZ_ASSERT(sInstance == this); - if (sInstance == this) { - sInstance = nullptr; - } + lock.SetInitialized(); } /* static */ DWORD -MainThreadRuntime::GetClientThreadId() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_IsParentProcess(), "Unsupported outside of parent process"); - if (!XRE_IsParentProcess()) { +ProcessRuntime::GetClientThreadId() { + DWORD callerTid; + HRESULT hr = ::CoGetCallerTID(&callerTid); + // Don't return callerTid unless the call succeeded and returned S_FALSE, + // indicating that the caller originates from a different process. + if (hr != S_FALSE) { return 0; } - // Don't check for a calling executable if the caller is in-process. - // We verify this by asking COM for a call context. If none exists, then - // we must be a local call. - RefPtr serverSecurity; - if (FAILED(::CoGetCallContext(IID_IServerSecurity, - getter_AddRefs(serverSecurity)))) { - return 0; - } - - MOZ_ASSERT(sInstance); - if (!sInstance) { - return 0; - } - - MOZ_ASSERT(sInstance->mClientInfo); - if (!sInstance->mClientInfo) { - return 0; - } - - return sInstance->mClientInfo->GetLastRemoteCallThreadId(); + return callerTid; } HRESULT -MainThreadRuntime::InitializeSecurity() { +ProcessRuntime::InitializeSecurity() { HANDLE rawToken = nullptr; BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken); if (!ok) { @@ -186,7 +195,7 @@ MainThreadRuntime::InitializeSecurity() { BYTE appContainersSid[SECURITY_MAX_SID_SIZE]; DWORD appContainersSidSize = sizeof(appContainersSid); - if (XRE_IsParentProcess() && IsWin8OrLater()) { + if (mIsParentProcess && IsWin8OrLater()) { if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr, appContainersSid, &appContainersSidSize)) { return HRESULT_FROM_WIN32(::GetLastError()); @@ -195,38 +204,43 @@ MainThreadRuntime::InitializeSecurity() { // Grant access to SYSTEM, Administrators, the user, and when running as the // browser process on Windows 8+, all app containers. - EXPLICIT_ACCESS entries[] = { - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(systemSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}, - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, - reinterpret_cast(tokenUser.User.Sid)}}, - // appContainersSid must be the last entry in this array! - {COM_RIGHTS_EXECUTE, - GRANT_ACCESS, - NO_INHERITANCE, - {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, - TRUSTEE_IS_WELL_KNOWN_GROUP, - reinterpret_cast(appContainersSid)}}}; + const size_t kMaxInlineEntries = 4; + mozilla::Vector entries; - ULONG numEntries = ArrayLength(entries); - if (!XRE_IsParentProcess() || !IsWin8OrLater()) { - // Exclude appContainersSid on Windows 7 and non-parent processes. - --numEntries; + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(systemSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast(adminSid)}}); + + Unused << entries.append(EXPLICIT_ACCESS_W{ + COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER, + reinterpret_cast(tokenUser.User.Sid)}}); + + if (mIsParentProcess && IsWin8OrLater()) { + Unused << entries.append( + EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE, + GRANT_ACCESS, + NO_INHERITANCE, + {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, + TRUSTEE_IS_WELL_KNOWN_GROUP, + reinterpret_cast(appContainersSid)}}); } PACL rawDacl = nullptr; - win32Error = ::SetEntriesInAcl(numEntries, entries, nullptr, &rawDacl); + win32Error = + ::SetEntriesInAclW(entries.length(), entries.begin(), nullptr, &rawDacl); if (win32Error != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(win32Error); } @@ -251,5 +265,26 @@ MainThreadRuntime::InitializeSecurity() { RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr); } +#if defined(MOZILLA_INTERNAL_API) + +/* static */ bool +ProcessRuntime::IsWin32kLockedDown() { + static const DynamicallyLinkedFunctionPtr + pGetProcessMitigationPolicy(L"kernel32.dll", "GetProcessMitigationPolicy"); + if (!pGetProcessMitigationPolicy) { + return false; + } + + PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY polInfo; + if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), + ProcessSystemCallDisablePolicy, &polInfo, sizeof(polInfo))) { + return false; + } + + return polInfo.DisallowWin32kSystemCalls; +} + +#endif // defined(MOZILLA_INTERNAL_API) + } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/ProcessRuntime.h b/ipc/mscom/ProcessRuntime.h new file mode 100644 index 000000000000..3d27e8f43d82 --- /dev/null +++ b/ipc/mscom/ProcessRuntime.h @@ -0,0 +1,61 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ProcessRuntime_h +#define mozilla_mscom_ProcessRuntime_h + +#include "mozilla/Attributes.h" +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +# include "mozilla/mscom/ActivationContext.h" +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) +#include "mozilla/mscom/ApartmentRegion.h" +#include "nsXULAppAPI.h" + +namespace mozilla { +namespace mscom { + +class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final { + public: +#if defined(MOZILLA_INTERNAL_API) + ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {} +#endif // defined(MOZILLA_INTERNAL_API) + + explicit ProcessRuntime(GeckoProcessType aProcessType); + ~ProcessRuntime() = default; + + explicit operator bool() const { return SUCCEEDED(mInitResult); } + + ProcessRuntime(ProcessRuntime&) = delete; + ProcessRuntime(ProcessRuntime&&) = delete; + ProcessRuntime& operator=(ProcessRuntime&) = delete; + ProcessRuntime& operator=(ProcessRuntime&&) = delete; + + /** + * @return 0 if call is in-process or resolving the calling thread failed, + * otherwise contains the thread id of the calling thread. + */ + static DWORD GetClientThreadId(); + + private: + void InitInsideApartment(); + HRESULT InitializeSecurity(); + +#if defined(MOZILLA_INTERNAL_API) + static bool IsWin32kLockedDown(); +#endif // defined(MOZILLA_INTERNAL_API) + + HRESULT mInitResult; + bool mIsParentProcess; +#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ActivationContextRegion mActCtxRgn; +#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API) + ApartmentRegion mAptRegion; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntime_h diff --git a/ipc/mscom/Ptr.h b/ipc/mscom/Ptr.h index 9df05b4a0b79..98cbef684f94 100644 --- a/ipc/mscom/Ptr.h +++ b/ipc/mscom/Ptr.h @@ -16,6 +16,8 @@ #include "nsThreadUtils.h" #include "nsXULAppAPI.h" +#include + /** * The glue code in mozilla::mscom often needs to pass around interface pointers * belonging to a different apartment from the current one. We must not touch diff --git a/ipc/mscom/moz.build b/ipc/mscom/moz.build index 5f425ceb806b..71a3cb05f8d5 100644 --- a/ipc/mscom/moz.build +++ b/ipc/mscom/moz.build @@ -7,19 +7,22 @@ EXPORTS.mozilla.mscom += [ 'Aggregation.h', 'AgileReference.h', + 'ApartmentRegion.h', 'AsyncInvoker.h', - 'COMApartmentRegion.h', 'COMPtrHolder.h', 'EnsureMTA.h', - 'MainThreadClientInfo.h', - 'MainThreadRuntime.h', 'Objref.h', 'PassthruProxy.h', + 'ProcessRuntime.h', 'ProxyStream.h', 'Ptr.h', 'Utils.h', ] +DIRS += [ + 'mozglue', +] + SOURCES += [ 'VTableBuilder.c', ] @@ -27,10 +30,9 @@ SOURCES += [ UNIFIED_SOURCES += [ 'AgileReference.cpp', 'EnsureMTA.cpp', - 'MainThreadClientInfo.cpp', - 'MainThreadRuntime.cpp', 'Objref.cpp', 'PassthruProxy.cpp', + 'ProcessRuntime.cpp', 'ProxyStream.cpp', 'RegistrationAnnotator.cpp', 'Utils.cpp', diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp new file mode 100644 index 000000000000..517918f2d87c --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp @@ -0,0 +1,33 @@ +/* -*- 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 "mozilla/mscom/ProcessRuntimeShared.h" +#include "MozglueUtils.h" + +// We allow multiple ProcessRuntime instances to exist simultaneously (even +// on separate threads), but only one should be doing the process-wide +// initialization. These variables provide that mutual exclusion. +static mozilla::glue::Win32SRWLock gLock; +static bool gIsProcessInitialized = false; + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& +BeginProcessRuntimeInit() { + gLock.LockExclusive(); + return gIsProcessInitialized; +} + +MFBT_API void +EndProcessRuntimeInit() { + gLock.UnlockExclusive(); +} + +} // namespace detail +} // namespace mscom +} // namespace mozilla diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.h b/ipc/mscom/mozglue/ProcessRuntimeShared.h new file mode 100644 index 000000000000..a42b1b818e54 --- /dev/null +++ b/ipc/mscom/mozglue/ProcessRuntimeShared.h @@ -0,0 +1,54 @@ +/* -*- 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/. */ + +#ifndef mozilla_mscom_ProcessRuntimeShared_h +#define mozilla_mscom_ProcessRuntimeShared_h + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/Types.h" + +namespace mozilla { +namespace mscom { +namespace detail { + +MFBT_API bool& BeginProcessRuntimeInit(); +MFBT_API void EndProcessRuntimeInit(); + +} // namespace detail + +class MOZ_RAII ProcessInitLock final { + public: + ProcessInitLock() + : mIsProcessInitialized(detail::BeginProcessRuntimeInit()) { + } + + ~ProcessInitLock() { + detail::EndProcessRuntimeInit(); + } + + bool IsInitialized() const { + return mIsProcessInitialized; + } + + void SetInitialized() { + MOZ_ASSERT(!mIsProcessInitialized); + mIsProcessInitialized = true; + } + + ProcessInitLock(const ProcessInitLock&) = delete; + ProcessInitLock(ProcessInitLock&&) = delete; + ProcessInitLock operator=(const ProcessInitLock&) = delete; + ProcessInitLock operator=(ProcessInitLock&&) = delete; + + private: + bool& mIsProcessInitialized; +}; + +} // namespace mscom +} // namespace mozilla + +#endif // mozilla_mscom_ProcessRuntimeShared_h diff --git a/ipc/mscom/mozglue/moz.build b/ipc/mscom/mozglue/moz.build new file mode 100644 index 000000000000..2d444a2e50af --- /dev/null +++ b/ipc/mscom/mozglue/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Library('mscom-mozglue') + +EXPORTS.mozilla.mscom += [ + 'ProcessRuntimeShared.h', +] + +LOCAL_INCLUDES += [ + '/mozglue/build', +] + +DEFINES['IMPL_MFBT'] = True + +UNIFIED_SOURCES += [ + 'ProcessRuntimeShared.cpp', +] diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 4a5a18c659a4..fd3db244211f 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -84,6 +84,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']: EXPORTS.mozilla.glue += [ 'WindowsDllServices.h', ] + USE_LIBS += [ + 'mscom-mozglue', + ] EXPORTS.mozilla += [ 'arm.h', diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index fc91477d20cb..9454ea1dd871 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -110,7 +110,7 @@ # include "cairo/cairo-features.h" # include "mozilla/WindowsDllBlocklist.h" # include "mozilla/WinHeaderOnlyUtils.h" -# include "mozilla/mscom/MainThreadRuntime.h" +# include "mozilla/mscom/ProcessRuntime.h" # include "mozilla/widget/AudioSession.h" # if defined(MOZ_LAUNCHER_PROCESS) @@ -4803,7 +4803,7 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) { // trivial COM is run in the application. Since these settings may affect // stability, we should instantiate COM ASAP so that we can ensure that these // global settings are configured before anything can interfere. - mozilla::mscom::MainThreadRuntime msCOMRuntime; + mozilla::mscom::ProcessRuntime msCOMRuntime; #endif // init diff --git a/widget/windows/JumpListBuilder.cpp b/widget/windows/JumpListBuilder.cpp index 48c419828a36..32cd7d03be41 100644 --- a/widget/windows/JumpListBuilder.cpp +++ b/widget/windows/JumpListBuilder.cpp @@ -23,7 +23,7 @@ #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "mozilla/dom/Promise.h" -#include "mozilla/mscom/COMApartmentRegion.h" +#include "mozilla/mscom/ApartmentRegion.h" #include "mozilla/mscom/EnsureMTA.h" #include From 74c580a4c5427330fae3d45b3fdcf072ba669a88 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 14 Feb 2019 10:43:35 +0000 Subject: [PATCH 56/84] Bug 1527733 - Remove special XUL DOM tree traversal. r=smaug Move functionality out of XULDocument::AddElementToDocumentPost: 1) Convert all XUL link elements into HTML link elements which have code to handle when they are added to the DOM. 2) Move handling of the end of a linkset element into nsXULElement's DoneAddingChildren callback. 3) Move document direction reset to where the root element is created. Differential Revision: https://phabricator.services.mozilla.com/D19739 --HG-- extra : moz-landing-system : lando --- browser/base/content/aboutDialog.xul | 4 +- browser/base/content/safeMode.xul | 5 +- browser/base/content/sanitize.xul | 2 +- .../preferences/applicationManager.xul | 3 +- browser/components/preferences/blocklists.xul | 4 +- .../preferences/browserLanguages.xul | 5 +- .../components/preferences/clearSiteData.xul | 5 +- browser/components/preferences/colors.xul | 2 +- browser/components/preferences/connection.xul | 6 +- browser/components/preferences/containers.xul | 3 +- browser/components/preferences/fonts.xul | 2 +- .../preferences/in-content/preferences.xul | 34 +++---- .../preferences/in-content/syncDisconnect.xul | 5 +- browser/components/preferences/languages.xul | 3 +- .../components/preferences/permissions.xul | 3 +- browser/components/preferences/sanitize.xul | 4 +- .../components/preferences/selectBookmark.xul | 3 +- .../preferences/siteDataRemoveSelected.xul | 5 +- .../preferences/siteDataSettings.xul | 5 +- .../preferences/sitePermissions.xul | 5 +- .../components/preferences/translation.xul | 3 +- dom/xbl/nsXBLBinding.cpp | 3 +- dom/xul/XULDocument.cpp | 88 +++---------------- dom/xul/XULDocument.h | 11 +-- dom/xul/nsXULElement.cpp | 9 ++ dom/xul/nsXULElement.h | 1 + intl/l10n/test/dom/test_docl10n.xul | 2 +- .../pki/resources/content/certManager.xul | 3 +- .../pki/resources/content/certViewer.xul | 2 +- .../pki/resources/content/deletecert.xul | 3 +- .../pki/resources/content/device_manager.xul | 3 +- .../pki/resources/content/editcacert.xul | 3 +- .../pki/resources/content/exceptionDialog.xul | 5 +- .../pki/resources/content/load_device.xul | 3 +- .../components/viewconfig/content/config.xul | 3 +- toolkit/content/customElements.js | 3 +- toolkit/content/resetProfile.xul | 5 +- .../mozapps/extensions/content/extensions.xul | 4 +- toolkit/mozapps/preferences/changemp.xul | 4 +- toolkit/mozapps/preferences/removemp.xul | 3 +- toolkit/mozapps/update/content/history.xul | 3 +- 41 files changed, 117 insertions(+), 155 deletions(-) diff --git a/browser/base/content/aboutDialog.xul b/browser/base/content/aboutDialog.xul index ab284bf4e8ab..f483bf58943c 100644 --- a/browser/base/content/aboutDialog.xul +++ b/browser/base/content/aboutDialog.xul @@ -35,8 +35,8 @@ #endif - - + + + + + + + + + + + + + + + Mozilla Bug 1525980 + + +

+ +
+  
+ + + diff --git a/accessible/windows/msaa/nsEventMap.h b/accessible/windows/msaa/nsEventMap.h index 9ab482cb1833..49cfbbc57d7e 100644 --- a/accessible/windows/msaa/nsEventMap.h +++ b/accessible/windows/msaa/nsEventMap.h @@ -101,5 +101,6 @@ static const uint32_t gWinEventMap[] = { kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED EVENT_OBJECT_VALUECHANGE, // nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_SCROLLING + kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_ANNOUNCEMENT // clang-format on }; diff --git a/accessible/xpcom/AccEvents.conf b/accessible/xpcom/AccEvents.conf index 7247a6d18820..0ccf0e09d71a 100644 --- a/accessible/xpcom/AccEvents.conf +++ b/accessible/xpcom/AccEvents.conf @@ -15,5 +15,6 @@ simple_events = [ 'ObjectAttributeChangedEvent', 'TableChangeEvent', 'VirtualCursorChangeEvent', - 'ScrollingEvent' + 'ScrollingEvent', + 'AnnouncementEvent' ] diff --git a/accessible/xpcom/xpcAccessible.cpp b/accessible/xpcom/xpcAccessible.cpp index 6c2d9ceb0176..9de7ce03c442 100644 --- a/accessible/xpcom/xpcAccessible.cpp +++ b/accessible/xpcom/xpcAccessible.cpp @@ -757,3 +757,13 @@ xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) { return NS_OK; } + +NS_IMETHODIMP +xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) { + if (IntlGeneric().IsProxy()) { + return NS_ERROR_NOT_IMPLEMENTED; + } else { + Intl()->Announce(aAnnouncement, aPriority); + } + return NS_OK; +} diff --git a/accessible/xpcom/xpcAccessible.h b/accessible/xpcom/xpcAccessible.h index e2908039a914..914a01c5c1ac 100644 --- a/accessible/xpcom/xpcAccessible.h +++ b/accessible/xpcom/xpcAccessible.h @@ -82,6 +82,8 @@ class xpcAccessible : public nsIAccessible { NS_IMETHOD ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) final; + NS_IMETHOD Announce(const nsAString& aAnnouncement, uint16_t aPriority) final; + protected: xpcAccessible() {} virtual ~xpcAccessible() {} From 773b9d611aa3e1b95a2145ee1e70535c61b11a2b Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 14 Feb 2019 17:42:47 +0000 Subject: [PATCH 59/84] Bug 1525980 - Make announcement events work over IPC. r=Jamie Differential Revision: https://phabricator.services.mozilla.com/D19061 --HG-- extra : moz-landing-system : lando --- accessible/generic/Accessible.cpp | 8 +++++ accessible/ipc/DocAccessibleParent.cpp | 29 +++++++++++++++++++ accessible/ipc/DocAccessibleParent.h | 6 ++++ accessible/ipc/ProxyAccessibleShared.h | 2 ++ accessible/ipc/other/DocAccessibleChild.cpp | 11 +++++++ accessible/ipc/other/DocAccessibleChild.h | 4 +++ accessible/ipc/other/PDocAccessible.ipdl | 4 +++ accessible/ipc/other/ProxyAccessible.cpp | 5 ++++ accessible/tests/browser/e10s/browser.ini | 2 ++ .../e10s/browser_events_announcement.js | 23 +++++++++++++++ accessible/tests/browser/events.js | 13 +++++---- accessible/xpcom/xpcAccessible.cpp | 8 ++++- 12 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 accessible/tests/browser/e10s/browser_events_announcement.js diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index ec22dcb6f549..db87ff8b640c 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -914,6 +914,14 @@ nsresult Accessible::HandleAccEvent(AccEvent* aEvent) { scrollingEvent->MaxScrollY()); break; } +#if !defined(XP_WIN) + case nsIAccessibleEvent::EVENT_ANNOUNCEMENT: { + AccAnnouncementEvent* announcementEvent = downcast_accEvent(aEvent); + ipcDoc->SendAnnouncementEvent(id, announcementEvent->Announcement(), + announcementEvent->Priority()); + break; + } +#endif default: ipcDoc->SendEvent(id, aEvent->GetEventType()); } diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp index b6c3a74597a6..52029a29d512 100644 --- a/accessible/ipc/DocAccessibleParent.cpp +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -431,6 +431,35 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvScrollingEvent( return IPC_OK(); } +#if !defined(XP_WIN) +mozilla::ipc::IPCResult DocAccessibleParent::RecvAnnouncementEvent( + const uint64_t& aID, const nsString& aAnnouncement, + const uint16_t& aPriority) { + ProxyAccessible* target = GetAccessible(aID); + + if (!target) { + NS_ERROR("no proxy for event!"); + return IPC_OK(); + } + + // XXX: A future patch will add platform support for this event type. + // Right now, we just need to support XPC for testing. + + if (!nsCoreUtils::AccEventObserversExist()) { + return IPC_OK(); + } + + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + RefPtr event = new xpcAccAnnouncementEvent( + nsIAccessibleEvent::EVENT_ANNOUNCEMENT, xpcAcc, doc, nullptr, false, + aAnnouncement, aPriority); + nsCoreUtils::DispatchAccEvent(std::move(event)); + + return IPC_OK(); +} +#endif + mozilla::ipc::IPCResult DocAccessibleParent::RecvRoleChangedEvent( const a11y::role& aRole) { if (mShutdown) { diff --git a/accessible/ipc/DocAccessibleParent.h b/accessible/ipc/DocAccessibleParent.h index 80e76aba7fcc..de3b63d155a0 100644 --- a/accessible/ipc/DocAccessibleParent.h +++ b/accessible/ipc/DocAccessibleParent.h @@ -117,6 +117,12 @@ class DocAccessibleParent : public ProxyAccessible, const uint32_t& aScrollY, const uint32_t& aMaxScrollX, const uint32_t& aMaxScrollY) override; +#if !defined(XP_WIN) + virtual mozilla::ipc::IPCResult RecvAnnouncementEvent( + const uint64_t& aID, const nsString& aAnnouncement, + const uint16_t& aPriority) override; +#endif + mozilla::ipc::IPCResult RecvRoleChangedEvent(const a11y::role& aRole) final; virtual mozilla::ipc::IPCResult RecvBindChildDoc( diff --git a/accessible/ipc/ProxyAccessibleShared.h b/accessible/ipc/ProxyAccessibleShared.h index c1458fa363e3..448182348d1b 100644 --- a/accessible/ipc/ProxyAccessibleShared.h +++ b/accessible/ipc/ProxyAccessibleShared.h @@ -68,6 +68,8 @@ int32_t GetLevelInternal(); void ScrollTo(uint32_t aScrollType); void ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY); +void Announce(const nsString& aAnnouncement, uint16_t aPriority); + int32_t CaretLineNumber(); int32_t CaretOffset(); void SetCaretOffset(int32_t aOffset); diff --git a/accessible/ipc/other/DocAccessibleChild.cpp b/accessible/ipc/other/DocAccessibleChild.cpp index b1400a1cfd89..017e732b0bf6 100644 --- a/accessible/ipc/other/DocAccessibleChild.cpp +++ b/accessible/ipc/other/DocAccessibleChild.cpp @@ -263,6 +263,17 @@ mozilla::ipc::IPCResult DocAccessibleChild::RecvScrollToPoint( return IPC_OK(); } +mozilla::ipc::IPCResult DocAccessibleChild::RecvAnnounce( + const uint64_t& aID, const nsString& aAnnouncement, + const uint16_t& aPriority) { + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->Announce(aAnnouncement, aPriority); + } + + return IPC_OK(); +} + mozilla::ipc::IPCResult DocAccessibleChild::RecvCaretLineNumber( const uint64_t& aID, int32_t* aLineNumber) { HyperTextAccessible* acc = IdToHyperTextAccessible(aID); diff --git a/accessible/ipc/other/DocAccessibleChild.h b/accessible/ipc/other/DocAccessibleChild.h index 0c5c961f5e76..a1d8ca45b650 100644 --- a/accessible/ipc/other/DocAccessibleChild.h +++ b/accessible/ipc/other/DocAccessibleChild.h @@ -93,6 +93,10 @@ class DocAccessibleChild : public DocAccessibleChildBase { const int32_t& aX, const int32_t& aY) override; + virtual mozilla::ipc::IPCResult RecvAnnounce( + const uint64_t& aID, const nsString& aAnnouncement, + const uint16_t& aPriority) override; + virtual mozilla::ipc::IPCResult RecvCaretLineNumber( const uint64_t& aID, int32_t* aLineNumber) override; virtual mozilla::ipc::IPCResult RecvCaretOffset(const uint64_t& aID, diff --git a/accessible/ipc/other/PDocAccessible.ipdl b/accessible/ipc/other/PDocAccessible.ipdl index adcb103cff02..2c61f51b6a2c 100644 --- a/accessible/ipc/other/PDocAccessible.ipdl +++ b/accessible/ipc/other/PDocAccessible.ipdl @@ -97,6 +97,9 @@ parent: async ScrollingEvent(uint64_t aID, uint64_t aType, uint32_t aScrollX, uint32_t aScrollY, uint32_t aMaxScrollX, uint32_t aMaxScrollY); + async AnnouncementEvent(uint64_t aID, + nsString aAnnouncement, + uint16_t aPriority); /* * Tell the parent document to bind the existing document as a new child @@ -134,6 +137,7 @@ child: async ScrollTo(uint64_t aID, uint32_t aScrollType); async ScrollToPoint(uint64_t aID, uint32_t aScrollType, int32_t aX, int32_t aY); + async Announce(uint64_t aID, nsString aAnnouncement, uint16_t aPriority); // AccessibleText diff --git a/accessible/ipc/other/ProxyAccessible.cpp b/accessible/ipc/other/ProxyAccessible.cpp index ef7e2431f6d5..1ee5f9b686df 100644 --- a/accessible/ipc/other/ProxyAccessible.cpp +++ b/accessible/ipc/other/ProxyAccessible.cpp @@ -126,6 +126,11 @@ void ProxyAccessible::ScrollToPoint(uint32_t aScrollType, int32_t aX, Unused << mDoc->SendScrollToPoint(mID, aScrollType, aX, aY); } +void ProxyAccessible::Announce(const nsString& aAnnouncement, + uint16_t aPriority) { + Unused << mDoc->SendAnnounce(mID, aAnnouncement, aPriority); +} + int32_t ProxyAccessible::CaretLineNumber() { int32_t line = -1; Unused << mDoc->SendCaretOffset(mID, &line); diff --git a/accessible/tests/browser/e10s/browser.ini b/accessible/tests/browser/e10s/browser.ini index 91875e5d181d..6a9c6a4edb93 100644 --- a/accessible/tests/browser/e10s/browser.ini +++ b/accessible/tests/browser/e10s/browser.ini @@ -23,6 +23,8 @@ skip-if = (e10s && os == 'win') || (os == 'mac' && debug) # Bug 1338034, leaks # [browser_caching_value.js] # Events tests +[browser_events_announcement.js] +skip-if = e10s && os == 'win' # Bug 1288839 [browser_events_caretmove.js] [browser_events_hide.js] [browser_events_show.js] diff --git a/accessible/tests/browser/e10s/browser_events_announcement.js b/accessible/tests/browser/e10s/browser_events_announcement.js new file mode 100644 index 000000000000..406727dcdff8 --- /dev/null +++ b/accessible/tests/browser/e10s/browser_events_announcement.js @@ -0,0 +1,23 @@ +/* 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"; + +addAccessibleTask(`

abc

`, + async function(browser, accDoc) { + let acc = findAccessibleChildByID(accDoc, "p"); + let onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc); + acc.announce("please", nsIAccessibleAnnouncementEvent.POLITE); + let evt = await onAnnounce; + evt.QueryInterface(nsIAccessibleAnnouncementEvent); + is(evt.announcement, "please", "announcement matches."); + is(evt.priority, nsIAccessibleAnnouncementEvent.POLITE, "priority matches"); + + onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc); + acc.announce("do it", nsIAccessibleAnnouncementEvent.ASSERTIVE); + evt = await onAnnounce; + evt.QueryInterface(nsIAccessibleAnnouncementEvent); + is(evt.announcement, "do it", "announcement matches."); + is(evt.priority, nsIAccessibleAnnouncementEvent.ASSERTIVE, "priority matches"); + }); diff --git a/accessible/tests/browser/events.js b/accessible/tests/browser/events.js index e59deb576ae5..e50c17fbac30 100644 --- a/accessible/tests/browser/events.js +++ b/accessible/tests/browser/events.js @@ -9,15 +9,16 @@ /* import-globals-from shared-head.js */ /* import-globals-from ../mochitest/common.js */ -/* exported EVENT_REORDER, EVENT_SCROLLING, EVENT_SCROLLING_END, EVENT_SHOW, - EVENT_TEXT_INSERTED, EVENT_TEXT_REMOVED, - EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, EVENT_TEXT_CARET_MOVED, - EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE, - EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS, - EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, +/* exported EVENT_ANNOUNCEMENT, EVENT_REORDER, EVENT_SCROLLING, + EVENT_SCROLLING_END, EVENT_SHOW, EVENT_TEXT_INSERTED, + EVENT_TEXT_REMOVED, EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, + EVENT_TEXT_CARET_MOVED, EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, + EVENT_STATE_CHANGE, EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, + EVENT_FOCUS, EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, UnexpectedEvents, contentSpawnMutation, waitForEvent, waitForEvents, waitForOrderedEvents */ +const EVENT_ANNOUNCEMENT = nsIAccessibleEvent.EVENT_ANNOUNCEMENT; const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE; const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE; const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER; diff --git a/accessible/xpcom/xpcAccessible.cpp b/accessible/xpcom/xpcAccessible.cpp index 9de7ce03c442..76e72b420eaf 100644 --- a/accessible/xpcom/xpcAccessible.cpp +++ b/accessible/xpcom/xpcAccessible.cpp @@ -760,10 +760,16 @@ xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) { NS_IMETHODIMP xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) { - if (IntlGeneric().IsProxy()) { + if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) { +#if defined(XP_WIN) return NS_ERROR_NOT_IMPLEMENTED; +#else + nsString announcement(aAnnouncement); + proxy->Announce(announcement, aPriority); +#endif } else { Intl()->Announce(aAnnouncement, aPriority); } + return NS_OK; } From ed2e78aef0067ab2d7364d6a569f323b76402827 Mon Sep 17 00:00:00 2001 From: Randall Barker Date: Thu, 14 Feb 2019 19:04:06 +0000 Subject: [PATCH 60/84] Bug 1508372 - Add scrollTo and scrollBy to PanZoomController r=geckoview-reviewers,snorp,esawin The scrollTo() and scrollBy() functions in the PanZoomController may be used to scroll the root document in GeckoView. Differential Revision: https://phabricator.services.mozilla.com/D18898 --HG-- extra : moz-landing-system : lando --- .../chrome/geckoview/GeckoViewContentChild.js | 52 ++++++ mobile/android/geckoview/api.txt | 24 +++ .../src/androidTest/assets/www/scroll.html | 35 ++++ .../mozilla/geckoview/test/BaseSessionTest.kt | 1 + .../geckoview/test/PanZoomControllerTest.kt | 64 +++++++ .../mozilla/geckoview/PanZoomController.java | 98 +++++++++++ .../org/mozilla/geckoview/ScreenLength.java | 156 ++++++++++++++++++ .../mozilla/geckoview/doc-files/CHANGELOG.md | 4 +- .../modules/geckoview/GeckoViewContent.jsm | 8 + 9 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 mobile/android/geckoview/src/androidTest/assets/www/scroll.html create mode 100644 mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt create mode 100644 mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java diff --git a/mobile/android/chrome/geckoview/GeckoViewContentChild.js b/mobile/android/chrome/geckoview/GeckoViewContentChild.js index d2aa1ff58183..2f1454410218 100644 --- a/mobile/android/chrome/geckoview/GeckoViewContentChild.js +++ b/mobile/android/chrome/geckoview/GeckoViewContentChild.js @@ -7,6 +7,17 @@ const {GeckoViewChildModule} = ChromeUtils.import("resource://gre/modules/GeckoV var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +// This needs to match ScreenLength.java +const SCREEN_LENGTH_TYPE_PIXEL = 0; +const SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH = 1; +const SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT = 2; +const SCREEN_LENGTH_DOCUMENT_WIDTH = 3; +const SCREEN_LENGTH_DOCUMENT_HEIGHT = 4; + +// This need to match PanZoomController.java +const SCROLL_BEHAVIOR_SMOOTH = 0; +const SCROLL_BEHAVIOR_AUTO = 1; + XPCOMUtils.defineLazyModuleGetters(this, { FormLikeFactory: "resource://gre/modules/FormLikeFactory.jsm", GeckoViewAutoFill: "resource://gre/modules/GeckoViewAutoFill.jsm", @@ -33,6 +44,8 @@ class GeckoViewContentChild extends GeckoViewChildModule { this.messageManager.addMessageListener("GeckoView:SetActive", this); this.messageManager.addMessageListener("GeckoView:UpdateInitData", this); this.messageManager.addMessageListener("GeckoView:ZoomToInput", this); + this.messageManager.addMessageListener("GeckoView:ScrollBy", this); + this.messageManager.addMessageListener("GeckoView:ScrollTo", this); const options = { mozSystemGroup: true, @@ -109,6 +122,31 @@ class GeckoViewContentChild extends GeckoViewChildModule { return {history, formdata, scrolldata}; } + toPixels(aLength, aType) { + if (aType === SCREEN_LENGTH_TYPE_PIXEL) { + return aLength; + } else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH) { + return aLength * content.innerWidth; + } else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT) { + return aLength * content.innerHeight; + } else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) { + return aLength * content.document.body.scrollWidth; + } else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) { + return aLength * content.document.body.scrollHeight; + } + + return aLength; + } + + toScrollBehavior(aBehavior) { + if (aBehavior === SCROLL_BEHAVIOR_SMOOTH) { + return "smooth"; + } else if (aBehavior === SCROLL_BEHAVIOR_AUTO) { + return "auto"; + } + return "smooth"; + } + receiveMessage(aMsg) { debug `receiveMessage: ${aMsg.name}`; @@ -246,6 +284,20 @@ class GeckoViewContentChild extends GeckoViewChildModule { Services.obs.notifyObservers( docShell, "geckoview-content-global-transferred"); break; + case "GeckoView:ScrollBy": + content.scrollBy({ + top: this.toPixels(aMsg.data.heightValue, aMsg.data.heightType), + left: this.toPixels(aMsg.data.widthValue, aMsg.data.widthType), + behavior: this.toScrollBehavior(aMsg.data.behavior), + }); + break; + case "GeckoView:ScrollTo": + content.scrollTo({ + top: this.toPixels(aMsg.data.heightValue, aMsg.data.heightType), + left: this.toPixels(aMsg.data.widthValue, aMsg.data.widthType), + behavior: this.toScrollBehavior(aMsg.data.behavior), + }); + break; } } diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index 015a129d8d3a..a8698afb9a12 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -832,8 +832,16 @@ package org.mozilla.geckoview { method public boolean onMotionEvent(@android.support.annotation.NonNull android.view.MotionEvent); method public boolean onMouseEvent(@android.support.annotation.NonNull android.view.MotionEvent); method public boolean onTouchEvent(@android.support.annotation.NonNull android.view.MotionEvent); + method @android.support.annotation.UiThread public void scrollBy(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength); + method @android.support.annotation.UiThread public void scrollBy(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, int); + method @android.support.annotation.UiThread public void scrollTo(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength); + method @android.support.annotation.UiThread public void scrollTo(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, int); + method @android.support.annotation.UiThread public void scrollToBottom(); + method @android.support.annotation.UiThread public void scrollToTop(); method public void setIsLongpressEnabled(boolean); method public void setScrollFactor(float); + field public static final int SCROLL_BEHAVIOR_AUTO = 1; + field public static final int SCROLL_BEHAVIOR_SMOOTH = 0; } public abstract class RuntimeSettings implements android.os.Parcelable { @@ -854,6 +862,22 @@ package org.mozilla.geckoview { method @android.support.annotation.AnyThread @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoResult getSnapshots(boolean); } + public class ScreenLength { + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength bottom(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromPixels(double); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromViewportHeight(double); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromViewportWidth(double); + method @android.support.annotation.AnyThread public int getType(); + method @android.support.annotation.AnyThread public double getValue(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength top(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength zero(); + field public static final int DOCUMENT_HEIGHT = 4; + field public static final int DOCUMENT_WIDTH = 3; + field public static final int PIXEL = 0; + field public static final int VIEWPORT_HEIGHT = 2; + field public static final int VIEWPORT_WIDTH = 1; + } + @android.support.annotation.UiThread public class SessionAccessibility { method @android.support.annotation.Nullable public android.view.View getView(); method public boolean onMotionEvent(@android.support.annotation.NonNull android.view.MotionEvent); diff --git a/mobile/android/geckoview/src/androidTest/assets/www/scroll.html b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html new file mode 100644 index 000000000000..915f4dab3c90 --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt index 432b61b7050b..3caad41a15bd 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt @@ -52,6 +52,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { const val IFRAME_REDIRECT_LOCAL = "/assets/www/iframe_redirect_local.html" const val IFRAME_REDIRECT_AUTOMATION = "/assets/www/iframe_redirect_automation.html" const val AUTOPLAY_PATH = "/assets/www/autoplay.html" + const val SCROLL_TEST_PATH = "/assets/www/scroll.html" } @get:Rule val sessionRule = GeckoSessionTestRule() diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt new file mode 100644 index 000000000000..0478f56cb77b --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt @@ -0,0 +1,64 @@ +package org.mozilla.geckoview.test + +import org.mozilla.geckoview.ScreenLength +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay + +import android.support.test.filters.MediumTest +import android.support.test.runner.AndroidJUnit4 +import org.hamcrest.Matchers.* +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.geckoview.PanZoomController + +@RunWith(AndroidJUnit4::class) +@MediumTest +class PanZoomControllerTest : BaseSessionTest() { + private val errorEpsilon = 3.0 + @WithDevToolsAPI + @WithDisplay(width = 100, height = 100) + @Test + fun scrollBy() { + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vh = sessionRule.evaluateJS(mainSession, "window.innerHeight") as Double + assertThat("Viewport height is not zero", vh, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollBy(ScreenLength.zero(), ScreenLength.fromViewportHeight(1.0), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollBy should have scrolled along y axis one viewport", scrollY, closeTo(vh, errorEpsilon)) + + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vw = sessionRule.evaluateJS(mainSession, "window.innerWidth") as Double + assertThat("Viewport width is not zero", vw, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollBy(ScreenLength.fromViewportWidth(1.0), ScreenLength.zero(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollX = sessionRule.evaluateJS(mainSession, "window.scrollX") as Double + assertThat("scrollBy should have scrolled along x axis one viewport", scrollX, closeTo(vw, errorEpsilon)) + } + + @WithDevToolsAPI + @WithDisplay(width = 100, height = 100) + @Test + fun scrollTo() { + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vh = sessionRule.evaluateJS(mainSession, "window.innerHeight") as Double + val scrollHeight = sessionRule.evaluateJS(mainSession, "window.document.body.scrollHeight") as Double + assertThat("Viewport height is not zero", vh, greaterThan(0.0)) + assertThat("scrollHeight height is not zero", scrollHeight, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollTo(ScreenLength.zero(), ScreenLength.bottom(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + var scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollTo should have scrolled to bottom", scrollY, closeTo(scrollHeight - vh, 3.0)) + + sessionRule.session.panZoomController.scrollTo(ScreenLength.zero(), ScreenLength.top(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollTo should have scrolled to top", scrollY, closeTo(0.0, errorEpsilon)) + + val vw = sessionRule.evaluateJS(mainSession, "window.innerWidth") as Double + val scrollWidth = sessionRule.evaluateJS(mainSession, "window.document.body.scrollWidth") as Double + + sessionRule.session.panZoomController.scrollTo(ScreenLength.fromViewportWidth(1.0), ScreenLength.zero(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollX = sessionRule.evaluateJS(mainSession, "window.scrollX") as Double + assertThat("scrollTo should have scrolled to right", scrollX, closeTo(scrollWidth - vw, errorEpsilon)) + } +} \ No newline at end of file diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java index 73176b13ecb7..6c8bf52c8db7 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java @@ -7,17 +7,22 @@ package org.mozilla.geckoview; import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.mozglue.JNIObject; +import org.mozilla.gecko.util.GeckoBundle; import org.mozilla.gecko.util.ThreadUtils; import android.graphics.Rect; import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.UiThread; +import android.support.annotation.IntDef; import android.util.Log; import android.util.Pair; import android.view.MotionEvent; import android.view.InputDevice; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + import java.util.ArrayList; @UiThread @@ -33,6 +38,19 @@ public class PanZoomController extends JNIObject { private float mPointerScrollFactor = 64.0f; private long mLastDownTime; + @Retention(RetentionPolicy.SOURCE) + @IntDef({SCROLL_BEHAVIOR_SMOOTH, SCROLL_BEHAVIOR_AUTO}) + /* package */ @interface ScrollBehaviorType {} + + /** + * Specifies smooth scrolling which animates content to the desired scroll position. + */ + public static final int SCROLL_BEHAVIOR_SMOOTH = 0; + /** + * Specifies auto scrolling which jumps content to the desired scroll position. + */ + public static final int SCROLL_BEHAVIOR_AUTO = 1; + private SynthesizedEventState mPointerState; private ArrayList> mQueuedEvents; @@ -530,4 +548,84 @@ public class PanZoomController extends JNIObject { PointerInfo.RESERVED_MOUSE_POINTER_ID, eventType, clientX, clientY, 0, 0); } + + /** + * Scroll the document body by an offset from the current scroll position. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + * + * @param width {@link ScreenLength} offset to scroll along X axis. + * @param height {@link ScreenLength} offset to scroll along Y axis. + */ + @UiThread + public void scrollBy(@NonNull ScreenLength width, @NonNull ScreenLength height) { + scrollBy(width, height, SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll the document body by an offset from the current scroll position. + * + * @param width {@link ScreenLength} offset to scroll along X axis. + * @param height {@link ScreenLength} offset to scroll along Y axis. + * @param behavior ScrollBehaviorType One of {@link #SCROLL_BEHAVIOR_SMOOTH}, {@link #SCROLL_BEHAVIOR_AUTO}, + * that specifies how to scroll the content. + */ + @UiThread + public void scrollBy(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = buildScrollMessage(width, height, behavior); + mSession.getEventDispatcher().dispatch("GeckoView:ScrollBy", msg); + } + + /** + * Scroll the document body to an absolute position. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + * + * @param width {@link ScreenLength} position to scroll along X axis. + * @param height {@link ScreenLength} position to scroll along Y axis. + */ + @UiThread + public void scrollTo(@NonNull ScreenLength width, @NonNull ScreenLength height) { + scrollTo(width, height, SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll the document body to an absolute position. + * + * @param width {@link ScreenLength} position to scroll along X axis. + * @param height {@link ScreenLength} position to scroll along Y axis. + * @param behavior ScrollBehaviorType One of {@link #SCROLL_BEHAVIOR_SMOOTH}, {@link #SCROLL_BEHAVIOR_AUTO}, + * that specifies how to scroll the content. + */ + @UiThread + public void scrollTo(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = buildScrollMessage(width, height, behavior); + mSession.getEventDispatcher().dispatch("GeckoView:ScrollTo", msg); + } + + /** + * Scroll to the top left corner of the screen. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + */ + @UiThread + public void scrollToTop() { + scrollTo(ScreenLength.zero(), ScreenLength.top(), SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll to the bottom left corner of the screen. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + */ + @UiThread + public void scrollToBottom() { + scrollTo(ScreenLength.zero(), ScreenLength.bottom(), SCROLL_BEHAVIOR_SMOOTH); + } + + private GeckoBundle buildScrollMessage(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = new GeckoBundle(); + msg.putDouble("widthValue", width.getValue()); + msg.putInt("widthType", width.getType()); + msg.putDouble("heightValue", height.getValue()); + msg.putInt("heightType", height.getType()); + msg.putInt("behavior", behavior); + return msg; + } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java new file mode 100644 index 000000000000..73422d7bf88a --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java @@ -0,0 +1,156 @@ +/* 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/. */ + +package org.mozilla.geckoview; + +import android.support.annotation.AnyThread; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * ScreenLength is a class that represents a length on the screen using different units. + * The default unit is a pixel. However lengths may be also represented by a dimension + * of the visual viewport or of the full scroll size of the root document. + */ +public class ScreenLength { + @Retention(RetentionPolicy.SOURCE) + @IntDef({PIXEL, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, DOCUMENT_WIDTH, DOCUMENT_HEIGHT}) + /* package */ @interface ScreenLengthType {} + + /** + * Pixel units. + */ + public static final int PIXEL = 0; + /** + * Units are in visual viewport width. If the visual viewport is 100 pixels wide, then a value + * of 2.0 would represent a length of 200 pixels. + * @see MDN Visual Viewport + */ + public static final int VIEWPORT_WIDTH = 1; + /** + * Units are in visual viewport height. If the visual viewport is 100 pixels high, then a value + * of 2.0 would represent a length of 200 pixels. + * @see MDN Visual Viewport + */ + public static final int VIEWPORT_HEIGHT = 2; + /** + * Units represent the entire scrollable documents width. If the document is 1000 pixels wide + * then a value of 1.0 would represent 1000 pixels. + */ + public static final int DOCUMENT_WIDTH = 3; + /** + * Units represent the entire scrollable documents height. If the document is 1000 pixels tall + * then a value of 1.0 would represent 1000 pixels. + */ + public static final int DOCUMENT_HEIGHT = 4; + + /** + * Create a ScreenLength of zero pixels length. + * Type is {@link #PIXEL}. + * @return ScreenLength of zero length. + */ + @NonNull + @AnyThread + public static ScreenLength zero() { + return new ScreenLength(0.0, PIXEL); + } + + /** + * Create a ScreenLength of zero pixels length. + * Type is {@link #PIXEL}. Can be used to scroll to the top of a page when used with + * PanZoomController.scrollTo() + * @return ScreenLength of zero length. + */ + @NonNull + @AnyThread + public static ScreenLength top() { + return zero(); + } + + /** + * Create a ScreenLength of the documents height. + * Type is {@link #DOCUMENT_HEIGHT}. Can be used to scroll to the bottom of a page when used with + * {@link PanZoomController#scrollTo(ScreenLength, ScreenLength)} + * @return ScreenLength of document height. + */ + @NonNull + @AnyThread + public static ScreenLength bottom() { + return new ScreenLength(1.0, DOCUMENT_HEIGHT); + } + + /** + * Create a ScreenLength of a specific length. + * Type is {@link #PIXEL}. + * @param value Pixel length. + * @return ScreenLength of document height. + */ + @NonNull + @AnyThread + public static ScreenLength fromPixels(final double value) { + return new ScreenLength(value, PIXEL); + } + + /** + * Create a ScreenLength that uses the visual viewport width as units. + * Type is {@link #VIEWPORT_WIDTH}. Can be used with {@link PanZoomController#scrollBy(ScreenLength, ScreenLength)} + * to scroll a value of the width of visual viewport content. + * @param value Factor used to calculate length. A value of 2.0 would indicate a length + * twice as long as the length of the visual viewports width. + * @return ScreenLength of specifying a length of value * visual viewport width. + */ + @NonNull + @AnyThread + public static ScreenLength fromViewportWidth(final double value) { + return new ScreenLength(value, VIEWPORT_WIDTH); + } + + /** + * Create a ScreenLength that uses the visual viewport width as units. + * Type is {@link #VIEWPORT_HEIGHT}. Can be used with {@link PanZoomController#scrollBy(ScreenLength, ScreenLength)} + * to scroll a value of the height of visual viewport content. + * @param value Factor used to calculate length. A value of 2.0 would indicate a length + * twice as long as the length of the visual viewports height. + * @return ScreenLength of specifying a length of value * visual viewport width. + */ + @NonNull + @AnyThread + public static ScreenLength fromViewportHeight(final double value) { + return new ScreenLength(value, VIEWPORT_HEIGHT); + } + + private final double mValue; + @ScreenLengthType private final int mType; + + /* package */ ScreenLength(final double value, @ScreenLengthType final int type) { + mValue = value; + mType = type; + } + + /** + * Returns the scalar value used to calculate length. + * The units of the returned valued are defined by what is returned by + * {@link #getType()} + * @return Scalar value of the length. + */ + @AnyThread + public double getValue() { + return mValue; + } + + /** + * Returns the unit type of the length + * The length can be one of the following: + * {@link #PIXEL}, {@link #VIEWPORT_WIDTH}, {@link #VIEWPORT_HEIGHT}, {@link #DOCUMENT_WIDTH}, {@link #DOCUMENT_HEIGHT} + * @return Unit type of the length. + */ + + @AnyThread + @ScreenLengthType + public int getType() { + return mType; + } +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md index 23b2a23efe69..ccee9450240e 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -23,6 +23,8 @@ exclude: true - Added `baseUri` to [`ContentDelegate.ContextElement`][65.21] and changed `linkUri` to absolute form. +- Added `scrollBy()` and `scrollTo()` to `PanZoomController`. + ## v66 - Removed redundant field `GeckoSession.ProgressDelegate.SecurityInformation.trackingMode`. Use `GeckoSession.TrackingProtectionDelegate.onTrackerBlocked` for @@ -132,4 +134,4 @@ exclude: true [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String- [65.25]: ../GeckoResult.html -[api-version]: a42a6f4481dd690ac46f14d8e692785bb00e8b04 +[api-version]: fb3375bbe85695b337d830dcf3fffec7231f4e4b diff --git a/mobile/android/modules/geckoview/GeckoViewContent.jsm b/mobile/android/modules/geckoview/GeckoViewContent.jsm index 2b64ac959003..c422869d86e1 100644 --- a/mobile/android/modules/geckoview/GeckoViewContent.jsm +++ b/mobile/android/modules/geckoview/GeckoViewContent.jsm @@ -25,6 +25,8 @@ class GeckoViewContent extends GeckoViewModule { "GeckoView:SetActive", "GeckoView:SetFocused", "GeckoView:ZoomToInput", + "GeckoView:ScrollBy", + "GeckoView:ScrollTo", ]); this.messageManager.addMessageListener("GeckoView:SaveStateFinish", this); @@ -77,6 +79,12 @@ class GeckoViewContent extends GeckoViewModule { case "GeckoView:ZoomToInput": this.messageManager.sendAsyncMessage(aEvent); break; + case "GeckoView:ScrollBy": + this.messageManager.sendAsyncMessage(aEvent, aData); + break; + case "GeckoView:ScrollTo": + this.messageManager.sendAsyncMessage(aEvent, aData); + break; case "GeckoView:SetActive": if (aData.active) { this.browser.docShellIsActive = true; From a32ea7277b07eff2a193ba963ab943c6c4e7a6da Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Feb 2019 18:52:18 +0000 Subject: [PATCH 61/84] Bug 1522637 - Part 9: Allow 'element_stale' to work after process swap, r=ato The element has never existed in the new process, so it gets a missing error rather than a stale error in that case. Depends on D19692 Differential Revision: https://phabricator.services.mozilla.com/D19829 --HG-- extra : moz-landing-system : lando --- testing/marionette/client/marionette_driver/expected.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testing/marionette/client/marionette_driver/expected.py b/testing/marionette/client/marionette_driver/expected.py index 018377767443..1605b2adadbd 100644 --- a/testing/marionette/client/marionette_driver/expected.py +++ b/testing/marionette/client/marionette_driver/expected.py @@ -101,7 +101,9 @@ class element_stale(object): # Calling any method forces a staleness check self.el.is_enabled() return False - except errors.StaleElementException: + except (errors.StaleElementException, errors.NoSuchElementException): + # StaleElementException is raised when the element is gone, and + # NoSuchElementException is raised after a process swap. return True From 75718b91a45d021524629b6ea2ac56f209fbe440 Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Thu, 14 Feb 2019 19:46:00 +0000 Subject: [PATCH 62/84] Bug 1525125 block newtab and homepage overrides in private windows r=rpl,Gijs Differential Revision: https://phabricator.services.mozilla.com/D18730 --HG-- extra : moz-landing-system : lando --- browser/base/content/browser.js | 2 +- browser/base/content/utilityOverlay.js | 17 +- .../extensions/ExtensionControlledPopup.jsm | 9 +- .../extensions/parent/ext-windows.js | 9 +- ...wser_ext_chrome_settings_overrides_home.js | 116 +++++++++++ .../browser_ext_url_overrides_newtab.js | 189 ++++++++++++++++++ browser/components/nsBrowserContentHandler.js | 10 +- .../components/sessionstore/SessionStore.jsm | 2 +- browser/modules/HomePage.jsm | 26 ++- 9 files changed, 367 insertions(+), 13 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 9994cb518a03..d9237bd5036c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2174,7 +2174,7 @@ function BrowserHome(aEvent) { aEvent.button == 2) // right-click: do nothing return; - var homePage = HomePage.get(); + var homePage = HomePage.get(window); var where = whereToOpenLink(aEvent, false, true); var urls; var notifyObservers; diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index e1fd134a7985..896fe5c6fc25 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -24,10 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", Object.defineProperty(this, "BROWSER_NEW_TAB_URL", { enumerable: true, get() { - if (PrivateBrowsingUtils.isWindowPrivate(window) && - !PrivateBrowsingUtils.permanentPrivateBrowsing && - !aboutNewTabService.overridden) { - return "about:privatebrowsing"; + if (PrivateBrowsingUtils.isWindowPrivate(window)) { + if (!PrivateBrowsingUtils.permanentPrivateBrowsing && + !aboutNewTabService.overridden) { + return "about:privatebrowsing"; + } + // If the extension does not have private browsing permission, + // use about:privatebrowsing. + if (aboutNewTabService.newTabURL.startsWith("moz-extension")) { + let url = new URL(aboutNewTabService.newTabURL); + if (!WebExtensionPolicy.getByHostname(url.hostname).privateBrowsingAllowed) { + return "about:privatebrowsing"; + } + } } return aboutNewTabService.newTabURL; }, diff --git a/browser/components/extensions/ExtensionControlledPopup.jsm b/browser/components/extensions/ExtensionControlledPopup.jsm index 821cdca9fa63..f264a4582942 100644 --- a/browser/components/extensions/ExtensionControlledPopup.jsm +++ b/browser/components/extensions/ExtensionControlledPopup.jsm @@ -31,6 +31,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); +ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); let { makeWidgetId, @@ -195,6 +197,12 @@ class ExtensionControlledPopup { extensionId = item && item.id; } + let win = targetWindow || this.topWindow; + let isPrivate = PrivateBrowsingUtils.isWindowPrivate(win); + if (isPrivate && extensionId && !WebExtensionPolicy.getByID(extensionId).privateBrowsingAllowed) { + return; + } + // The item should have an extension and the user shouldn't have confirmed // the change here, but just to be sure check that it is still controlled // and the user hasn't already confirmed the change. @@ -203,7 +211,6 @@ class ExtensionControlledPopup { return; } - let win = targetWindow || this.topWindow; // If the window closes while waiting for focus, this might reject/throw, // and we should stop trying to show the popup. try { diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index f44f7508d24a..7812b69d8146 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -191,8 +191,13 @@ this.windows = class extends ExtensionAPI { args.appendElement(mkstr(createData.url)); } } else { - let url = createData.incognito && !PrivateBrowsingUtils.permanentPrivateBrowsing ? - "about:privatebrowsing" : HomePage.get().split("|", 1)[0]; + let url; + if (createData.incognito) { + url = PrivateBrowsingUtils.permanentPrivateBrowsing ? + HomePage.getPrivate().split("|", 1)[0] : "about:privatebrowsing"; + } else { + url = HomePage.get().split("|", 1)[0]; + } args.appendElement(mkstr(url)); if (url.startsWith("about:") && diff --git a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js index ef702f0b832d..1b0db6f22401 100644 --- a/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js +++ b/browser/components/extensions/test/browser/browser_ext_chrome_settings_overrides_home.js @@ -422,3 +422,119 @@ add_task(async function test_doorhanger_new_window() { ok(!isConfirmed(ext1Id), "The confirmation is cleaned up on uninstall"); }); + +add_task(async function test_overriding_home_page_incognito_not_allowed() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_settings_overrides: {"homepage": "home.html"}, + name: "extension", + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("home.html")); + }, + files: {"home.html": "

1

"}, + useAddonManager: "temporary", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow({url}); + let win = OpenBrowserWindow(); + await windowOpenedPromise; + let doc = win.document; + let description = doc.getElementById("extension-homepage-notification-description"); + let panel = doc.getElementById("extension-notification-panel"); + await promisePopupShown(panel); + + let popupnotification = description.closest("popupnotification"); + is(description.textContent, + "An extension, extension, changed what you see when you open your homepage and new windows.Learn more", + "The extension name is in the popup"); + is(popupnotification.hidden, false, "The expected popup notification is visible"); + + ok(win.gURLBar.value.endsWith("home.html"), "extension is in control"); + await BrowserTestUtils.closeWindow(win); + + // Verify a private window does not open the extension page. + windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + win.BrowserHome(); + await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); + + is(win.gURLBar.value, "", "home page not used in private window"); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_home_page_incognito_not_allowed_bypass() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + name: "extension", + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("home.html")); + }, + files: {"home.html": "

1

"}, + useAddonManager: "temporary", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + // Verify manually setting the pref to the extension page does not work. + let changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF); + Services.prefs.setStringPref(HOMEPAGE_URL_PREF, url); + await changed; + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + win.BrowserHome(); + await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); + + is(win.gURLBar.value, "", "home page not used in private window"); + changed = promisePrefChangeObserved(HOMEPAGE_URL_PREF); + Services.prefs.clearUserPref(HOMEPAGE_URL_PREF); + await changed; + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_home_page_incognito_spanning() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_settings_overrides: {"homepage": "home.html"}, + name: "private extension", + applications: { + gecko: {id: "@spanning-home"}, + }, + }, + files: {"home.html": "

1

"}, + useAddonManager: "permanent", + incognitoOverride: "spanning", + }); + + await extension.startup(); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + let doc = win.document; + let panel = doc.getElementById("extension-notification-panel"); + win.BrowserHome(); + await promisePopupShown(panel); + + ok(win.gURLBar.value.endsWith("home.html"), "extension is in control in private window"); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js index a8ae9a53aa89..32e9d8b0c8d5 100644 --- a/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js +++ b/browser/components/extensions/test/browser/browser_ext_url_overrides_newtab.js @@ -5,6 +5,9 @@ ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); +XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", + "@mozilla.org/browser/aboutnewtab-service;1", + "nsIAboutNewTabService"); const NEWTAB_URI_1 = "webext-newtab-1.html"; @@ -522,3 +525,189 @@ add_task(async function dontTemporarilyShowAboutExtensionPath() { BrowserTestUtils.removeTab(tab); await extension.unload(); }); + +add_task(async function test_overriding_newtab_incognito_not_allowed() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let panel = getNewTabDoorhanger().closest("panel"); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_url_overrides: {"newtab": "newtab.html"}, + name: "extension", + applications: { + gecko: {id: "@not-allowed-newtab"}, + }, + }, + files: { + "newtab.html": ` + + + + + + + + + `, + + "newtab.js": function() { + window.onload = () => { + browser.test.sendMessage("from-newtab-page", window.location.href); + }; + }, + }, + useAddonManager: "permanent", + }); + + await extension.startup(); + + let popupShown = promisePopupShown(panel); + BrowserOpenTab(); + await popupShown; + + let url = await extension.awaitMessage("from-newtab-page"); + ok(url.endsWith("newtab.html"), + "Newtab url is overridden by the extension."); + + // This will show a confirmation doorhanger, make sure we don't leave it open. + let popupHidden = promisePopupHidden(panel); + panel.hidePopup(); + await popupHidden; + + BrowserTestUtils.removeTab(gBrowser.selectedTab); + + // Verify a private window does not open the extension page. We would + // get an extra notification that we don't listen for if it gets loaded. + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + + let newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "newtab not used in private window"); + + // Verify setting the pref directly doesn't bypass permissions. + let origUrl = aboutNewTabService.newTabURL; + aboutNewTabService.newTabURL = url; + newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "directly set newtab not used in private window"); + + aboutNewTabService.newTabURL = origUrl; + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_newtab_incognito_not_allowed_bypass() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + name: "extension", + applications: { + gecko: {id: "@not-allowed-newtab"}, + }, + }, + background() { + browser.test.sendMessage("url", browser.runtime.getURL("newtab.html")); + }, + files: { + "newtab.html": ` + + + + + + + + `, + }, + useAddonManager: "permanent", + }); + + await extension.startup(); + let url = await extension.awaitMessage("url"); + + // Verify setting the pref directly doesn't bypass permissions. + let origUrl = aboutNewTabService.newTabURL; + aboutNewTabService.newTabURL = url; + + // Verify a private window does not open the extension page. We would + // get an extra notification that we don't listen for if it gets loaded. + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + + let newTabOpened = waitForNewTab(); + win.BrowserOpenTab(); + await newTabOpened; + + is(win.gURLBar.value, "", "directly set newtab not used in private window"); + + aboutNewTabService.newTabURL = origUrl; + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function test_overriding_newtab_incognito_spanning() { + await SpecialPowers.pushPrefEnv({set: [["extensions.allowPrivateBrowsingByDefault", false]]}); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + chrome_url_overrides: {"newtab": "newtab.html"}, + name: "extension", + applications: { + gecko: {id: "@spanning-newtab"}, + }, + }, + files: { + "newtab.html": ` + + + + + + + + + `, + + "newtab.js": function() { + window.onload = () => { + browser.test.sendMessage("from-newtab-page", window.location.href); + }; + }, + }, + useAddonManager: "permanent", + incognitoOverride: "spanning", + }); + + await extension.startup(); + + let windowOpenedPromise = BrowserTestUtils.waitForNewWindow(); + let win = OpenBrowserWindow({private: true}); + await windowOpenedPromise; + let panel = win.document.getElementById("extension-new-tab-notification").closest("panel"); + let popupShown = promisePopupShown(panel); + win.BrowserOpenTab(); + await popupShown; + + let url = await extension.awaitMessage("from-newtab-page"); + ok(url.endsWith("newtab.html"), + "Newtab url is overridden by the extension."); + + // This will show a confirmation doorhanger, make sure we don't leave it open. + let popupHidden = promisePopupHidden(panel); + panel.hidePopup(); + await popupHidden; + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); +}); diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index ecb08a61cd2f..874159a13362 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -207,7 +207,7 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData let args; if (!urlOrUrlList) { // Just pass in the defaultArgs directly. We'll use system principal on the other end. - args = [gBrowserContentHandler.defaultArgs]; + args = [gBrowserContentHandler.getDefaultArgs(forcePrivate)]; } else { let pService = Cc["@mozilla.org/toolkit/profile-service;1"]. getService(Ci.nsIToolkitProfileService); @@ -522,7 +522,7 @@ nsBrowserContentHandler.prototype = { /* nsIBrowserHandler */ - get defaultArgs() { + getDefaultArgs(forcePrivate = false) { var prefb = Services.prefs; if (!gFirstWindow) { @@ -607,7 +607,7 @@ nsBrowserContentHandler.prototype = { try { var choice = prefb.getIntPref("browser.startup.page"); if (choice == 1 || choice == 3) - startPage = HomePage.get(); + startPage = forcePrivate ? HomePage.getPrivate() : HomePage.get(); } catch (e) { Cu.reportError(e); } @@ -625,6 +625,10 @@ nsBrowserContentHandler.prototype = { return overridePage || startPage || "about:blank"; }, + get defaultArgs() { + return this.getDefaultArgs(PrivateBrowsingUtils.permanentPrivateBrowsing); + }, + mFeatures: null, getFeatures: function bch_features(cmdLine) { diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index c0370612cfc9..73cf59ba374c 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -3341,7 +3341,7 @@ var SessionStoreInternal = { let tabbrowser = aWindow.gBrowser; let startupPref = this._prefBranch.getIntPref("startup.page"); if (startupPref == 1) - homePages = homePages.concat(HomePage.get().split("|")); + homePages = homePages.concat(HomePage.get(aWindow).split("|")); for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; diff --git a/browser/modules/HomePage.jsm b/browser/modules/HomePage.jsm index 486209167e87..2f7a3aa491fb 100644 --- a/browser/modules/HomePage.jsm +++ b/browser/modules/HomePage.jsm @@ -10,6 +10,8 @@ var EXPORTED_SYMBOLS = ["HomePage"]; const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); const kPrefName = "browser.startup.homepage"; @@ -43,7 +45,11 @@ function getHomepagePref(useDefault) { } let HomePage = { - get() { + get(aWindow) { + if (PrivateBrowsingUtils.permanentPrivateBrowsing || + (aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) { + return this.getPrivate(); + } return getHomepagePref(); }, @@ -51,6 +57,24 @@ let HomePage = { return getHomepagePref(true); }, + getPrivate() { + let homePages = getHomepagePref(); + if (!homePages.includes("moz-extension")) { + return homePages; + } + // Verify private access and build a new list. + let privateHomePages = homePages.split("|").filter(page => { + let url = new URL(page); + if (url.protocol !== "moz-extension:") { + return true; + } + let policy = WebExtensionPolicy.getByHostname(url.hostname); + return policy && policy.privateBrowsingAllowed; + }); + // Extensions may not be ready on startup, fallback to defaults. + return privateHomePages.join("|") || this.getDefault(); + }, + get overridden() { return Services.prefs.prefHasUserValue(kPrefName); }, From 93d45e85e9f0ac7d6cbd5e4ccd9aa88ecf52eb8a Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Thu, 14 Feb 2019 18:08:32 +0000 Subject: [PATCH 63/84] Bug 1527863 - Prevent the video controls from inheriting white-space style. r=alwu Differential Revision: https://phabricator.services.mozilla.com/D19802 --HG-- extra : moz-landing-system : lando --- toolkit/themes/shared/media/videocontrols.css | 1 + 1 file changed, 1 insertion(+) diff --git a/toolkit/themes/shared/media/videocontrols.css b/toolkit/themes/shared/media/videocontrols.css index daede1a4c28d..c806a8b5ab83 100644 --- a/toolkit/themes/shared/media/videocontrols.css +++ b/toolkit/themes/shared/media/videocontrols.css @@ -17,6 +17,7 @@ list-style-image: none !important; font: normal normal normal 100%/normal sans-serif !important; text-decoration: none !important; + white-space: normal !important; } .controlsContainer { From c3577f0fc0a1dbbb539020041f9ed17a88bab693 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Thu, 14 Feb 2019 19:48:58 +0000 Subject: [PATCH 64/84] Bug 1525634 - Preserve lazyness of the old tab when adopted by another window. r=jaws Differential Revision: https://phabricator.services.mozilla.com/D18982 --HG-- extra : moz-landing-system : lando --- ...ect_tabs_move_to_new_window_contextmenu.js | 51 +++++++++++-------- .../extensions/parent/ext-browser.js | 9 ++-- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js b/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js index b47a4b3a7d50..347d2f6c0f37 100644 --- a/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js +++ b/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js @@ -47,58 +47,67 @@ add_task(async function test() { add_task(async function testLazyTabs() { let params = {createLazyBrowser: true}; - let tabs = []; + let oldTabs = []; let numTabs = 4; for (let i = 0; i < numTabs; ++i) { - tabs.push(BrowserTestUtils.addTab(gBrowser, `http://example.com/?${i}`, params)); + oldTabs.push(BrowserTestUtils.addTab(gBrowser, `http://example.com/?${i}`, params)); } - await BrowserTestUtils.switchTab(gBrowser, tabs[0]); + await BrowserTestUtils.switchTab(gBrowser, oldTabs[0]); for (let i = 1; i < numTabs; ++i) { - await triggerClickOn(tabs[i], { ctrlKey: true }); + await triggerClickOn(oldTabs[i], { ctrlKey: true }); } - isnot(tabs[0].linkedPanel, "", `Tab 0 shouldn't be lazy`); + isnot(oldTabs[0].linkedPanel, "", `Old tab 0 shouldn't be lazy`); for (let i = 1; i < numTabs; ++i) { - is(tabs[i].linkedPanel, "", `Tab ${i} should be lazy`); + is(oldTabs[i].linkedPanel, "", `Old tab ${i} should be lazy`); } is(gBrowser.multiSelectedTabsCount, numTabs, `${numTabs} multiselected tabs`); for (let i = 0; i < numTabs; ++i) { - ok(tabs[i].multiselected, `Tab ${i} should be multiselected`); + ok(oldTabs[i].multiselected, `Old tab ${i} should be multiselected`); } let tabsMoved = new Promise(resolve => { // Tab tabs in the new window will be about:blank before swapping the docshells. // The "EndSwapDocShells" event is not dispatched for lazy tabs, so listen for // "TabClose" instead and await a tick. - let i = 0; - window.addEventListener("TabClose", async function listener() { + let numTabsMoved = 0; + window.addEventListener("TabClose", async function listener(event) { + let tab = event.target; + let i = oldTabs.indexOf(tab); + if (i == 0) { + isnot(tab.linkedPanel, "", `Old tab ${i} should continue not being lazy`); + } else if (i > 0) { + is(tab.linkedPanel, "", `Old tab ${i} should continue being lazy`); + } else { + return; + } await Promise.resolve(); - if (++i == numTabs) { + if (++numTabsMoved == numTabs) { window.removeEventListener("TabClose", listener); resolve(); } }); }); - let newWindow = gBrowser.replaceTabsWithWindow(tabs[0]); + let newWindow = gBrowser.replaceTabsWithWindow(oldTabs[0]); await tabsMoved; - tabs = newWindow.gBrowser.tabs; + let newTabs = newWindow.gBrowser.tabs; - isnot(tabs[0].linkedPanel, "", `Tab 0 should continue not being lazy`); + isnot(newTabs[0].linkedPanel, "", `New tab 0 should continue not being lazy`); // FIXME: bug 1521923 - First inactive tab to be moved into another window loses laziness - todo_is(tabs[1].linkedPanel, "", `Tab 1 should continue being lazy`); + todo_is(newTabs[1].linkedPanel, "", `New tab 1 should continue being lazy`); for (let i = 2; i < numTabs; ++i) { - is(tabs[i].linkedPanel, "", `Tab ${i} should continue being lazy`); + is(newTabs[i].linkedPanel, "", `New tab ${i} should continue being lazy`); } - is(tabs[0].linkedBrowser.currentURI.spec, `http://example.com/?0`, - `Tab 0 should have the right URL`); - todo_is(SessionStore.getLazyTabValue(tabs[1], "url"), `http://example.com/?1`, - `Tab 1 should have the right lazy URL`); + is(newTabs[0].linkedBrowser.currentURI.spec, `http://example.com/?0`, + `New tab 0 should have the right URL`); + todo_is(SessionStore.getLazyTabValue(newTabs[1], "url"), `http://example.com/?1`, + `New tab 1 should have the right lazy URL`); for (let i = 2; i < numTabs; ++i) { - is(SessionStore.getLazyTabValue(tabs[i], "url"), `http://example.com/?${i}`, - `Tab ${i} should have the right lazy URL`); + is(SessionStore.getLazyTabValue(newTabs[i], "url"), `http://example.com/?${i}`, + `New tab ${i} should have the right lazy URL`); } BrowserTestUtils.closeWindow(newWindow); diff --git a/browser/components/extensions/parent/ext-browser.js b/browser/components/extensions/parent/ext-browser.js index 7ba6534db938..c74ec9db370e 100644 --- a/browser/components/extensions/parent/ext-browser.js +++ b/browser/components/extensions/parent/ext-browser.js @@ -454,10 +454,11 @@ class TabTracker extends TabTrackerBase { // This tab is being created to adopt a tab from a different window. // Handle the adoption. this.adopt(nativeTab, adoptedTab); - - adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetFrameData", { - windowId: windowTracker.getId(nativeTab.ownerGlobal), - }); + if (adoptedTab.linkedPanel) { + adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetFrameData", { + windowId: windowTracker.getId(nativeTab.ownerGlobal), + }); + } } else { // Save the size of the current tab, since the newly-created tab will // likely be active by the time the promise below resolves and the From 2928c19d6366bed0c5ab271519971bdbe1019d68 Mon Sep 17 00:00:00 2001 From: "J.C. Jones" Date: Thu, 14 Feb 2019 20:11:34 +0000 Subject: [PATCH 65/84] Bug 1526023 - Web Authentication - add isExternalCTAP2SecurityKeySupported r=qdot,keeler We support CTAP2 devices on one specific platform, making it hard for RPs to decide whether or not Firefox will support the tokens they're asking for. This adds a non-standard method to divine that information while Firefox moves toward CTAP2 support. Differential Revision: https://phabricator.services.mozilla.com/D19826 --HG-- extra : moz-landing-system : lando --- dom/webauthn/PublicKeyCredential.cpp | 25 +++++++++++++ dom/webauthn/PublicKeyCredential.h | 3 ++ dom/webauthn/tests/mochitest.ini | 1 + ...n_isexternalctap2securitykeysupported.html | 37 +++++++++++++++++++ dom/webidl/WebAuthentication.webidl | 2 + 5 files changed, 68 insertions(+) create mode 100644 dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html diff --git a/dom/webauthn/PublicKeyCredential.cpp b/dom/webauthn/PublicKeyCredential.cpp index fcbe494e2b2e..c9737c3c4677 100644 --- a/dom/webauthn/PublicKeyCredential.cpp +++ b/dom/webauthn/PublicKeyCredential.cpp @@ -112,6 +112,31 @@ PublicKeyCredential::IsUserVerifyingPlatformAuthenticatorAvailable( return promise.forget(); } +/* static */ already_AddRefed +PublicKeyCredential::IsExternalCTAP2SecurityKeySupported( + GlobalObject& aGlobal) { + nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aGlobal.Context()); + if (NS_WARN_IF(!globalObject)) { + return nullptr; + } + + ErrorResult rv; + RefPtr promise = Promise::Create(globalObject, rv); + if (rv.Failed()) { + return nullptr; + } + +#ifdef OS_WIN + if (WinWebAuthnManager::AreWebAuthNApisAvailable()) { + promise->MaybeResolve(true); + return promise.forget(); + } +#endif + + promise->MaybeResolve(false); + return promise.forget(); +} + void PublicKeyCredential::GetClientExtensionResults( AuthenticationExtensionsClientOutputs& aResult) { aResult = mClientExtensionOutputs; diff --git a/dom/webauthn/PublicKeyCredential.h b/dom/webauthn/PublicKeyCredential.h index 1f2a893b3964..451defce545e 100644 --- a/dom/webauthn/PublicKeyCredential.h +++ b/dom/webauthn/PublicKeyCredential.h @@ -44,6 +44,9 @@ class PublicKeyCredential final : public Credential { static already_AddRefed IsUserVerifyingPlatformAuthenticatorAvailable(GlobalObject& aGlobal); + static already_AddRefed IsExternalCTAP2SecurityKeySupported( + GlobalObject& aGlobal); + void GetClientExtensionResults( AuthenticationExtensionsClientOutputs& aResult); diff --git a/dom/webauthn/tests/mochitest.ini b/dom/webauthn/tests/mochitest.ini index a65af5079212..b590e402c4a4 100644 --- a/dom/webauthn/tests/mochitest.ini +++ b/dom/webauthn/tests/mochitest.ini @@ -20,3 +20,4 @@ scheme = https [test_webauthn_store_credential.html] [test_webauthn_sameorigin.html] [test_webauthn_isplatformauthenticatoravailable.html] +[test_webauthn_isexternalctap2securitykeysupported.html] diff --git a/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html b/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html new file mode 100644 index 000000000000..e6152ffc91df --- /dev/null +++ b/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html @@ -0,0 +1,37 @@ + + + + Test for W3C Web Authentication isExternalCTAP2SecurityKeySupported + + + + + + + + + + +

Test for W3C Web Authentication isExternalCTAP2SecurityKeySupported

+Mozilla Bug 1526023 + + + + + diff --git a/dom/webidl/WebAuthentication.webidl b/dom/webidl/WebAuthentication.webidl index 9b409dd116c3..8632324c6b73 100644 --- a/dom/webidl/WebAuthentication.webidl +++ b/dom/webidl/WebAuthentication.webidl @@ -19,6 +19,8 @@ interface PublicKeyCredential : Credential { [SecureContext] partial interface PublicKeyCredential { static Promise isUserVerifyingPlatformAuthenticatorAvailable(); + // isExternalCTAP2SecurityKeySupported is non-standard; see Bug 1526023 + static Promise isExternalCTAP2SecurityKeySupported(); }; [SecureContext, Pref="security.webauth.webauthn"] From f83531d710e0061c8a5b0fdfba7817afb878f1a2 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:01 +0000 Subject: [PATCH 66/84] Bug 1460874 - Part 1: Cleanups. r=geckoview-reviewers,snorp The GeckoFontScaleListener is intended to live as long as the app (and there- fore Gecko) remains alive and consequently keeps a reference to the *application* context, so the linter warning can be safely suppressed. Also reorder imports to match coding style. Differential Revision: https://phabricator.services.mozilla.com/D17743 --HG-- extra : moz-landing-system : lando --- .../java/org/mozilla/gecko/GeckoFontScaleListener.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java index c82250cf262b..5f87a2e1b8a1 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -5,17 +5,18 @@ package org.mozilla.gecko; +import org.mozilla.gecko.preferences.GeckoPreferences; + +import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; -import android.database.ContentObserver; import android.content.SharedPreferences; +import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; import android.support.annotation.UiThread; import android.util.Log; -import org.mozilla.gecko.preferences.GeckoPreferences; - class GeckoFontScaleListener extends ContentObserver implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -27,6 +28,8 @@ class GeckoFontScaleListener private static final int FONT_INFLATION_ON_DEFAULT_VALUE = 120; private static final float DEFAULT_FONT_SCALE = 1.0f; + // We're referencing the *application* context, so this is in fact okay. + @SuppressLint("StaticFieldLeak") private static final GeckoFontScaleListener listenerInstance = new GeckoFontScaleListener(); private Context applicationContext; From b0ce764ff23f0ac7c3ac12fb1c5cbab37a312a5b Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:08 +0000 Subject: [PATCH 67/84] Bug 1460874 - Part 2: Rename instance variables to better match GeckoView code style. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D17744 --HG-- extra : moz-landing-system : lando --- .../mozilla/gecko/GeckoFontScaleListener.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java index 5f87a2e1b8a1..ed1266f84d88 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -30,14 +30,14 @@ class GeckoFontScaleListener // We're referencing the *application* context, so this is in fact okay. @SuppressLint("StaticFieldLeak") - private static final GeckoFontScaleListener listenerInstance = new GeckoFontScaleListener(); + private static final GeckoFontScaleListener sInstance = new GeckoFontScaleListener(); - private Context applicationContext; - private boolean initialized; - private boolean running; + private Context mApplicationContext; + private boolean mInitialized; + private boolean mRunning; public static GeckoFontScaleListener getInstance() { - return listenerInstance; + return sInstance; } private GeckoFontScaleListener() { @@ -45,53 +45,53 @@ class GeckoFontScaleListener } public synchronized void initialize(final Context context) { - if (initialized) { + if (mInitialized) { Log.w(LOGTAG, "Already initialized!"); return; } - applicationContext = context.getApplicationContext(); - SharedPreferences prefs = GeckoSharedPrefs.forApp(applicationContext); + mApplicationContext = context.getApplicationContext(); + SharedPreferences prefs = GeckoSharedPrefs.forApp(mApplicationContext); prefs.registerOnSharedPreferenceChangeListener(this); onPrefChange(prefs); - initialized = true; + mInitialized = true; } public synchronized void shutdown() { - if (!initialized) { + if (!mInitialized) { Log.w(LOGTAG, "Already shut down!"); return; } - GeckoSharedPrefs.forApp(applicationContext).unregisterOnSharedPreferenceChangeListener(this); + GeckoSharedPrefs.forApp(mApplicationContext).unregisterOnSharedPreferenceChangeListener(this); stop(); - applicationContext = null; - initialized = false; + mApplicationContext = null; + mInitialized = false; } private synchronized void start() { - if (running) { + if (mRunning) { return; } - ContentResolver contentResolver = applicationContext.getContentResolver(); + ContentResolver contentResolver = mApplicationContext.getContentResolver(); Uri fontSizeSetting = Settings.System.getUriFor(Settings.System.FONT_SCALE); contentResolver.registerContentObserver(fontSizeSetting, false, this); onSystemFontScaleChange(contentResolver, false); - running = true; + mRunning = true; } private synchronized void stop() { - if (!running) { + if (!mRunning) { return; } - ContentResolver contentResolver = applicationContext.getContentResolver(); + ContentResolver contentResolver = mApplicationContext.getContentResolver(); contentResolver.unregisterContentObserver(this); onSystemFontScaleChange(contentResolver, /*stopping*/ true); - running = false; + mRunning = false; } private void onSystemFontScaleChange(final ContentResolver contentResolver, boolean stopping) { @@ -122,7 +122,7 @@ class GeckoFontScaleListener @Override public void onChange(boolean selfChange) { - onSystemFontScaleChange(applicationContext.getContentResolver(), false); + onSystemFontScaleChange(mApplicationContext.getContentResolver(), false); } @UiThread // According to the docs. From 34aef44d69ead4189c8816521f62e47d09f36cb6 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:16 +0000 Subject: [PATCH 68/84] Bug 1460874 - Part 3: Rename initalize() method for more clarity. r=geckoview-reviewers,snorp Going forward, we want to be able to toggle the enabled state at all times, and being able to do this before calling initialize() seems a bit inconsistent. Hence, we rename it to the more neutral-sounding attachToContext(). Differential Revision: https://phabricator.services.mozilla.com/D17745 --HG-- extra : moz-landing-system : lando --- .../org/mozilla/gecko/GeckoApplication.java | 2 +- .../mozilla/gecko/GeckoFontScaleListener.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java index 041ac58289ae..801f59526fbc 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java @@ -212,7 +212,7 @@ public class GeckoApplication extends Application public void onApplicationForeground() { if (mIsInitialResume) { GeckoBatteryManager.getInstance().start(this); - GeckoFontScaleListener.getInstance().initialize(this); + GeckoFontScaleListener.getInstance().attachToContext(this); GeckoNetworkManager.getInstance().start(this); mIsInitialResume = false; } else if (mPausedGecko) { diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java index ed1266f84d88..8e6e1df085bf 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -33,7 +33,7 @@ class GeckoFontScaleListener private static final GeckoFontScaleListener sInstance = new GeckoFontScaleListener(); private Context mApplicationContext; - private boolean mInitialized; + private boolean mAttached; private boolean mRunning; public static GeckoFontScaleListener getInstance() { @@ -44,9 +44,9 @@ class GeckoFontScaleListener super(null); } - public synchronized void initialize(final Context context) { - if (mInitialized) { - Log.w(LOGTAG, "Already initialized!"); + public synchronized void attachToContext(final Context context) { + if (mAttached) { + Log.w(LOGTAG, "Already attached!"); return; } @@ -54,19 +54,19 @@ class GeckoFontScaleListener SharedPreferences prefs = GeckoSharedPrefs.forApp(mApplicationContext); prefs.registerOnSharedPreferenceChangeListener(this); onPrefChange(prefs); - mInitialized = true; + mAttached = true; } - public synchronized void shutdown() { - if (!mInitialized) { - Log.w(LOGTAG, "Already shut down!"); + public synchronized void detachFromContext() { + if (!mAttached) { + Log.w(LOGTAG, "Already detached!"); return; } GeckoSharedPrefs.forApp(mApplicationContext).unregisterOnSharedPreferenceChangeListener(this); stop(); mApplicationContext = null; - mInitialized = false; + mAttached = false; } private synchronized void start() { From 2b75da3bc6765a62ddafc1f7fe430be8dd9b853e Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:23 +0000 Subject: [PATCH 69/84] Bug 1460874 - Part 4: Clean up threading assumptions. r=snorp In practice, everything in the GeckoFontScaleListener will run on the UI thread, so get rid of the `synchronized` methods and just enforce the threading assumptions in the public API. Differential Revision: https://phabricator.services.mozilla.com/D18505 --HG-- extra : moz-landing-system : lando --- .../mozilla/gecko/GeckoFontScaleListener.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java index 8e6e1df085bf..c8b0eccb09c9 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.preferences.GeckoPreferences; +import org.mozilla.gecko.util.ThreadUtils; import android.annotation.SuppressLint; import android.content.ContentResolver; @@ -41,10 +42,13 @@ class GeckoFontScaleListener } private GeckoFontScaleListener() { - super(null); + // Ensure the ContentObserver callback runs on the UI thread. + super(ThreadUtils.getUiHandler()); } - public synchronized void attachToContext(final Context context) { + public void attachToContext(final Context context) { + ThreadUtils.assertOnUiThread(); + if (mAttached) { Log.w(LOGTAG, "Already attached!"); return; @@ -57,7 +61,9 @@ class GeckoFontScaleListener mAttached = true; } - public synchronized void detachFromContext() { + public void detachFromContext() { + ThreadUtils.assertOnUiThread(); + if (!mAttached) { Log.w(LOGTAG, "Already detached!"); return; @@ -69,7 +75,7 @@ class GeckoFontScaleListener mAttached = false; } - private synchronized void start() { + private void start() { if (mRunning) { return; } @@ -82,7 +88,7 @@ class GeckoFontScaleListener mRunning = true; } - private synchronized void stop() { + private void stop() { if (!mRunning) { return; } @@ -120,6 +126,7 @@ class GeckoFontScaleListener } } + @UiThread // See constructor. @Override public void onChange(boolean selfChange) { onSystemFontScaleChange(mApplicationContext.getContentResolver(), false); From b3ee3af69077dbbf07526bc3238d2a3e32e2ba86 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:30 +0000 Subject: [PATCH 70/84] Bug 1460874 - Part 5: Move out SharedPreferences watching. r=geckoview-reviewers,snorp For easier testing in Fennec, we want to continue watching the respective SharedPreferences key and toggle the listener in response to *that* instead of directly wiring it into our Settings menu (GeckoPreferences), however because that functionality is Fennec-specific, we move that logic out of the font scale listener itself. In conjunction with this, we also decouple the enabled state of the listener from its attached state. The enabled state can now be toggled at all times, but unless the listener is also attached to a context, it simply won't have any practical effect. Differential Revision: https://phabricator.services.mozilla.com/D17746 --HG-- extra : moz-landing-system : lando --- .../org/mozilla/gecko/GeckoApplication.java | 23 +++++++- .../mozilla/gecko/GeckoFontScaleListener.java | 59 +++++++++---------- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java index 801f59526fbc..fc765f5f132c 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java @@ -11,6 +11,7 @@ import android.app.Service; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Bitmap; import android.net.Uri; @@ -49,6 +50,7 @@ import org.mozilla.gecko.notifications.NotificationClient; import org.mozilla.gecko.notifications.NotificationHelper; import org.mozilla.gecko.permissions.Permissions; import org.mozilla.gecko.preferences.DistroSharedPrefsImport; +import org.mozilla.gecko.preferences.GeckoPreferences; import org.mozilla.gecko.pwa.PwaUtils; import org.mozilla.gecko.telemetry.TelemetryBackgroundReceiver; import org.mozilla.gecko.util.ActivityResultHandler; @@ -72,7 +74,8 @@ import java.net.URL; import java.util.UUID; public class GeckoApplication extends Application - implements HapticFeedbackDelegate { + implements HapticFeedbackDelegate, + SharedPreferences.OnSharedPreferenceChangeListener { private static final String LOG_TAG = "GeckoApplication"; public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG"; private static final String MEDIA_DECODING_PROCESS_CRASH = "MEDIA_DECODING_PROCESS_CRASH"; @@ -212,7 +215,7 @@ public class GeckoApplication extends Application public void onApplicationForeground() { if (mIsInitialResume) { GeckoBatteryManager.getInstance().start(this); - GeckoFontScaleListener.getInstance().attachToContext(this); + initFontScaleListener(); GeckoNetworkManager.getInstance().start(this); mIsInitialResume = false; } else if (mPausedGecko) { @@ -224,6 +227,13 @@ public class GeckoApplication extends Application mInBackground = false; } + private void initFontScaleListener() { + final SharedPreferences prefs = GeckoSharedPrefs.forApp(this); + prefs.registerOnSharedPreferenceChangeListener(this); + onSharedPreferenceChanged(prefs, GeckoPreferences.PREFS_SYSTEM_FONT_SIZE); + GeckoFontScaleListener.getInstance().attachToContext(this); + } + private static GeckoRuntime sGeckoRuntime; public static GeckoRuntime getRuntime() { return sGeckoRuntime; @@ -422,6 +432,7 @@ public class GeckoApplication extends Application "Image:SetAs", "Profile:Create", null); + GeckoSharedPrefs.forApp(this).unregisterOnSharedPreferenceChangeListener(this); GeckoService.unregister(); } @@ -909,4 +920,12 @@ public class GeckoApplication extends Application currentActivity.getWindow().getDecorView().performHapticFeedback(effect); } } + + @Override // OnSharedPreferenceChangeListener + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (GeckoPreferences.PREFS_SYSTEM_FONT_SIZE.equals(key)) { + final boolean enabled = prefs.getBoolean(GeckoPreferences.PREFS_SYSTEM_FONT_SIZE, false); + GeckoFontScaleListener.getInstance().setEnabled(enabled); + } + } } diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java index c8b0eccb09c9..bbd7f6db16bd 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -5,13 +5,11 @@ package org.mozilla.gecko; -import org.mozilla.gecko.preferences.GeckoPreferences; import org.mozilla.gecko.util.ThreadUtils; import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; -import android.content.SharedPreferences; import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; @@ -19,8 +17,7 @@ import android.support.annotation.UiThread; import android.util.Log; class GeckoFontScaleListener - extends ContentObserver - implements SharedPreferences.OnSharedPreferenceChangeListener { + extends ContentObserver { private static final String LOGTAG = "GeckoFontScaleListener"; private static final String PREF_SYSTEM_FONT_SCALE = "font.size.systemFontScale"; @@ -35,6 +32,7 @@ class GeckoFontScaleListener private Context mApplicationContext; private boolean mAttached; + private boolean mEnabled; private boolean mRunning; public static GeckoFontScaleListener getInstance() { @@ -54,11 +52,9 @@ class GeckoFontScaleListener return; } - mApplicationContext = context.getApplicationContext(); - SharedPreferences prefs = GeckoSharedPrefs.forApp(mApplicationContext); - prefs.registerOnSharedPreferenceChangeListener(this); - onPrefChange(prefs); mAttached = true; + mApplicationContext = context.getApplicationContext(); + onEnabledChange(); } public void detachFromContext() { @@ -69,12 +65,33 @@ class GeckoFontScaleListener return; } - GeckoSharedPrefs.forApp(mApplicationContext).unregisterOnSharedPreferenceChangeListener(this); stop(); mApplicationContext = null; mAttached = false; } + public void setEnabled(boolean enabled) { + ThreadUtils.assertOnUiThread(); + mEnabled = enabled; + onEnabledChange(); + } + + public boolean getEnabled() { + return mEnabled; + } + + private void onEnabledChange() { + if (!mAttached) { + return; + } + + if (mEnabled) { + start(); + } else { + stop(); + } + } + private void start() { if (mRunning) { return; @@ -104,10 +121,10 @@ class GeckoFontScaleListener float fontScale; int fontInflation; - if (!stopping) { // Pref was flipped to "On" or system font scale changed. + if (!stopping) { // Either we were enabled, or else the system font scale changed. fontScale = Settings.System.getFloat(contentResolver, Settings.System.FONT_SCALE, DEFAULT_FONT_SCALE); fontInflation = Math.round(FONT_INFLATION_ON_DEFAULT_VALUE * fontScale); - } else { // Pref was flipped to "Off". + } else { // We were turned off. fontScale = DEFAULT_FONT_SCALE; fontInflation = FONT_INFLATION_OFF; } @@ -116,29 +133,9 @@ class GeckoFontScaleListener PrefsHelper.setPref(PREF_SYSTEM_FONT_SCALE, Math.round(fontScale * 100)); } - private void onPrefChange(final SharedPreferences prefs) { - boolean useSystemFontScale = prefs.getBoolean(GeckoPreferences.PREFS_SYSTEM_FONT_SIZE, false); - - if (useSystemFontScale) { - start(); - } else { - stop(); - } - } - @UiThread // See constructor. @Override public void onChange(boolean selfChange) { onSystemFontScaleChange(mApplicationContext.getContentResolver(), false); } - - @UiThread // According to the docs. - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (!GeckoPreferences.PREFS_SYSTEM_FONT_SIZE.equals(key)) { - return; - } - - onPrefChange(sharedPreferences); - } } From 4b59a86921c2dbc8f266a252285f64f1dfaf698e Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:37 +0000 Subject: [PATCH 71/84] Bug 1460874 - Part 6: Move GeckoFontScaleListener into GeckoView. r=snorp With the dependencies on Fennec's GeckoPreferences and GeckoSharedPrefs gone, we can now move the class into GeckoView in preparation for hooking it up to the GeckoViewRuntimeSettings. Differential Revision: https://phabricator.services.mozilla.com/D18506 --HG-- rename : mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java => mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java extra : moz-landing-system : lando --- .../mozilla/gecko/GeckoFontScaleListener.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) rename mobile/android/{base => geckoview/src/main}/java/org/mozilla/gecko/GeckoFontScaleListener.java (79%) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java similarity index 79% rename from mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java index bbd7f6db16bd..f7ecef58c38a 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -16,7 +16,13 @@ import android.provider.Settings; import android.support.annotation.UiThread; import android.util.Log; -class GeckoFontScaleListener +/** + * A class that automatically adjusts font size and font inflation settings for web content in Gecko + * in accordance with the device's OS font scale setting. + * + * @see android.provider.Settings.System#FONT_SCALE + */ +/* package */ final class GeckoFontScaleListener extends ContentObserver { private static final String LOGTAG = "GeckoFontScaleListener"; @@ -44,6 +50,10 @@ class GeckoFontScaleListener super(ThreadUtils.getUiHandler()); } + /** + * Prepare the GeckoFontScaleListener for usage. If it has been previously enabled, it will + * now start actively working. + */ public void attachToContext(final Context context) { ThreadUtils.assertOnUiThread(); @@ -57,6 +67,9 @@ class GeckoFontScaleListener onEnabledChange(); } + /** + * Detaches the context and also stops the GeckoFontScaleListener if it was previously enabled. + */ public void detachFromContext() { ThreadUtils.assertOnUiThread(); @@ -70,12 +83,26 @@ class GeckoFontScaleListener mAttached = false; } + /** + * Controls whether the GeckoFontScaleListener should automatically adjust font sizes for web + * content in Gecko. + * + *

This method can be called at any time, but the GeckoFontScaleListener won't start actively + * adjusting font sizes until it has been attached to a context. + * + * @param enabled True if automatic font size setting should be enabled. + */ public void setEnabled(boolean enabled) { ThreadUtils.assertOnUiThread(); mEnabled = enabled; onEnabledChange(); } + /** + * Get whether the GeckoFontScaleListener is currently enabled. + * + * @return True if the GeckoFontScaleListener is currently enabled. + */ public boolean getEnabled() { return mEnabled; } From 51fe895ba7bb5bbfed1d84e71ed5e46b7cc9d3d4 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:44 +0000 Subject: [PATCH 72/84] Bug 1460874 - Part 7: Automatically attach GeckoFontScaleListener through GeckoRuntime. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D17747 --HG-- extra : moz-landing-system : lando --- .../android/base/java/org/mozilla/gecko/GeckoApplication.java | 1 - .../src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java | 2 +- .../src/main/java/org/mozilla/geckoview/GeckoRuntime.java | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java index fc765f5f132c..a31f17753607 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java @@ -231,7 +231,6 @@ public class GeckoApplication extends Application final SharedPreferences prefs = GeckoSharedPrefs.forApp(this); prefs.registerOnSharedPreferenceChangeListener(this); onSharedPreferenceChanged(prefs, GeckoPreferences.PREFS_SYSTEM_FONT_SIZE); - GeckoFontScaleListener.getInstance().attachToContext(this); } private static GeckoRuntime sGeckoRuntime; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java index f7ecef58c38a..128a25c19964 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -22,7 +22,7 @@ import android.util.Log; * * @see android.provider.Settings.System#FONT_SCALE */ -/* package */ final class GeckoFontScaleListener +public final class GeckoFontScaleListener extends ContentObserver { private static final String LOGTAG = "GeckoFontScaleListener"; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java index 0c1923ac7f9b..b45ca558adb2 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java @@ -25,6 +25,7 @@ import android.util.Log; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.GeckoFontScaleListener; import org.mozilla.gecko.GeckoSystemStateListener; import org.mozilla.gecko.GeckoScreenOrientation; import org.mozilla.gecko.GeckoThread; @@ -212,6 +213,7 @@ public final class GeckoRuntime implements Parcelable { GeckoAppShell.setDisplayDpiOverride(settings.getDisplayDpiOverride()); GeckoAppShell.setScreenSizeOverride(settings.getScreenSizeOverride()); GeckoAppShell.setCrashHandlerService(settings.getCrashHandler()); + GeckoFontScaleListener.getInstance().attachToContext(context); final GeckoThread.InitInfo info = new GeckoThread.InitInfo(); info.args = settings.getArguments(); From a2454b987a0f3c9803b1dfcf412aaa6f9d0d11f2 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:42:51 +0000 Subject: [PATCH 73/84] Bug 1460874 - Part 8: Allow setting prefs via GeckoRuntimeSettings in Fennec, too. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D17748 --HG-- extra : moz-landing-system : lando --- mobile/android/components/BrowserCLH.js | 28 +++++++++++++++++++ .../components/MobileComponents.manifest | 1 + 2 files changed, 29 insertions(+) diff --git a/mobile/android/components/BrowserCLH.js b/mobile/android/components/BrowserCLH.js index 4f340c120ab4..6913b5c7f643 100644 --- a/mobile/android/components/BrowserCLH.js +++ b/mobile/android/components/BrowserCLH.js @@ -9,7 +9,9 @@ XPCOMUtils.defineLazyModuleGetters(this, { ActorManagerParent: "resource://gre/modules/ActorManagerParent.jsm", AppConstants: "resource://gre/modules/AppConstants.jsm", DelayedInit: "resource://gre/modules/DelayedInit.jsm", + EventDispatcher: "resource://gre/modules/Messaging.jsm", GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm", + Preferences: "resource://gre/modules/Preferences.jsm", Services: "resource://gre/modules/Services.jsm", }); @@ -174,6 +176,32 @@ BrowserCLH.prototype = { }); break; } + + case "profile-after-change": { + EventDispatcher.instance.registerListener(this, "GeckoView:SetDefaultPrefs"); + break; + } + } + }, + + onEvent(aEvent, aData, aCallback) { + switch (aEvent) { + case "GeckoView:SetDefaultPrefs": { + // While we want to allow setting certain preferences via GeckoView, we + // don't want to let it take over completely the management of those + // preferences. Therefore we don't handle the "ResetUserPrefs" message, + // and consequently we also apply any pref changes directly, i.e. *not* + // on the default branch. + const prefs = new Preferences(); + for (const name of Object.keys(aData)) { + try { + prefs.set(name, aData[name]); + } catch (e) { + Cu.reportError(`Failed to set preference ${name}: ${e}`); + } + } + break; + } } }, diff --git a/mobile/android/components/MobileComponents.manifest b/mobile/android/components/MobileComponents.manifest index 0e6121c7fbac..e247b2dc3c3c 100644 --- a/mobile/android/components/MobileComponents.manifest +++ b/mobile/android/components/MobileComponents.manifest @@ -65,6 +65,7 @@ contract @mozilla.org/helperapplauncherdialog;1 {e9d277a0-268a-4ec2-bb8c-10fdf3e component {be623d20-d305-11de-8a39-0800200c9a66} BrowserCLH.js application={aa3c5121-dab2-40e2-81ca-7ea25febc110} contract @mozilla.org/browser/browser-clh;1 {be623d20-d305-11de-8a39-0800200c9a66} category app-startup BrowserCLH service,@mozilla.org/browser/browser-clh;1 +category profile-after-change BrowserCLH @mozilla.org/browser/browser-clh;1 # ContentDispatchChooser.js component {5a072a22-1e66-4100-afc1-07aed8b62fc5} ContentDispatchChooser.js From 711b9872667abae619a862a8670239037fa87973 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:43:06 +0000 Subject: [PATCH 74/84] Bug 1460874 - Part 9: Expose font size/inflation options via GeckoRuntimeSettings. r=geckoview-reviewers,snorp Some callers might prefer to manually set the font size in analogy to WebView's WebSettings.setTextZoom(), respectively allow their users to do so. Subsequently, we're also going to switch the GeckoFontScaleListener to operate on those settings. Because the effects of font inflation are more difficult to quantify than a plain text zoom, we just check that operating the runtime setting sets the corresponding Gecko pref. Besides, there already are further platform (ref)tests checking the actual operation of font inflation itself. Differential Revision: https://phabricator.services.mozilla.com/D17749 --HG-- extra : moz-landing-system : lando --- mobile/android/geckoview/api.txt | 6 + .../geckoview/test/RuntimeSettingsTest.kt | 89 ++++++++++++++ .../geckoview/GeckoRuntimeSettings.java | 112 ++++++++++++++++++ .../mozilla/geckoview/doc-files/CHANGELOG.md | 5 +- 4 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index a8698afb9a12..6cf438ac1f03 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -214,6 +214,8 @@ package org.mozilla.geckoview { method @android.support.annotation.Nullable public java.lang.Float getDisplayDensityOverride(); method @android.support.annotation.Nullable public java.lang.Integer getDisplayDpiOverride(); method @android.support.annotation.NonNull public android.os.Bundle getExtras(); + method public boolean getFontInflationEnabled(); + method public float getFontSizeFactor(); method public boolean getJavaScriptEnabled(); method @android.support.annotation.Nullable public java.lang.String[] getLocales(); method public boolean getPauseForDebuggerEnabled(); @@ -225,6 +227,8 @@ package org.mozilla.geckoview { method public boolean getWebFontsEnabled(); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setAutoplayDefault(int); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setConsoleOutputEnabled(boolean); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setFontInflationEnabled(boolean); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setFontSizeFactor(float); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setJavaScriptEnabled(boolean); method public void setLocales(@android.support.annotation.Nullable java.lang.String[]); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setRemoteDebuggingEnabled(boolean); @@ -244,6 +248,8 @@ package org.mozilla.geckoview { method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder displayDensityOverride(float); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder displayDpiOverride(int); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder extras(@android.support.annotation.NonNull android.os.Bundle); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder fontInflation(boolean); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder fontSizeFactor(float); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder javaScriptEnabled(boolean); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder locales(java.lang.String[]); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder pauseForDebugger(boolean); diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt new file mode 100644 index 000000000000..9ad4f3112c37 --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt @@ -0,0 +1,89 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +package org.mozilla.geckoview.test + +import android.support.test.filters.MediumTest +import android.support.test.runner.AndroidJUnit4 +import org.hamcrest.Matchers.* +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ReuseSession +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI +import kotlin.math.roundToInt + +@RunWith(AndroidJUnit4::class) +@MediumTest +@ReuseSession(false) +class RuntimeSettingsTest : BaseSessionTest() { + + @WithDevToolsAPI + @Test fun fontSize() { + val settings = sessionRule.runtime.settings + settings.fontSizeFactor = 1.0f + sessionRule.session.loadTestPath(HELLO_HTML_PATH) + sessionRule.waitForPageStop() + + val fontSizeJs = "parseFloat(window.getComputedStyle(document.querySelector('p')).fontSize)" + val initialFontSize = sessionRule.session.evaluateJS(fontSizeJs) as Double + + val textSizeFactor = 2.0f + settings.fontSizeFactor = textSizeFactor + sessionRule.session.reload() + sessionRule.waitForPageStop() + var fontSize = sessionRule.session.evaluateJS(fontSizeJs) as Double + val expectedFontSize = initialFontSize * textSizeFactor + assertThat("old text size ${initialFontSize}px, new size should be ${expectedFontSize}px", + fontSize, closeTo(expectedFontSize, 0.1)) + + settings.fontSizeFactor = 1.0f + sessionRule.session.reload() + sessionRule.waitForPageStop() + fontSize = sessionRule.session.evaluateJS(fontSizeJs) as Double + assertThat("text size should be ${initialFontSize}px again", + fontSize, closeTo(initialFontSize, 0.1)) + } + + @WithDevToolsAPI + @Test fun fontInflation() { + val baseFontInflationMinTwips = 120 + val settings = sessionRule.runtime.settings + + settings.fontInflationEnabled = false; + settings.fontSizeFactor = 1.0f + val fontInflationPrefJs = "Services.prefs.getIntPref('font.size.inflation.minTwips')" + var prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("Gecko font inflation pref should be turned off", + prefValue, `is`(0)) + + settings.fontInflationEnabled = true; + prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("Gecko font inflation pref should be turned on", + prefValue, `is`(baseFontInflationMinTwips)) + + settings.fontSizeFactor = 2.0f + prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("Gecko font inflation pref should scale with increased font size factor", + prefValue, greaterThan(baseFontInflationMinTwips)) + + settings.fontSizeFactor = 0.5f + prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("Gecko font inflation pref should scale with decreased font size factor", + prefValue, lessThan(baseFontInflationMinTwips)) + + settings.fontSizeFactor = 0.0f + prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("setting font size factor to 0 turns off font inflation", + prefValue, `is`(0)) + assertThat("GeckoRuntimeSettings returns new font inflation state, too", + settings.fontInflationEnabled, `is`(false)) + + settings.fontSizeFactor = 1.0f + prefValue = (sessionRule.evaluateChromeJS(fontInflationPrefJs) as Double).roundToInt() + assertThat("Gecko font inflation pref remains turned off", + prefValue, `is`(0)) + assertThat("GeckoRuntimeSettings remains turned off", + settings.fontInflationEnabled, `is`(false)) + } +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java index 49e00ecde76c..7e5039d56b41 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -154,6 +154,43 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return this; } + /** + * Set a font size factor that will operate as a global text zoom. All font sizes will be + * multiplied by this factor. + * + *

The default factor is 1.0. + * + * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0 + * disables both this feature and + * {@link Builder#fontInflation font inflation}. + * @return The builder instance. + */ + public @NonNull Builder fontSizeFactor(float fontSizeFactor) { + getSettings().setFontSizeFactor(fontSizeFactor); + return this; + } + + /** + * Set whether or not font inflation for non mobile-friendly pages should be enabled. The + * default value of this setting is false. + * + *

When enabled, font sizes will be increased on all pages that are lacking a + * <meta> viewport tag and have been loaded in a session using + * {@link GeckoSessionSettings#VIEWPORT_MODE_MOBILE}. To improve readability, the font + * inflation logic will attempt to increase font sizes for the main text content of the page + * only. + * + *

The magnitude of font inflation applied depends on the + * {@link Builder#fontSizeFactor font size factor} currently in use. + * + * @param enabled A flag determining whether or not font inflation should be enabled. + * @return The builder instance. + */ + public @NonNull Builder fontInflation(boolean enabled) { + getSettings().setFontInflationEnabled(enabled); + return this; + } + /** * Set the display density override. * @@ -277,6 +314,10 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { "geckoview.console.enabled", false); /* package */ final Pref mAutoplayDefault = new Pref( "media.autoplay.default", AUTOPLAY_DEFAULT_BLOCKED); + /* package */ final Pref mFontSizeFactor = new Pref<>( + "font.size.systemFontScale", 100); + /* package */ final Pref mFontInflationMinTwips = new Pref<>( + "font.size.inflation.minTwips", 0); /* package */ boolean mDebugPause; /* package */ boolean mUseMaxScreenDepth; @@ -573,6 +614,77 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return mAutoplayDefault.get(); } + private static int FONT_INFLATION_BASE_VALUE = 120; + + /** + * Set a font size factor that will operate as a global text zoom. All font sizes will be + * multiplied by this factor. + * + *

The default factor is 1.0. + * + *

Currently, any changes only take effect after a reload of the session. + * + * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0 + * disables both this feature and + * {@link GeckoRuntimeSettings#setFontInflationEnabled font inflation}. + * @return This GeckoRuntimeSettings instance. + */ + public @NonNull GeckoRuntimeSettings setFontSizeFactor(float fontSizeFactor) { + if (fontSizeFactor < 0) { + throw new IllegalArgumentException("fontSizeFactor cannot be < 0"); + } + + final int fontSizePercentage = Math.round(fontSizeFactor * 100); + mFontSizeFactor.commit(Math.round(fontSizePercentage)); + if (getFontInflationEnabled()) { + final int scaledFontInflation = Math.round(FONT_INFLATION_BASE_VALUE * fontSizeFactor); + mFontInflationMinTwips.commit(scaledFontInflation); + } + return this; + } + + /** + * Gets the currently applied font size factor. + * + * @return The currently applied font size factor. + */ + public float getFontSizeFactor() { + return mFontSizeFactor.get() / 100f; + } + + /** + * Set whether or not font inflation for non mobile-friendly pages should be enabled. The + * default value of this setting is false. + * + *

When enabled, font sizes will be increased on all pages that are lacking a <meta> + * viewport tag and have been loaded in a session using + * {@link GeckoSessionSettings#VIEWPORT_MODE_MOBILE}. To improve readability, the font inflation + * logic will attempt to increase font sizes for the main text content of the page only. + * + *

The magnitude of font inflation applied depends on the + * {@link GeckoRuntimeSettings#setFontSizeFactor font size factor} currently in use. + * + *

Currently, any changes only take effect after a reload of the session. + * + * @param enabled A flag determining whether or not font inflation should be enabled. + * @return This GeckoRuntimeSettings instance. + */ + public @NonNull GeckoRuntimeSettings setFontInflationEnabled(boolean enabled) { + final int minTwips = + enabled ? Math.round(FONT_INFLATION_BASE_VALUE * getFontSizeFactor()) : 0; + mFontInflationMinTwips.commit(minTwips); + return this; + } + + /** + * Get whether or not font inflation for non mobile-friendly pages is currently enabled. + * + * @return True if font inflation is enabled. + */ + public boolean getFontInflationEnabled() { + return mFontInflationMinTwips.get() > 0; + } + @Override // Parcelable public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md index ccee9450240e..70c7a1cc2275 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -9,6 +9,9 @@ exclude: true

GeckoView API Changelog.

## v67 +- Added GeckoRuntimeSettings for setting a font size scaling factor, and for + enabling font inflation for non-mobile-friendly pages. + - Updated video autoplay API to reflect changes in Gecko. Instead of being a per-video permission in the PermissionDelegate, it is a runtime setting that either allows or blocks autoplay videos. @@ -134,4 +137,4 @@ exclude: true [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String- [65.25]: ../GeckoResult.html -[api-version]: fb3375bbe85695b337d830dcf3fffec7231f4e4b +[api-version]: 4cd5232f60675d7eaaad47fb62d7245f643039fe From e24f654f529e6c74f5881a43f7e6f60d3bce21b8 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:43:09 +0000 Subject: [PATCH 75/84] Bug 1460874 - Part 10: Set font size settings in listener using GeckoRuntimeSettings. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D17750 --HG-- extra : moz-landing-system : lando --- .../mozilla/gecko/GeckoFontScaleListener.java | 32 ++++++++++++------- .../org/mozilla/geckoview/GeckoRuntime.java | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java index 128a25c19964..2648a4c13e73 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.util.ThreadUtils; +import org.mozilla.geckoview.GeckoRuntimeSettings; import android.annotation.SuppressLint; import android.content.ContentResolver; @@ -26,10 +27,6 @@ public final class GeckoFontScaleListener extends ContentObserver { private static final String LOGTAG = "GeckoFontScaleListener"; - private static final String PREF_SYSTEM_FONT_SCALE = "font.size.systemFontScale"; - private static final String PREF_FONT_INFLATION = "font.size.inflation.minTwips"; - private static final int FONT_INFLATION_OFF = 0; - private static final int FONT_INFLATION_ON_DEFAULT_VALUE = 120; private static final float DEFAULT_FONT_SCALE = 1.0f; // We're referencing the *application* context, so this is in fact okay. @@ -37,10 +34,15 @@ public final class GeckoFontScaleListener private static final GeckoFontScaleListener sInstance = new GeckoFontScaleListener(); private Context mApplicationContext; + private GeckoRuntimeSettings mSettings; + private boolean mAttached; private boolean mEnabled; private boolean mRunning; + private float mPrevGeckoFontScale; + private boolean mPrevFontInflationState; + public static GeckoFontScaleListener getInstance() { return sInstance; } @@ -54,7 +56,8 @@ public final class GeckoFontScaleListener * Prepare the GeckoFontScaleListener for usage. If it has been previously enabled, it will * now start actively working. */ - public void attachToContext(final Context context) { + public void attachToContext(final Context context, + final GeckoRuntimeSettings settings) { ThreadUtils.assertOnUiThread(); if (mAttached) { @@ -63,12 +66,14 @@ public final class GeckoFontScaleListener } mAttached = true; + mSettings = settings; mApplicationContext = context.getApplicationContext(); onEnabledChange(); } /** * Detaches the context and also stops the GeckoFontScaleListener if it was previously enabled. + * This will also restore the previously used font size settings. */ public void detachFromContext() { ThreadUtils.assertOnUiThread(); @@ -80,12 +85,13 @@ public final class GeckoFontScaleListener stop(); mApplicationContext = null; + mSettings = null; mAttached = false; } /** * Controls whether the GeckoFontScaleListener should automatically adjust font sizes for web - * content in Gecko. + * content in Gecko. When disabling, this will restore the previously used font size settings. * *

This method can be called at any time, but the GeckoFontScaleListener won't start actively * adjusting font sizes until it has been attached to a context. @@ -124,6 +130,8 @@ public final class GeckoFontScaleListener return; } + mPrevGeckoFontScale = mSettings.getFontSizeFactor(); + mPrevFontInflationState = mSettings.getFontInflationEnabled(); ContentResolver contentResolver = mApplicationContext.getContentResolver(); Uri fontSizeSetting = Settings.System.getUriFor(Settings.System.FONT_SCALE); contentResolver.registerContentObserver(fontSizeSetting, false, this); @@ -146,18 +154,18 @@ public final class GeckoFontScaleListener private void onSystemFontScaleChange(final ContentResolver contentResolver, boolean stopping) { float fontScale; - int fontInflation; + boolean fontInflationEnabled; if (!stopping) { // Either we were enabled, or else the system font scale changed. fontScale = Settings.System.getFloat(contentResolver, Settings.System.FONT_SCALE, DEFAULT_FONT_SCALE); - fontInflation = Math.round(FONT_INFLATION_ON_DEFAULT_VALUE * fontScale); + fontInflationEnabled = true; } else { // We were turned off. - fontScale = DEFAULT_FONT_SCALE; - fontInflation = FONT_INFLATION_OFF; + fontScale = mPrevGeckoFontScale; + fontInflationEnabled = mPrevFontInflationState; } - PrefsHelper.setPref(PREF_FONT_INFLATION, fontInflation); - PrefsHelper.setPref(PREF_SYSTEM_FONT_SCALE, Math.round(fontScale * 100)); + mSettings.setFontInflationEnabled(fontInflationEnabled); + mSettings.setFontSizeFactor(fontScale); } @UiThread // See constructor. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java index b45ca558adb2..dbc76eaf538b 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java @@ -213,7 +213,7 @@ public final class GeckoRuntime implements Parcelable { GeckoAppShell.setDisplayDpiOverride(settings.getDisplayDpiOverride()); GeckoAppShell.setScreenSizeOverride(settings.getScreenSizeOverride()); GeckoAppShell.setCrashHandlerService(settings.getCrashHandler()); - GeckoFontScaleListener.getInstance().attachToContext(context); + GeckoFontScaleListener.getInstance().attachToContext(context, settings); final GeckoThread.InitInfo info = new GeckoThread.InitInfo(); info.args = settings.getArguments(); From c5a86e4d1f5bff6a774883775a3fbda4be78c91f Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:44:19 +0000 Subject: [PATCH 76/84] Bug 1460874 - Part 11: Allow toggling font scale listener via GeckoRuntimeSettings. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D17751 --HG-- extra : moz-landing-system : lando --- mobile/android/geckoview/api.txt | 3 ++ .../geckoview/test/RuntimeSettingsTest.kt | 54 +++++++++++++++++++ .../geckoview/GeckoRuntimeSettings.java | 40 ++++++++++++++ .../mozilla/geckoview/doc-files/CHANGELOG.md | 5 +- 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index 6cf438ac1f03..cc02b398d89f 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -207,6 +207,7 @@ package org.mozilla.geckoview { @android.support.annotation.AnyThread public final class GeckoRuntimeSettings extends org.mozilla.geckoview.RuntimeSettings { method @android.support.annotation.NonNull public java.lang.String[] getArguments(); + method public boolean getAutomaticFontSizeAdjustment(); method public int getAutoplayDefault(); method public boolean getConsoleOutputEnabled(); method @android.support.annotation.NonNull public org.mozilla.geckoview.ContentBlocking.Settings getContentBlocking(); @@ -225,6 +226,7 @@ package org.mozilla.geckoview { method public boolean getUseContentProcessHint(); method public boolean getUseMaxScreenDepth(); method public boolean getWebFontsEnabled(); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setAutomaticFontSizeAdjustment(boolean); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setAutoplayDefault(int); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setConsoleOutputEnabled(boolean); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings setFontInflationEnabled(boolean); @@ -241,6 +243,7 @@ package org.mozilla.geckoview { @android.support.annotation.AnyThread public static final class GeckoRuntimeSettings.Builder extends org.mozilla.geckoview.RuntimeSettings.Builder { ctor public Builder(); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder arguments(@android.support.annotation.NonNull java.lang.String[]); + method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder automaticFontSizeAdjustment(boolean); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder autoplayDefault(int); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder consoleOutput(boolean); method @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoRuntimeSettings.Builder contentBlocking(@android.support.annotation.NonNull org.mozilla.geckoview.ContentBlocking.Settings); diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt index 9ad4f3112c37..9adf5f3e9b1b 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt @@ -4,6 +4,8 @@ package org.mozilla.geckoview.test +import android.provider.Settings +import android.support.test.InstrumentationRegistry import android.support.test.filters.MediumTest import android.support.test.runner.AndroidJUnit4 import org.hamcrest.Matchers.* @@ -18,6 +20,58 @@ import kotlin.math.roundToInt @ReuseSession(false) class RuntimeSettingsTest : BaseSessionTest() { + @Test fun automaticFontSize() { + val settings = sessionRule.runtime.settings + var initialFontSize = 2.15f + var initialFontInflation = true + settings.fontSizeFactor = initialFontSize + assertThat("initial font scale $initialFontSize set", + settings.fontSizeFactor.toDouble(), closeTo(initialFontSize.toDouble(), 0.05)) + settings.fontInflationEnabled = initialFontInflation + assertThat("font inflation initially set to $initialFontInflation", + settings.fontInflationEnabled, `is`(initialFontInflation)) + + + settings.automaticFontSizeAdjustment = true + val contentResolver = InstrumentationRegistry.getTargetContext().contentResolver + val expectedFontSizeFactor = Settings.System.getFloat(contentResolver, + Settings.System.FONT_SCALE, 1.0f) + assertThat("Gecko font scale should match system font scale", + settings.fontSizeFactor.toDouble(), closeTo(expectedFontSizeFactor.toDouble(), 0.05)) + assertThat("font inflation enabled", + settings.fontInflationEnabled, `is`(true)) + + settings.automaticFontSizeAdjustment = false + assertThat("Gecko font scale restored to previous value", + settings.fontSizeFactor.toDouble(), closeTo(initialFontSize.toDouble(), 0.05)) + assertThat("font inflation restored to previous value", + settings.fontInflationEnabled, `is`(initialFontInflation)) + + // Now check with that with font inflation initially off, the initial state is still + // restored correctly after switching auto mode back off. + // Also reset font size factor back to its default value of 1.0f. + initialFontSize = 1.0f + initialFontInflation = false + settings.fontSizeFactor = initialFontSize + assertThat("initial font scale $initialFontSize set", + settings.fontSizeFactor.toDouble(), closeTo(initialFontSize.toDouble(), 0.05)) + settings.fontInflationEnabled = initialFontInflation + assertThat("font inflation initially set to $initialFontInflation", + settings.fontInflationEnabled, `is`(initialFontInflation)) + + settings.automaticFontSizeAdjustment = true + assertThat("Gecko font scale should match system font scale", + settings.fontSizeFactor.toDouble(), closeTo(expectedFontSizeFactor.toDouble(), 0.05)) + assertThat("font inflation enabled", + settings.fontInflationEnabled, `is`(true)) + + settings.automaticFontSizeAdjustment = false + assertThat("Gecko font scale restored to previous value", + settings.fontSizeFactor.toDouble(), closeTo(initialFontSize.toDouble(), 0.05)) + assertThat("font inflation restored to previous value", + settings.fontInflationEnabled, `is`(initialFontInflation)) + } + @WithDevToolsAPI @Test fun fontSize() { val settings = sessionRule.runtime.settings diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java index 7e5039d56b41..612f34470d4b 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -20,6 +20,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.mozilla.gecko.EventDispatcher; +import org.mozilla.gecko.GeckoFontScaleListener; import org.mozilla.gecko.util.GeckoBundle; @AnyThread @@ -154,6 +155,19 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return this; } + /** + * Set whether or not font sizes in web content should be automatically scaled according to + * the device's current system font scale setting. + * + * @param enabled A flag determining whether or not font sizes should be scaled automatically + * to match the device's system font scale. + * @return The builder instance. + */ + public @NonNull Builder automaticFontSizeAdjustment(boolean enabled) { + getSettings().setAutomaticFontSizeAdjustment(enabled); + return this; + } + /** * Set a font size factor that will operate as a global text zoom. All font sizes will be * multiplied by this factor. @@ -579,6 +593,32 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { return mConsoleOutput.get(); } + /** + * Set whether or not font sizes in web content should be automatically scaled according to + * the device's current system font scale setting. + * Disabling this setting will restore the previously used values for + * {@link GeckoRuntimeSettings#getFontSizeFactor()} and + * {@link GeckoRuntimeSettings#getFontInflationEnabled()}. + * + * @param enabled A flag determining whether or not font sizes should be scaled automatically + * to match the device's system font scale. + * @return This GeckoRuntimeSettings instance. + */ + public @NonNull GeckoRuntimeSettings setAutomaticFontSizeAdjustment(boolean enabled) { + GeckoFontScaleListener.getInstance().setEnabled(enabled); + return this; + } + + /** + * Get whether or not the font sizes for web content are automatically adjusted to match the + * device's system font scale setting. + * + * @return True if font sizes are automatically adjusted. + */ + public boolean getAutomaticFontSizeAdjustment() { + return GeckoFontScaleListener.getInstance().getEnabled(); + } + // Sync values with dom/media/nsIAutoplay.idl. @Retention(RetentionPolicy.SOURCE) @IntDef({ AUTOPLAY_DEFAULT_ALLOWED, AUTOPLAY_DEFAULT_BLOCKED }) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md index 70c7a1cc2275..7a23920330da 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -9,6 +9,9 @@ exclude: true

GeckoView API Changelog.

## v67 +- Added GeckoRuntimeSetting for automatically adjusting font size settings + depending on the OS-level font size setting. + - Added GeckoRuntimeSettings for setting a font size scaling factor, and for enabling font inflation for non-mobile-friendly pages. @@ -137,4 +140,4 @@ exclude: true [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String- [65.25]: ../GeckoResult.html -[api-version]: 4cd5232f60675d7eaaad47fb62d7245f643039fe +[api-version]: f318744a2a5bd8058977a5709a3e9a3b73d5202b From 6ae3b86617af5fe5127c8c6f8734002ac5c95a9e Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Thu, 14 Feb 2019 20:43:25 +0000 Subject: [PATCH 77/84] Bug 1460874 - Part 12: Enforce sensible API usage for manual font size settings. r=snorp Modifying the manual font size settings while the GeckoFontScaleListener is active is theoretically possible, but probably not the most sensible way of using that API. Therefore, we prohibit it and throw an exception in that case. There is one complication, though: The very same API is used by the font scale listener itself in order to modify the font size settings according to the system font scale. Therefore, we have to move the GeckoFontScaleListener into the GeckoView package itself, so that we can provide a package-private internal API that bypasses the above usage checks. This means that going forward, Fennec needs to use the official GeckoView API to communicate with the font scale listener, too. As we've moved out the Shared- Preferences watching in part 5, this doesn't pose any insurmountable difficulties. Because for a short while I encountered some strange crashes where getRuntime() in GeckoApplication apparently returned null while trying to initialise the listener, I'm tying its initialisation to creation of the runtime, just to be on the safe side. Differential Revision: https://phabricator.services.mozilla.com/D18507 --HG-- rename : mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java => mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoFontScaleListener.java extra : moz-landing-system : lando --- .../org/mozilla/gecko/GeckoApplication.java | 10 ++++-- .../GeckoFontScaleListener.java | 8 ++--- .../org/mozilla/geckoview/GeckoRuntime.java | 1 - .../geckoview/GeckoRuntimeSettings.java | 31 ++++++++++++++++++- 4 files changed, 42 insertions(+), 8 deletions(-) rename mobile/android/geckoview/src/main/java/org/mozilla/{gecko => geckoview}/GeckoFontScaleListener.java (96%) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java index a31f17753607..18ef17ddc1de 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java @@ -215,7 +215,6 @@ public class GeckoApplication extends Application public void onApplicationForeground() { if (mIsInitialResume) { GeckoBatteryManager.getInstance().start(this); - initFontScaleListener(); GeckoNetworkManager.getInstance().start(this); mIsInitialResume = false; } else if (mPausedGecko) { @@ -287,6 +286,7 @@ public class GeckoApplication extends Application } sGeckoRuntime = GeckoRuntime.create(context, builder.build()); + ((GeckoApplication) GeckoAppShell.getApplicationContext()).initFontScaleListener(); return sGeckoRuntime; } @@ -298,6 +298,12 @@ public class GeckoApplication extends Application final Context oldContext = GeckoAppShell.getApplicationContext(); if (oldContext instanceof GeckoApplication) { ((GeckoApplication) oldContext).onDestroy(); + if (sGeckoRuntime != null) { + // The listener is registered when the runtime gets created, so if we already have + // a runtime, we need to transfer the listener registration to the new instance. + // The old listener will be unregistered through onDestroy(). + GeckoSharedPrefs.forApp(this).registerOnSharedPreferenceChangeListener(this); + } } final Context context = getApplicationContext(); @@ -924,7 +930,7 @@ public class GeckoApplication extends Application public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if (GeckoPreferences.PREFS_SYSTEM_FONT_SIZE.equals(key)) { final boolean enabled = prefs.getBoolean(GeckoPreferences.PREFS_SYSTEM_FONT_SIZE, false); - GeckoFontScaleListener.getInstance().setEnabled(enabled); + getRuntime().getSettings().setAutomaticFontSizeAdjustment(enabled); } } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoFontScaleListener.java similarity index 96% rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java rename to mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoFontScaleListener.java index 2648a4c13e73..2f4f385863ed 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoFontScaleListener.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoFontScaleListener.java @@ -3,7 +3,7 @@ * 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/. */ -package org.mozilla.gecko; +package org.mozilla.geckoview; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.geckoview.GeckoRuntimeSettings; @@ -23,7 +23,7 @@ import android.util.Log; * * @see android.provider.Settings.System#FONT_SCALE */ -public final class GeckoFontScaleListener +/* package */ final class GeckoFontScaleListener extends ContentObserver { private static final String LOGTAG = "GeckoFontScaleListener"; @@ -164,8 +164,8 @@ public final class GeckoFontScaleListener fontInflationEnabled = mPrevFontInflationState; } - mSettings.setFontInflationEnabled(fontInflationEnabled); - mSettings.setFontSizeFactor(fontScale); + mSettings.setFontInflationEnabledInternal(fontInflationEnabled); + mSettings.setFontSizeFactorInternal(fontScale); } @UiThread // See constructor. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java index dbc76eaf538b..963cf9ca7d58 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java @@ -25,7 +25,6 @@ import android.util.Log; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoFontScaleListener; import org.mozilla.gecko.GeckoSystemStateListener; import org.mozilla.gecko.GeckoScreenOrientation; import org.mozilla.gecko.GeckoThread; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java index 612f34470d4b..8f0a8ac9386d 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -20,7 +20,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.GeckoFontScaleListener; import org.mozilla.gecko.util.GeckoBundle; @AnyThread @@ -174,6 +173,10 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { * *

The default factor is 1.0. * + *

This setting cannot be modified if + * {@link Builder#automaticFontSizeAdjustment automatic font size adjustment} + * has already been enabled. + * * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0 * disables both this feature and * {@link Builder#fontInflation font inflation}. @@ -197,6 +200,10 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { *

The magnitude of font inflation applied depends on the * {@link Builder#fontSizeFactor font size factor} currently in use. * + *

This setting cannot be modified if + * {@link Builder#automaticFontSizeAdjustment automatic font size adjustment} + * has already been enabled. + * * @param enabled A flag determining whether or not font inflation should be enabled. * @return The builder instance. */ @@ -664,12 +671,23 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { * *

Currently, any changes only take effect after a reload of the session. * + *

This setting cannot be modified while + * {@link GeckoRuntimeSettings#setAutomaticFontSizeAdjustment automatic font size adjustment} + * is enabled. + * * @param fontSizeFactor The factor to be used for scaling all text. Setting a value of 0 * disables both this feature and * {@link GeckoRuntimeSettings#setFontInflationEnabled font inflation}. * @return This GeckoRuntimeSettings instance. */ public @NonNull GeckoRuntimeSettings setFontSizeFactor(float fontSizeFactor) { + if (getAutomaticFontSizeAdjustment()) { + throw new IllegalStateException("Not allowed when automatic font size adjustment is enabled"); + } + return setFontSizeFactorInternal(fontSizeFactor); + } + + /* package */ @NonNull GeckoRuntimeSettings setFontSizeFactorInternal(float fontSizeFactor) { if (fontSizeFactor < 0) { throw new IllegalArgumentException("fontSizeFactor cannot be < 0"); } @@ -706,10 +724,21 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { * *

Currently, any changes only take effect after a reload of the session. * + *

This setting cannot be modified while + * {@link GeckoRuntimeSettings#setAutomaticFontSizeAdjustment automatic font size adjustment} + * is enabled. + * * @param enabled A flag determining whether or not font inflation should be enabled. * @return This GeckoRuntimeSettings instance. */ public @NonNull GeckoRuntimeSettings setFontInflationEnabled(boolean enabled) { + if (getAutomaticFontSizeAdjustment()) { + throw new IllegalStateException("Not allowed when automatic font size adjustment is enabled"); + } + return setFontInflationEnabledInternal(enabled); + } + + /* package */ @NonNull GeckoRuntimeSettings setFontInflationEnabledInternal(boolean enabled) { final int minTwips = enabled ? Math.round(FONT_INFLATION_BASE_VALUE * getFontSizeFactor()) : 0; mFontInflationMinTwips.commit(minTwips); From 349d4a5381ec6d96e8e6ef2899ab304bb530f50b Mon Sep 17 00:00:00 2001 From: Gerald Squelart Date: Thu, 14 Feb 2019 21:19:42 +0000 Subject: [PATCH 78/84] Bug 1527564 - Child forwards its process name to the profiler - r=mstange Profiler was previously fetching process name at the time of shutdown serialization, at which point that name could have already been destroyed. Now the child process just forwards the name as soon as it is given, so the profiler can store it for later. Differential Revision: https://phabricator.services.mozilla.com/D19732 --HG-- extra : moz-landing-system : lando --- dom/ipc/ContentChild.cpp | 6 +++++- tools/profiler/core/ProfiledThreadData.cpp | 15 ++++++--------- tools/profiler/core/ProfiledThreadData.h | 3 ++- tools/profiler/core/ProfilerBacktrace.cpp | 2 +- tools/profiler/core/platform.cpp | 13 +++++++++++++ tools/profiler/public/GeckoProfiler.h | 3 +++ 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index cc3b6018336a..41eb35fa7fb7 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -734,7 +734,11 @@ void ContentChild::SetProcessName(const nsAString& aName) { } mProcessName = aName; - mozilla::ipc::SetThisProcessName(NS_LossyConvertUTF16toASCII(aName).get()); + NS_LossyConvertUTF16toASCII asciiName(aName); + mozilla::ipc::SetThisProcessName(asciiName.get()); +#ifdef MOZ_GECKO_PROFILER + profiler_set_process_name(asciiName); +#endif } NS_IMETHODIMP diff --git a/tools/profiler/core/ProfiledThreadData.cpp b/tools/profiler/core/ProfiledThreadData.cpp index a118092f26b5..f984a1cfdc7e 100644 --- a/tools/profiler/core/ProfiledThreadData.cpp +++ b/tools/profiler/core/ProfiledThreadData.cpp @@ -40,6 +40,7 @@ ProfiledThreadData::~ProfiledThreadData() { void ProfiledThreadData::StreamJSON(const ProfileBuffer& aBuffer, JSContext* aCx, SpliceableJSONWriter& aWriter, + const nsACString& aProcessName, const mozilla::TimeStamp& aProcessStartTime, double aSinceTime, bool JSTracerEnabled) { if (mJITFrameInfoForPreviousJSContexts && @@ -64,7 +65,7 @@ void ProfiledThreadData::StreamJSON(const ProfileBuffer& aBuffer, aWriter.Start(); { StreamSamplesAndMarkers(mThreadInfo->Name(), mThreadInfo->ThreadId(), - aBuffer, aWriter, aProcessStartTime, + aBuffer, aWriter, aProcessName, aProcessStartTime, mThreadInfo->RegisterTime(), mUnregisterTime, aSinceTime, uniqueStacks); @@ -204,6 +205,7 @@ void ProfiledThreadData::StreamTraceLoggerJSON( void StreamSamplesAndMarkers(const char* aName, int aThreadId, const ProfileBuffer& aBuffer, SpliceableJSONWriter& aWriter, + const nsACString& aProcessName, const mozilla::TimeStamp& aProcessStartTime, const mozilla::TimeStamp& aRegisterTime, const mozilla::TimeStamp& aUnregisterTime, @@ -213,16 +215,11 @@ void StreamSamplesAndMarkers(const char* aName, int aThreadId, aWriter.StringProperty("name", aName); + // Use given process name (if any), unless we're the parent process. if (XRE_IsParentProcess()) { aWriter.StringProperty("processName", "Parent Process"); - } else if (mozilla::dom::ContentChild* cc = - mozilla::dom::ContentChild::GetSingleton()) { - // Try to get the process name from ContentChild. - nsAutoCString processName; - cc->GetProcessName(processName); - if (!processName.IsEmpty()) { - aWriter.StringProperty("processName", processName.Data()); - } + } else if (!aProcessName.IsEmpty()) { + aWriter.StringProperty("processName", aProcessName.Data()); } aWriter.IntProperty("tid", static_cast(aThreadId)); diff --git a/tools/profiler/core/ProfiledThreadData.h b/tools/profiler/core/ProfiledThreadData.h index 497fc627b702..20b0f68ba264 100644 --- a/tools/profiler/core/ProfiledThreadData.h +++ b/tools/profiler/core/ProfiledThreadData.h @@ -63,7 +63,7 @@ class ProfiledThreadData final { mozilla::Maybe& LastSample() { return mLastSample; } void StreamJSON(const ProfileBuffer& aBuffer, JSContext* aCx, - SpliceableJSONWriter& aWriter, + SpliceableJSONWriter& aWriter, const nsACString& aProcessName, const mozilla::TimeStamp& aProcessStartTime, double aSinceTime, bool aJSTracerEnabled); @@ -130,6 +130,7 @@ class ProfiledThreadData final { void StreamSamplesAndMarkers(const char* aName, int aThreadId, const ProfileBuffer& aBuffer, SpliceableJSONWriter& aWriter, + const nsACString& aProcessName, const mozilla::TimeStamp& aProcessStartTime, const mozilla::TimeStamp& aRegisterTime, const mozilla::TimeStamp& aUnregisterTime, diff --git a/tools/profiler/core/ProfilerBacktrace.cpp b/tools/profiler/core/ProfilerBacktrace.cpp index f3463809042c..eab9655af4f9 100644 --- a/tools/profiler/core/ProfilerBacktrace.cpp +++ b/tools/profiler/core/ProfilerBacktrace.cpp @@ -27,7 +27,7 @@ void ProfilerBacktrace::StreamJSON(SpliceableJSONWriter& aWriter, // JitReturnAddr entries. For synchronous samples, JIT frames get expanded // at sample time. StreamSamplesAndMarkers(mName.get(), mThreadId, *mBuffer.get(), aWriter, - aProcessStartTime, + NS_LITERAL_CSTRING(""), aProcessStartTime, /* aRegisterTime */ mozilla::TimeStamp(), /* aUnregisterTime */ mozilla::TimeStamp(), /* aSinceTime */ 0, aUniqueStacks); diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index 42204f8ea07c..7701e60697d6 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -356,6 +356,8 @@ class CorePS { } #endif + PS_GET_AND_SET(const nsACString&, ProcessName) + private: // The singleton instance static CorePS* sInstance; @@ -378,6 +380,9 @@ class CorePS { // LUL's state. Null prior to the first activation, non-null thereafter. UniquePtr mLul; #endif + + // Process name, provided by child process initialization code. + nsAutoCString mProcessName; }; CorePS* CorePS::sInstance = nullptr; @@ -2005,6 +2010,7 @@ static void locked_profiler_stream_json_for_this_process( registeredThread ? registeredThread->GetJSContext() : nullptr; ProfiledThreadData* profiledThreadData = thread.second(); profiledThreadData->StreamJSON(buffer, cx, aWriter, + CorePS::ProcessName(aLock), CorePS::ProcessStartTime(), aSinceTime, ActivePS::FeatureJSTracer(aLock)); } @@ -2022,6 +2028,7 @@ static void locked_profiler_stream_json_for_this_process( ProfiledThreadData profiledThreadData( threadInfo, nullptr, ActivePS::FeatureResponsiveness(aLock)); profiledThreadData.StreamJSON(*javaBuffer.get(), nullptr, aWriter, + CorePS::ProcessName(aLock), CorePS::ProcessStartTime(), aSinceTime, ActivePS::FeatureJSTracer(aLock)); @@ -2897,6 +2904,12 @@ static bool WriteProfileToJSONWriter(SpliceableChunkedJSONWriter& aWriter, return true; } +void profiler_set_process_name(const nsACString& aProcessName) { + LOG("profiler_set_process_name(\"%s\")", aProcessName.Data()); + PSAutoLock lock(gPSMutex); + CorePS::SetProcessName(lock, aProcessName); +} + UniquePtr profiler_get_profile(double aSinceTime, bool aIsShuttingDown) { LOG("profiler_get_profile"); diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index 5f250dcd50d6..ff3e8868579b 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -774,6 +774,9 @@ class MOZ_RAII AutoProfilerTextMarker { // Output profiles //--------------------------------------------------------------------------- +// Set a user-friendly process name, used in JSON stream. +void profiler_set_process_name(const nsACString& aProcessName); + // Get the profile encoded as a JSON string. A no-op (returning nullptr) if the // profiler is inactive. // If aIsShuttingDown is true, the current time is included as the process From 3fcd2d85d2149f5ff191f6c1b885cab3677ec644 Mon Sep 17 00:00:00 2001 From: Thomas Daede Date: Thu, 14 Feb 2019 21:30:22 +0000 Subject: [PATCH 79/84] Bug 1511224 - Add win64-nasm toolchain. r=ted,jya,glandium Differential Revision: https://phabricator.services.mozilla.com/D13875 --HG-- extra : moz-landing-system : lando --- build/mozconfig.common | 1 + build/mozconfig.nasm | 11 +++++++++ media/ffvpx/config_win64.asm | 2 +- taskcluster/ci/build/windows.yml | 33 ++++++++++++++++++++++++++ taskcluster/ci/fetch/toolchains.yml | 8 +++++++ taskcluster/ci/toolchain/clang.yml | 2 +- taskcluster/ci/toolchain/kind.yml | 1 + taskcluster/ci/toolchain/nasm.yml | 18 ++++++++++++++ taskcluster/scripts/misc/build-nasm.sh | 25 +++++++++++++++++++ 9 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 build/mozconfig.nasm create mode 100644 taskcluster/ci/toolchain/nasm.yml create mode 100755 taskcluster/scripts/misc/build-nasm.sh diff --git a/build/mozconfig.common b/build/mozconfig.common index 308795ff549c..2951948a18dd 100644 --- a/build/mozconfig.common +++ b/build/mozconfig.common @@ -19,6 +19,7 @@ MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0} ac_add_options --enable-js-shell +. "$topsrcdir/build/mozconfig.nasm" . "$topsrcdir/build/mozconfig.node" . "$topsrcdir/build/mozconfig.automation" . "$topsrcdir/build/mozconfig.rust" diff --git a/build/mozconfig.nasm b/build/mozconfig.nasm new file mode 100644 index 000000000000..9db9ba2b0303 --- /dev/null +++ b/build/mozconfig.nasm @@ -0,0 +1,11 @@ +# 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/. + +case "$(uname -s)" in +MINGW*) + export NASM=$topsrcdir/nasm/nasm.exe + ;; +*) + ;; +esac diff --git a/media/ffvpx/config_win64.asm b/media/ffvpx/config_win64.asm index fecfee4988a5..64e1c6dfb62d 100644 --- a/media/ffvpx/config_win64.asm +++ b/media/ffvpx/config_win64.asm @@ -54,7 +54,7 @@ %define HAVE_SSE42 1 %define HAVE_SSSE3 1 %define HAVE_XOP 1 -%define HAVE_CPUNOP 1 +%define HAVE_CPUNOP 0 %define HAVE_I686 1 %define HAVE_MIPSFPU 0 %define HAVE_MIPS32R2 0 diff --git a/taskcluster/ci/build/windows.yml b/taskcluster/ci/build/windows.yml index 89aba43c7cd6..9063ccd89bfb 100755 --- a/taskcluster/ci/build/windows.yml +++ b/taskcluster/ci/build/windows.yml @@ -34,6 +34,7 @@ win32/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32/opt: @@ -67,6 +68,7 @@ win32/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32/pgo: @@ -100,6 +102,7 @@ win32/pgo: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64/debug: @@ -133,6 +136,7 @@ win64/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-fuzzing/debug: @@ -168,6 +172,7 @@ win64-fuzzing/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-plain/debug: @@ -201,6 +206,7 @@ win64-plain/debug: - win64-clang-cl - win64-rust - win64-node + - win64-nasm - win64-cbindgen win64/opt: @@ -234,6 +240,7 @@ win64/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-plain/opt: @@ -267,6 +274,7 @@ win64-plain/opt: toolchains: - win64-clang-cl - win64-rust + - win64-nasm - win64-node - win64-cbindgen @@ -314,6 +322,7 @@ win32-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-nightly/opt: @@ -353,6 +362,7 @@ win64-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64/pgo: @@ -386,6 +396,7 @@ win64/pgo: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-add-on-devel/opt: @@ -419,6 +430,7 @@ win32-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-add-on-devel/opt: @@ -452,6 +464,7 @@ win64-add-on-devel/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-noopt/debug: @@ -484,6 +497,7 @@ win64-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-noopt/debug: @@ -516,6 +530,7 @@ win32-noopt/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-rusttests/opt: @@ -553,6 +568,7 @@ win32-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-rusttests/debug: @@ -590,6 +606,7 @@ win32-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-rusttests/opt: @@ -622,6 +639,7 @@ win64-rusttests/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-rusttests/debug: @@ -654,6 +672,7 @@ win64-rusttests/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-ccov/debug: @@ -690,6 +709,7 @@ win64-ccov/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node fetches: toolchain: @@ -726,6 +746,7 @@ win64-asan/debug: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan/opt: @@ -760,6 +781,7 @@ win64-asan/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan-reporter-nightly/opt: @@ -802,6 +824,7 @@ win64-asan-reporter-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-asan-fuzzing/opt: @@ -835,6 +858,7 @@ win64-asan-fuzzing/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-devedition-nightly/opt: @@ -882,6 +906,7 @@ win32-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-devedition-nightly/opt: @@ -922,6 +947,7 @@ win64-devedition-nightly/opt: - win64-rust-size - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-msvc/debug: @@ -953,6 +979,7 @@ win32-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-msvc/opt: @@ -985,6 +1012,7 @@ win32-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-msvc/debug: @@ -1016,6 +1044,7 @@ win64-msvc/debug: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-msvc/opt: @@ -1048,6 +1077,7 @@ win64-msvc/opt: - win64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64/debug: @@ -1083,6 +1113,7 @@ win64-aarch64/debug: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64/opt: @@ -1118,6 +1149,7 @@ win64-aarch64/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win64-aarch64-nightly/opt: @@ -1157,6 +1189,7 @@ win64-aarch64-nightly/opt: - win64-aarch64-rust - win64-cbindgen - win64-sccache + - win64-nasm - win64-node win32-mingwclang/opt: diff --git a/taskcluster/ci/fetch/toolchains.yml b/taskcluster/ci/fetch/toolchains.yml index c67fa0de1c63..c484dc7cc993 100644 --- a/taskcluster/ci/fetch/toolchains.yml +++ b/taskcluster/ci/fetch/toolchains.yml @@ -173,6 +173,14 @@ mpfr-3.1.5: sig-url: "{url}.asc" key-path: build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key +nasm-2.14.02: + description: nasm 2.14.02 source code + fetch: + type: static-url + url: https://ftp.halifax.rwth-aachen.de/gentoo/distfiles/nasm-2.14.02.tar.xz + sha256: e24ade3e928f7253aa8c14aa44726d1edf3f98643f87c9d72ec1df44b26be8f5 + size: 827620 + wix-3.1.1: description: wix 3.1.1 binary release # WIX doesn't use a wrapping toplevel DIR, so we should really repackage it when diff --git a/taskcluster/ci/toolchain/clang.yml b/taskcluster/ci/toolchain/clang.yml index af6ef32554a8..a68385e362de 100644 --- a/taskcluster/ci/toolchain/clang.yml +++ b/taskcluster/ci/toolchain/clang.yml @@ -60,7 +60,7 @@ linux64-clang-trunk-mingw-x64: description: "MinGW-Clang Trunk x64 toolchain build" treeherder: symbol: TMW(clang-x64) - tier: 2 + tier: 1 run: script: build-clang-trunk-mingw.sh arguments: [ diff --git a/taskcluster/ci/toolchain/kind.yml b/taskcluster/ci/toolchain/kind.yml index 2e7ce5b92da5..57af10e234c1 100644 --- a/taskcluster/ci/toolchain/kind.yml +++ b/taskcluster/ci/toolchain/kind.yml @@ -35,6 +35,7 @@ jobs-from: - mingw.yml - minidump_stackwalk.yml - misc.yml + - nasm.yml - node.yml - rust.yml - rust-size.yml diff --git a/taskcluster/ci/toolchain/nasm.yml b/taskcluster/ci/toolchain/nasm.yml new file mode 100644 index 000000000000..5313ac6a5196 --- /dev/null +++ b/taskcluster/ci/toolchain/nasm.yml @@ -0,0 +1,18 @@ +win64-nasm: + description: "nasm win64 build" + treeherder: + symbol: TW64(nasm) + worker-type: aws-provisioner-v1/gecko-{level}-b-linux + worker: + docker-image: {in-tree: mingw32-build} + max-run-time: 1800 + run: + script: build-nasm.sh + resources: + - 'taskcluster/scripts/misc/tooltool-download.sh' + toolchain-artifact: public/build/nasm.tar.bz2 + toolchains: + - linux64-clang-trunk-mingw-x64 + fetches: + fetch: + - nasm-2.14.02 diff --git a/taskcluster/scripts/misc/build-nasm.sh b/taskcluster/scripts/misc/build-nasm.sh new file mode 100755 index 000000000000..c7673ea20cbb --- /dev/null +++ b/taskcluster/scripts/misc/build-nasm.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -x -e -v + +case "$(uname -s)" in + Linux) + WORKSPACE=$HOME/workspace + UPLOAD_DIR=$HOME/artifacts + COMPRESS_EXT=bz2 + ;; +esac + +cd $WORKSPACE/build/src + +. taskcluster/scripts/misc/tooltool-download.sh +export PATH="$WORKSPACE/build/src/clang/bin:$PATH" + +cd $WORKSPACE/build/nasm-2.14.02 +./configure CC=x86_64-w64-mingw32-clang AR=llvm-ar RANLIB=llvm-ranlib --host=x86_64-w64-mingw32 +make -j$(nproc) + +mkdir nasm +mv nasm.exe nasm/ +tar -acf nasm.tar.$COMPRESS_EXT nasm +mkdir -p "$UPLOAD_DIR" +cp nasm.tar.$COMPRESS_EXT "$UPLOAD_DIR" From 4ecf2184634710e704ce69b6758c001b944dc23b Mon Sep 17 00:00:00 2001 From: Tom Prince Date: Thu, 14 Feb 2019 21:34:49 +0000 Subject: [PATCH 80/84] Bug 1525736: [taskgraph] Allow looking up parameters by project for trust-domains other than `gecko`; r=dustin Previously, this code looked parameters under `gecko.v2`, but that doesn't work for projects using the out-of-tree taskgraph code, or Thunderbird. This moves the parameter loading slightly later to vary the index used based on trust domain. Differential Revision: https://phabricator.services.mozilla.com/D19028 --HG-- extra : moz-landing-system : lando --- taskcluster/mach_commands.py | 15 +++++++++------ taskcluster/taskgraph/parameters.py | 23 +++++++++++++++++++++-- tools/tryselect/tasks.py | 15 +++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/taskcluster/mach_commands.py b/taskcluster/mach_commands.py index 0ca60a3429c3..ea8864aee288 100644 --- a/taskcluster/mach_commands.py +++ b/taskcluster/mach_commands.py @@ -299,7 +299,12 @@ class MachCommands(MachCommandBase): else: input = None - parameters = taskgraph.parameters.load_parameters_file(options['parameters']) + parameters = taskgraph.parameters.load_parameters_file( + options['parameters'], + strict=False, + # FIXME: There should be a way to parameterize this. + trust_domain="gecko", + ) parameters.check() root = options['root'] @@ -345,8 +350,7 @@ class MachCommands(MachCommandBase): try: self.setup_logging(quiet=options['quiet'], verbose=options['verbose']) - parameters = taskgraph.parameters.load_parameters_file(options['parameters']) - parameters.check() + parameters = taskgraph.parameters.parameters_loader(options['parameters']) tgg = taskgraph.generator.TaskGraphGenerator( root_dir=options.get('root'), @@ -404,14 +408,13 @@ class MachCommands(MachCommandBase): try: self.setup_logging(quiet=options['quiet'], verbose=options['verbose']) - parameters = taskgraph.parameters.load_parameters_file(options['parameters']) - parameters.check() + parameters = taskgraph.parameters.parameters_loader(options['parameters']) tgg = taskgraph.generator.TaskGraphGenerator( root_dir=options.get('root'), parameters=parameters) - actions = taskgraph.actions.render_actions_json(parameters, tgg.graph_config) + actions = taskgraph.actions.render_actions_json(tgg.parameters, tgg.graph_config) print(json.dumps(actions, sort_keys=True, indent=2, separators=(',', ': '))) except Exception: traceback.print_exc() diff --git a/taskcluster/taskgraph/parameters.py b/taskcluster/taskgraph/parameters.py index e1e8e18545c4..5323381d108d 100644 --- a/taskcluster/taskgraph/parameters.py +++ b/taskcluster/taskgraph/parameters.py @@ -185,7 +185,7 @@ class Parameters(ReadOnlyDict): return release_level(self['project']) -def load_parameters_file(filename, strict=True, overrides=None): +def load_parameters_file(filename, strict=True, overrides=None, trust_domain=None): """ Load parameters from a path, url, decision task-id or project. @@ -212,7 +212,13 @@ def load_parameters_file(filename, strict=True, overrides=None): if filename.startswith("task-id="): task_id = filename.split("=")[1] elif filename.startswith("project="): - index = "gecko.v2.{project}.latest.taskgraph.decision".format( + if trust_domain is None: + raise ValueError( + "Can't specify parameters by project " + "if trust domain isn't supplied.", + ) + index = "{trust_domain}.v2.{project}.latest.taskgraph.decision".format( + trust_domain=trust_domain, project=filename.split("=")[1], ) task_id = find_task_id(index) @@ -231,3 +237,16 @@ def load_parameters_file(filename, strict=True, overrides=None): kwargs.update(overrides) return Parameters(strict=strict, **kwargs) + + +def parameters_loader(filename, strict=True, overrides=None): + def get_parameters(graph_config): + parameters = load_parameters_file( + filename, + strict=strict, + overrides=overrides, + trust_domain=graph_config["trust-domain"], + ) + parameters.check() + return parameters + return get_parameters diff --git a/tools/tryselect/tasks.py b/tools/tryselect/tasks.py index 93423e739b4d..055be92d6439 100644 --- a/tools/tryselect/tasks.py +++ b/tools/tryselect/tasks.py @@ -22,7 +22,7 @@ import taskgraph from taskgraph.generator import TaskGraphGenerator from taskgraph.parameters import ( ParameterMismatch, - load_parameters_file, + parameters_loader, ) from taskgraph.taskgraph import TaskGraph @@ -81,19 +81,18 @@ def generate_tasks(params, full, root): os.makedirs(cache_dir) print("Task configuration changed, generating {}".format(attr.replace('_', ' '))) - try: - params = load_parameters_file(params, strict=False, overrides={'try_mode': 'try_select'}) - params.check() - except ParameterMismatch as e: - print(PARAMETER_MISMATCH.format(e.args[0])) - sys.exit(1) taskgraph.fast = True cwd = os.getcwd() os.chdir(build.topsrcdir) root = os.path.join(root, 'taskcluster', 'ci') - tg = getattr(TaskGraphGenerator(root_dir=root, parameters=params), attr) + params = parameters_loader(params, strict=False, overrides={'try_mode': 'try_select'}) + try: + tg = getattr(TaskGraphGenerator(root_dir=root, parameters=params), attr) + except ParameterMismatch as e: + print(PARAMETER_MISMATCH.format(e.args[0])) + sys.exit(1) os.chdir(cwd) From 71158b6626520beeb53d1aad156e57e335f3cd5e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 14 Feb 2019 22:00:55 +0000 Subject: [PATCH 81/84] Bug 1512504 - Remove automated msvc builds. r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D19614 --HG-- extra : moz-landing-system : lando --- browser/config/mozconfigs/win32/debug-msvc | 9 -- browser/config/mozconfigs/win32/opt-msvc | 9 -- browser/config/mozconfigs/win64/debug-msvc | 6 - browser/config/mozconfigs/win64/opt-msvc | 6 - taskcluster/ci/build/windows.yml | 130 --------------------- 5 files changed, 160 deletions(-) delete mode 100644 browser/config/mozconfigs/win32/debug-msvc delete mode 100644 browser/config/mozconfigs/win32/opt-msvc delete mode 100644 browser/config/mozconfigs/win64/debug-msvc delete mode 100644 browser/config/mozconfigs/win64/opt-msvc diff --git a/browser/config/mozconfigs/win32/debug-msvc b/browser/config/mozconfigs/win32/debug-msvc deleted file mode 100644 index 23f975a9c0c5..000000000000 --- a/browser/config/mozconfigs/win32/debug-msvc +++ /dev/null @@ -1,9 +0,0 @@ -. "$topsrcdir/browser/config/mozconfigs/win32/debug" - -export CC="cl.exe" -export CXX="cl.exe" -export LINKER="link.exe" - -export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe -export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe -unset ENABLE_CLANG_PLUGIN diff --git a/browser/config/mozconfigs/win32/opt-msvc b/browser/config/mozconfigs/win32/opt-msvc deleted file mode 100644 index 21ef445ffb06..000000000000 --- a/browser/config/mozconfigs/win32/opt-msvc +++ /dev/null @@ -1,9 +0,0 @@ -. "$topsrcdir/browser/config/mozconfigs/win32/nightly" - -export CC="cl.exe" -export CXX="cl.exe" -export LINKER="link.exe" - -export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe -export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe -unset ENABLE_CLANG_PLUGIN diff --git a/browser/config/mozconfigs/win64/debug-msvc b/browser/config/mozconfigs/win64/debug-msvc deleted file mode 100644 index 32a01d11fa0a..000000000000 --- a/browser/config/mozconfigs/win64/debug-msvc +++ /dev/null @@ -1,6 +0,0 @@ -. "$topsrcdir/browser/config/mozconfigs/win64/debug" - -export CC="cl.exe" -export CXX="cl.exe" -export LINKER="link.exe" -unset ENABLE_CLANG_PLUGIN diff --git a/browser/config/mozconfigs/win64/opt-msvc b/browser/config/mozconfigs/win64/opt-msvc deleted file mode 100644 index 32edf8e089bc..000000000000 --- a/browser/config/mozconfigs/win64/opt-msvc +++ /dev/null @@ -1,6 +0,0 @@ -. "$topsrcdir/browser/config/mozconfigs/win64/nightly" - -export CC="cl.exe" -export CXX="cl.exe" -export LINKER="link.exe" -unset ENABLE_CLANG_PLUGIN diff --git a/taskcluster/ci/build/windows.yml b/taskcluster/ci/build/windows.yml index 9063ccd89bfb..567769f71e4f 100755 --- a/taskcluster/ci/build/windows.yml +++ b/taskcluster/ci/build/windows.yml @@ -950,136 +950,6 @@ win64-devedition-nightly/opt: - win64-nasm - win64-node -win32-msvc/debug: - description: "Win32 MSVC Debug" - index: - product: firefox - job-name: win32-msvc-debug - treeherder: - platform: windows2012-32/debug - symbol: Bmsvc - tier: 1 - worker-type: aws-provisioner-v1/gecko-{level}-b-win2012 - worker: - max-run-time: 7200 - env: - TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest" - PERFHERDER_EXTRA_OPTIONS: msvc - run: - options: [append-env-variables-from-configs] - script: mozharness/scripts/fx_desktop_build.py - config: - - builds/releng_base_firefox.py - - builds/taskcluster_base_windows.py - - builds/taskcluster_base_win32.py - - builds/taskcluster_sub_win32/debug.py - mozconfig-variant: debug-msvc - toolchains: - - win64-clang-cl - - win64-rust - - win64-cbindgen - - win64-sccache - - win64-nasm - - win64-node - -win32-msvc/opt: - description: "Win32 MSVC Opt" - index: - product: firefox - job-name: win32-msvc-opt - treeherder: - platform: windows2012-32/opt - symbol: Bmsvc - tier: 1 - worker-type: aws-provisioner-v1/gecko-{level}-b-win2012 - worker: - max-run-time: 7200 - env: - TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest" - PERFHERDER_EXTRA_OPTIONS: msvc - run: - options: [append-env-variables-from-configs] - script: mozharness/scripts/fx_desktop_build.py - config: - - builds/releng_base_firefox.py - - builds/taskcluster_base_windows.py - - builds/taskcluster_base_win32.py - extra-config: - stage_platform: win32 - mozconfig-variant: opt-msvc - toolchains: - - win64-clang-cl - - win64-rust - - win64-cbindgen - - win64-sccache - - win64-nasm - - win64-node - -win64-msvc/debug: - description: "Win64 MSVC Debug" - index: - product: firefox - job-name: win64-msvc-debug - treeherder: - platform: windows2012-64/debug - symbol: Bmsvc - tier: 1 - worker-type: aws-provisioner-v1/gecko-{level}-b-win2012 - worker: - max-run-time: 7200 - env: - TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win64/releng.manifest" - PERFHERDER_EXTRA_OPTIONS: msvc - run: - options: [append-env-variables-from-configs] - script: mozharness/scripts/fx_desktop_build.py - config: - - builds/releng_base_firefox.py - - builds/taskcluster_base_windows.py - - builds/taskcluster_base_win64.py - - builds/taskcluster_sub_win64/debug.py - mozconfig-variant: debug-msvc - toolchains: - - win64-clang-cl - - win64-rust - - win64-cbindgen - - win64-sccache - - win64-nasm - - win64-node - -win64-msvc/opt: - description: "Win64 MSVC Opt" - index: - product: firefox - job-name: win64-msvc-opt - treeherder: - platform: windows2012-64/opt - symbol: Bmsvc - tier: 1 - worker-type: aws-provisioner-v1/gecko-{level}-b-win2012 - worker: - max-run-time: 7200 - env: - TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win64/releng.manifest" - PERFHERDER_EXTRA_OPTIONS: msvc - run: - options: [append-env-variables-from-configs] - script: mozharness/scripts/fx_desktop_build.py - config: - - builds/releng_base_firefox.py - - builds/taskcluster_base_windows.py - - builds/taskcluster_base_win64.py - extra-config: - stage_platform: win64 - mozconfig-variant: opt-msvc - toolchains: - - win64-clang-cl - - win64-rust - - win64-cbindgen - - win64-sccache - - win64-nasm - - win64-node - win64-aarch64/debug: description: "AArch64 Win64 Debug" index: From ef3ad686ee6e04a0c627139129743e1a09df8a11 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 14 Feb 2019 21:45:27 +0000 Subject: [PATCH 82/84] Bug 1512504 - Remove support for MSVC. r=froydnj Consequently, this removes: - MOZ_LIBPRIO, which is now always enabled. - non_msvc_compiler, which is now always true. - The cl.py wrapper, since it's not used anymore. - CL_INCLUDES_PREFIX, which was only used for the cl.py wrapper. - NONASCII, which was only there to ensure CL_INCLUDES_PREFIX still worked in non-ASCII cases. This however keeps a large part of detecting and configuring for MSVC, because we still do need it for at least headers, libraries, and midl. Depends on D19614 Differential Revision: https://phabricator.services.mozilla.com/D19615 --HG-- extra : moz-landing-system : lando --- Makefile.in | 7 - browser/app/moz.build | 2 +- browser/app/profile/firefox.js | 4 +- browser/moz.build | 3 - build/autoconf/expandlibs.m4 | 2 +- build/moz.configure/bindgen.configure | 2 +- build/moz.configure/headers.configure | 7 +- build/moz.configure/rust.configure | 2 +- build/moz.configure/toolchain.configure | 100 ++---------- build/moz.configure/windows.configure | 65 +------- build/templates.mozbuild | 2 +- config/config.mk | 14 -- config/external/icu/defs.mozbuild | 11 -- config/external/moz.build | 7 +- config/external/msgpack/moz.build | 4 +- config/moz.build | 2 +- config/rules.mk | 13 +- dom/bindings/moz.build | 6 +- dom/chrome-webidl/moz.build | 7 +- dom/media/moz.build | 3 +- dom/media/mp4/moz.build | 2 +- .../platforms/agnostic/bytestreams/moz.build | 2 +- dom/media/platforms/ffmpeg/ffvpx/moz.build | 2 +- dom/media/platforms/omx/moz.build | 9 +- dom/media/systemservices/moz.build | 2 +- dom/media/webrtc/moz.build | 11 +- dom/moz.build | 4 +- dom/plugins/ipc/moz.build | 2 +- .../test/testplugin/testplugin.mozbuild | 2 +- gfx/cairo/cairo/src/moz.build | 71 +++----- gfx/cairo/libpixman/src/moz.build | 25 +-- gfx/qcms/moz.build | 2 +- gfx/skia/generate_mozbuild.py | 34 ++-- gfx/skia/moz.build | 34 ++-- gfx/vr/service/moz.build | 2 +- gfx/ycbcr/moz.build | 4 +- ipc/app/moz.build | 2 +- ipc/chromium/chromium-config.mozbuild | 2 +- ipc/glue/moz.build | 2 +- ipc/ipdl/test/cxx/app/moz.build | 2 +- js/src/js-cxxflags.mozbuild | 2 +- js/src/moz.build | 3 +- js/src/shell/moz.build | 6 - js/xpconnect/shell/moz.build | 2 +- js/xpconnect/wrappers/moz.build | 2 +- layout/base/moz.build | 2 +- layout/painting/moz.build | 2 +- layout/style/moz.build | 5 - media/ffvpx/ffvpxcommon.mozbuild | 85 ++++------ media/gmp-clearkey/0.1/moz.build | 17 +- media/libaom/moz.build | 43 ++--- media/libcubeb/src/moz.build | 2 +- media/libdav1d/moz.build | 5 - media/libopus/moz.build | 19 ++- media/libspeex_resampler/src/moz.build | 6 - media/libtheora/moz.build | 25 ++- media/libvpx/moz.build | 42 ++--- media/libwebp/src/dsp/moz.build | 2 +- media/webrtc/moz.build | 12 +- media/webrtc/signaling/gtest/moz.build | 2 +- media/webrtc/trunk/gtest/moz.build | 2 +- media/webrtc/webrtc.mozbuild | 2 +- memory/build/moz.build | 2 +- memory/mozalloc/moz.build | 2 +- mfbt/tests/moz.build | 2 +- modules/brotli/moz.build | 2 +- modules/fdlibm/src/moz.build | 2 +- modules/libpref/init/all.js | 2 - moz.configure | 2 +- mozglue/build/moz.build | 2 - .../mozbuild/mozbuild/action/check_binary.py | 2 +- python/mozbuild/mozbuild/action/cl.py | 127 --------------- python/mozbuild/mozbuild/frontend/context.py | 6 - .../mozbuild/mozbuild/frontend/gyp_reader.py | 4 +- .../configure/test_toolchain_configure.py | 152 ++---------------- python/mozbuild/mozbuild/test/test_util.py | 11 +- security/certverifier/moz.build | 89 +--------- security/ct/moz.build | 82 +--------- security/sandbox/moz.build | 2 +- .../components/jsoncpp/src/lib_json/moz.build | 11 +- .../components/maintenanceservice/moz.build | 2 +- toolkit/components/protobuf/moz.build | 2 +- toolkit/crashreporter/crashreporter.mozbuild | 4 +- .../src/tools/windows/dump_syms/moz.build | 2 +- toolkit/crashreporter/test/moz.build | 4 +- toolkit/library/moz.build | 4 +- toolkit/moz.configure | 44 ++--- .../update/updater/updater-common.build | 2 +- widget/windows/moz.build | 2 +- xpcom/ds/moz.build | 6 - xpcom/glue/standalone/moz.build | 2 +- xpcom/io/moz.build | 5 +- 92 files changed, 293 insertions(+), 1055 deletions(-) delete mode 100644 python/mozbuild/mozbuild/action/cl.py diff --git a/Makefile.in b/Makefile.in index 502ca0543f94..01164d67ac58 100644 --- a/Makefile.in +++ b/Makefile.in @@ -272,22 +272,15 @@ update-packaging: package-generated-sources: $(call py_action,package_generated_sources,'$(DIST)/$(PKG_PATH)$(GENERATED_SOURCE_FILE_PACKAGE)') -#XXX: this is a hack, since we don't want to clobber for MSVC # PGO support, but we can't do this test in client.mk # No point in clobbering if PGO has been explicitly disabled. ifdef NO_PROFILE_GUIDED_OPTIMIZE maybe_clobber_profiledbuild: else -ifneq ($(CC_TYPE),msvc) maybe_clobber_profiledbuild: clean ifneq (,$(findstring clang,$(CC_TYPE))) $(LLVM_PROFDATA) merge -o $(DEPTH)/merged.profdata $(DEPTH)/*.profraw endif -else -maybe_clobber_profiledbuild: - $(RM) $(DIST)/bin/*.pgc - find $(DIST)/$(MOZ_APP_NAME) -name '*.pgc' -exec mv {} $(DIST)/bin \; -endif # msvc endif # NO_PROFILE_GUIDED_OPTIMIZE .PHONY: maybe_clobber_profiledbuild diff --git a/browser/app/moz.build b/browser/app/moz.build index 922746ddf321..0b1a8023bb06 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -62,7 +62,7 @@ if CONFIG['LIBFUZZER']: if CONFIG['ENABLE_GECKODRIVER']: DEFINES['MOZ_GECKODRIVER'] = True -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # Always enter a Windows program through wmain, whether or not we're # a console application. WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 3f09bb66e776..666e968c22fe 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1791,16 +1791,14 @@ pref("browser.fission.simulate", false); // On platforms that do not build libprio, do not set these prefs at all, which gives us a way to detect support. // Curve25519 public keys for Prio servers -#ifdef MOZ_LIBPRIO pref("prio.publicKeyA", "35AC1C7576C7C6EDD7FED6BCFC337B34D48CB4EE45C86BEEFB40BD8875707733"); pref("prio.publicKeyB", "26E6674E65425B823F1F1D5F96E3BB3EF9E406EC7FBA7DEF8B08A35DD135AF50"); -#endif // Coverage ping is disabled by default. pref("toolkit.coverage.enabled", false); pref("toolkit.coverage.endpoint.base", "https://coverage.mozilla.org"); // Whether or not Prio-encoded Telemetry will be sent along with the main ping. -#if defined(NIGHTLY_BUILD) && defined(MOZ_LIBPRIO) +#if defined(NIGHTLY_BUILD) pref("prio.enabled", true); #endif diff --git a/browser/moz.build b/browser/moz.build index 217697e48754..15e11f45ff4a 100644 --- a/browser/moz.build +++ b/browser/moz.build @@ -45,9 +45,6 @@ for cdm in CONFIG['MOZ_EME_MODULES']: if CONFIG['MOZ_GPSD']: DEFINES['MOZ_GPSD'] = True -if CONFIG['MOZ_LIBPRIO']: - DEFINES['MOZ_LIBPRIO'] = True - # These files are specified in this moz.build to pick up DIST_SUBDIR as set in # this directory, which is un-set in browser/app. JS_PREFERENCE_PP_FILES += [ diff --git a/build/autoconf/expandlibs.m4 b/build/autoconf/expandlibs.m4 index d864655d46c1..959ee6f1b97c 100644 --- a/build/autoconf/expandlibs.m4 +++ b/build/autoconf/expandlibs.m4 @@ -20,7 +20,7 @@ AC_CACHE_CHECK(what kind of list files are supported by the linker, dnl https://sourceware.org/bugzilla/show_bug.cgi?id=23600 if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $MOZ_LTO_CFLAGS $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&5) && test -s conftest.${OBJ_SUFFIX}; then echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list - if test "$CC_TYPE" = "msvc" -o "$CC_TYPE" = "clang-cl"; then + if test "$CC_TYPE" = "clang-cl"; then link="$LINKER -OUT:conftest${ac_exeext}" else link="${CC-cc} -o conftest${ac_exeext}" diff --git a/build/moz.configure/bindgen.configure b/build/moz.configure/bindgen.configure index 978c58054a53..5f2e4b117a7e 100644 --- a/build/moz.configure/bindgen.configure +++ b/build/moz.configure/bindgen.configure @@ -273,7 +273,7 @@ def basic_bindgen_cflags(target, is_unix, compiler_info, android_cflags, clang_p ], }.get(target.os, []) - if compiler_info.type in ('msvc', 'clang-cl'): + if compiler_info.type == 'clang-cl': args += [ # To enable the builtin __builtin_offsetof so that CRT wouldn't # use reinterpret_cast in offsetof() which is not allowed inside diff --git a/build/moz.configure/headers.configure b/build/moz.configure/headers.configure index b10499418eaf..78daecc396b0 100644 --- a/build/moz.configure/headers.configure +++ b/build/moz.configure/headers.configure @@ -27,7 +27,6 @@ check_headers( 'unistd.h', 'nl_types.h', 'cpuid.h', - when=non_msvc_compiler, ) # These are all the places some variant of statfs can be hiding. @@ -36,7 +35,6 @@ check_headers( 'sys/statfs.h', 'sys/vfs.h', 'sys/mount.h', - when=non_msvc_compiler, ) # Quota support @@ -45,7 +43,6 @@ check_headers( set_define('HAVE_SYS_QUOTA_H', try_compile(includes=['sys/quota.h'], body='quotactl(0, nullptr, 0, (caddr_t)nullptr);', - when=non_msvc_compiler, check_msg='for sys/quota.h')) check_header('linux/quota.h', includes=['sys/socket.h'], @@ -59,14 +56,12 @@ check_headers( when=building_linux, ) -check_header('sys/queue.h', - when=non_msvc_compiler) +check_header('sys/queue.h') check_headers( 'sys/types.h', 'netinet/in.h', 'byteswap.h', - when=non_msvc_compiler, ) # TODO: Move these checks to file specific to --enable-project=js. diff --git a/build/moz.configure/rust.configure b/build/moz.configure/rust.configure index 4913f349f387..c0f7a56e094c 100644 --- a/build/moz.configure/rust.configure +++ b/build/moz.configure/rust.configure @@ -321,7 +321,7 @@ set_config('WIN64_CARGO_LINKER_CONFIG', win64_cargo_linker_config) @depends(target, c_compiler, rustc) @imports('os') def rustc_natvis_ldflags(target, compiler_info, rustc): - if target.kernel == 'WINNT' and compiler_info.type in ('msvc', 'clang-cl'): + if target.kernel == 'WINNT' and compiler_info.type == 'clang-cl': sysroot = check_cmd_output(rustc, '--print', 'sysroot').strip() etc = os.path.join(sysroot, 'lib/rustlib/etc') ldflags = [] diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index 154621cd8e6e..b039073e9400 100755 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -448,14 +448,11 @@ def get_compiler_info(compiler, language): form of a list or tuple), in the given `language`. The returned information includes: - - the compiler type (msvc, clang-cl, clang or gcc) + - the compiler type (clang-cl, clang or gcc) - the compiler version - the compiler supported language - the compiler supported language version ''' - # Note: MSVC doesn't expose __STDC_VERSION__. It does expose __STDC__, - # but only when given the -Za option, which disables compiler - # extensions. # Note: We'd normally do a version check for clang, but versions of clang # in Xcode have a completely different versioning scheme despite exposing # the version with the same defines. @@ -469,9 +466,6 @@ def get_compiler_info(compiler, language): #if defined(__clang__) %COMPILER "clang-cl" %VERSION __clang_major__.__clang_minor__.__clang_patchlevel__ - #else - %COMPILER "msvc" - %VERSION _MSC_FULL_VER #endif #elif defined(__clang__) %COMPILER "clang" @@ -487,8 +481,6 @@ def get_compiler_info(compiler, language): %cplusplus __cplusplus #elif __STDC_VERSION__ %STDC_VERSION __STDC_VERSION__ - #elif __STDC__ - %STDC_VERSION 198900L #endif ''') @@ -514,9 +506,9 @@ def get_compiler_info(compiler, language): # Also check for endianness. The advantage of living in modern times is # that all the modern compilers we support now have __BYTE_ORDER__ defined - # by the preprocessor, except MSVC, which only supports little endian. + # by the preprocessor. check += dedent('''\ - #if _MSC_VER || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ %ENDIANNESS "little" #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ %ENDIANNESS "big" @@ -549,14 +541,6 @@ def get_compiler_info(compiler, language): stdc_version = int(data.get('STDC_VERSION', '0L').rstrip('L')) version = data.get('VERSION') - if version and type == 'msvc': - msc_ver = version - version = msc_ver[0:2] - if len(msc_ver) > 2: - version += '.' + msc_ver[2:4] - if len(msc_ver) > 4: - version += '.' + msc_ver[4:] - if version: version = Version(version) @@ -604,7 +588,6 @@ def check_compiler(compiler, language, target): flags.append('-Xclang') flags.append('-std=gnu99') - # Note: MSVC, while supporting C++14, still reports 199711L for __cplusplus. # Note: this is a strict version check because we used to always add # -std=gnu++14. cxx14_version = 201402 @@ -634,7 +617,7 @@ def check_compiler(compiler, language, target): flags.append('--target=%s' % target.toolchain) has_target = True - if not has_target and (not info.cpu or info.cpu != target.cpu and info.type != 'msvc'): + if not has_target and (not info.cpu or info.cpu != target.cpu): same_arch = same_arch_different_bits() if (target.cpu, info.cpu) in same_arch: flags.append('-m32') @@ -853,7 +836,7 @@ def default_c_compilers(host_or_target, other_c_compiler=None): def default_c_compilers(host_or_target, target, toolchain_prefix, android_clang_compiler, *other_c_compiler): if host_or_target.kernel == 'WINNT': - supported = types = ('clang-cl', 'msvc', 'gcc', 'clang') + supported = types = ('clang-cl', 'gcc', 'clang') elif host_or_target.kernel == 'Darwin': types = ('clang',) supported = ('clang', 'gcc') @@ -878,10 +861,6 @@ def default_c_compilers(host_or_target, other_c_compiler=None): # Android NDK clangs do not function as host compiler, so # prioritize a raw 'clang' instead. prioritized = info.type - elif info.type == 'msvc' and target.cpu != host_or_target.cpu: - # MSVC compilers only support one architecture, so we'll - # want a cl in another (detected) path. - prioritized = 'cl' types = [prioritized] + [t for t in types if t != info.type] @@ -898,8 +877,6 @@ def default_c_compilers(host_or_target, other_c_compiler=None): result.append(android_clang_compiler) elif type == 'gcc': result.extend(gcc) - elif type == 'msvc': - result.append('cl') else: result.append(type) @@ -1119,16 +1096,6 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None, raise FatalCheckError( 'Only clang/llvm 3.9 or newer is supported.') - if info.type == 'msvc': - if info.version < '19.15.26726': - raise FatalCheckError( - 'This version (%s) of the MSVC compiler is not ' - 'supported.\n' - 'You must install Visual C++ 2017 Update 8 or ' - 'later in order to build.\n' - 'See https://developer.mozilla.org/en/' - 'Windows_Build_Prerequisites' % info.version) - if info.flags: raise FatalCheckError( 'Unknown compiler or compiler not supported.') @@ -1234,19 +1201,12 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None, if value: return value[0] - @depends(valid_compiler, linker) - def unused_linker(compiler, linker): - if linker and compiler.type != 'msvc': + @depends(linker) + def unused_linker(linker): + if linker: log.warning('The value of %s is not used by this build system.' % linker_var) - if host_or_target is target: - @depends(valid_compiler) - def is_msvc(compiler): - return compiler.type == 'msvc' - - imply_option('LINKER', linker, reason='LD', when=is_msvc) - return valid_compiler @@ -1258,7 +1218,6 @@ host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler, other_c_compiler=c_compiler) # Generic compiler-based conditions. -non_msvc_compiler = depends(c_compiler)(lambda info: info.type != 'msvc') building_with_gcc = depends(c_compiler)(lambda info: info.type == 'gcc') @@ -1266,7 +1225,7 @@ building_with_gcc = depends(c_compiler)(lambda info: info.type == 'gcc') def msvs_version(info): # clang-cl emulates the same version scheme as cl. And MSVS_VERSION needs to # be set for GYP on Windows. - if info.type in ('clang-cl', 'msvc'): + if info.type == 'clang-cl': return '2017' return '' @@ -1289,7 +1248,7 @@ def check_have_64_bit(have_64_bit, compiler_have_64_bit): @depends(c_compiler, target) def default_debug_flags(compiler_info, target): # Debug info is ON by default. - if compiler_info.type in ('msvc', 'clang-cl'): + if compiler_info.type == 'clang-cl': return '-Z7' elif target.kernel == 'WINNT' and compiler_info.type == 'clang': return '-g -gcodeview' @@ -1427,11 +1386,11 @@ set_config('WRAP_SYSTEM_INCLUDES', wrap_system_includes) set_config('VISIBILITY_FLAGS', visibility_flags) -@depends(c_compiler, using_sccache) -def depend_cflags(info, using_sccache): - if info.type not in ('clang-cl', 'msvc'): +@depends(c_compiler) +def depend_cflags(info): + if info.type != 'clang-cl': return ['-MD', '-MP', '-MF $(MDDEPDIR)/$(@F).pp'] - elif info.type == 'clang-cl': + else: # clang-cl doesn't accept the normal -MD -MP -MF options that clang # does, but the underlying cc1 binary understands how to generate # dependency files. These options are based on analyzing what the @@ -1444,10 +1403,6 @@ def depend_cflags(info, using_sccache): '-Xclang', '-MT', '-Xclang', '$@' ] - elif using_sccache: - # sccache supports a special flag to create depfiles - # by parsing MSVC's -showIncludes output. - return ['-deps$(MDDEPDIR)/$(@F).pp'] set_config('_DEPEND_CFLAGS', depend_cflags) @@ -1492,29 +1447,6 @@ def pgo_flags(compiler, build_env, target): use_ldflags=[], ) - if compiler.type == 'msvc': - num_cores = min(8, multiprocessing.cpu_count()) - cgthreads = '-CGTHREADS:%s' % num_cores - - return namespace( - gen_cflags=['-GL'], - gen_ldflags=['-LTCG:PGINSTRUMENT', '-PogoSafeMode', cgthreads], - # XXX: PGO builds can fail with warnings treated as errors, - # specifically "no profile data available" appears to be - # treated as an error sometimes. This might be a consequence - # of using WARNINGS_AS_ERRORS in some modules, combined - # with the linker doing most of the work in the whole-program - # optimization/PGO case. I think it's probably a compiler bug, - # but we work around it here. - use_cflags=['-GL', '-wd4624', '-wd4952'], - # XXX: should be -LTCG:PGOPTIMIZE, but that fails on libxul. - # Probably also a compiler bug, but what can you do? - # /d2:-cgsummary prints a summary of what is happening during - # code generation. How long individual functions are optimized, - # which functions are optimized, etc. - use_ldflags=['-LTCG:PGUPDATE', cgthreads, '-d2:-cgsummary'], - ) - set_config('PROFILE_GEN_CFLAGS', pgo_flags.gen_cflags) set_config('PROFILE_GEN_LDFLAGS', pgo_flags.gen_ldflags) @@ -2069,7 +2001,7 @@ js_option(env='AS', nargs=1, help='Path to the assembler') @depends(target, c_compiler) def as_info(target, c_compiler): - if c_compiler.type in ('msvc', 'clang-cl'): + if c_compiler.type == 'clang-cl': ml = { 'x86': 'ml', 'x86_64': 'ml64', @@ -2079,7 +2011,7 @@ def as_info(target, c_compiler): type='masm', names=(ml, ) ) - # When building with anything but MSVC, we just use the C compiler as the assembler. + # When building with anything but clang-cl, we just use the C compiler as the assembler. return namespace( type='gcc', names=(c_compiler.compiler, ) diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure index 2f268ca0b871..fbe97785dee7 100644 --- a/build/moz.configure/windows.configure +++ b/build/moz.configure/windows.configure @@ -251,16 +251,13 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env, c_compiler): @depends(c_compiler, toolchain_search_path) @imports('os') def vc_path(c_compiler, toolchain_search_path): - if c_compiler.type not in ('msvc', 'clang-cl'): + if c_compiler.type != 'clang-cl': return - vc_program = c_compiler.compiler - - # In clang-cl builds, we use the headers and libraries from an MSVC installation. - if c_compiler.type == 'clang-cl': - vc_program = find_program('cl.exe', paths=toolchain_search_path) - if not vc_program: - die('Cannot find a Visual C++ install for e.g. ATL headers.') + # In clang-cl builds, we need the headers and libraries from an MSVC installation. + vc_program = find_program('cl.exe', paths=toolchain_search_path) + if not vc_program: + die('Cannot find a Visual C++ install for e.g. ATL headers.') result = os.path.dirname(vc_program) while True: @@ -487,65 +484,17 @@ def valid_mt(path): set_config('MSMANIFEST_TOOL', depends(valid_mt)(lambda x: bool(x))) - -@template -def linker_progs_for(host_or_target): - compiler = { - host: host_c_compiler, - target: c_compiler, - }[host_or_target] - - @depends(compiler) - def linker_progs(compiler): - if compiler.type == 'msvc': - return ('link', 'lld-link') - if compiler.type == 'clang-cl': - return ('lld-link', 'link') - return linker_progs - - js_option(env='LINKER', nargs=1, help='Path to the linker') -link = check_prog('LINKER', linker_progs_for(target), input='LINKER', +link = check_prog('LINKER', ('lld-link',), input='LINKER', paths=toolchain_search_path) js_option(env='HOST_LINKER', nargs=1, help='Path to the host linker') -host_link = check_prog('HOST_LINKER', linker_progs_for(host), - input='HOST_LINKER', +host_link = check_prog('HOST_LINKER', ('lld-link',), input='HOST_LINKER', paths=host_toolchain_search_path) add_old_configure_assignment('LINKER', link) check_prog('MAKECAB', ('makecab.exe',)) - - -@depends(c_compiler, using_sccache) -def need_showincludes_prefix(info, using_sccache): - # sccache does its own -showIncludes prefix checking. - # clang-cl uses a gcc-style dependency scheme, see toolchain.configure. - if info.type == 'msvc' and not using_sccache: - return True - - -@depends(c_compiler, when=need_showincludes_prefix) -@imports(_from='re', _import='compile', _as='re_compile') -def msvc_showincludes_prefix(c_compiler): - pattern = re_compile(br'^([^:]*:.*[ :] )(.*\\stdio.h)$') - output = try_invoke_compiler([c_compiler.compiler], 'C', '#include \n', - ['-nologo', '-c', '-Fonul', '-showIncludes']) - for line in output.splitlines(): - if line.endswith(b'\\stdio.h'): - m = pattern.match(line) - if m: - return m.group(1) - # We should have found the prefix and returned earlier - die('Cannot find cl -showIncludes prefix.') - - -set_config('CL_INCLUDES_PREFIX', msvc_showincludes_prefix) - -# Make sure that the build system can handle non-ASCII characters in -# environment variables to prevent silent breakage on non-English systems. -set_config('NONASCII', b'\241\241') diff --git a/build/templates.mozbuild b/build/templates.mozbuild index facff42335f2..f130e2b761fd 100644 --- a/build/templates.mozbuild +++ b/build/templates.mozbuild @@ -159,7 +159,7 @@ def NoVisibilityFlags(): @template def ForceInclude(*headers): """Force includes a set of header files in C++ compilations""" - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': include_flag = '-FI' else: include_flag = '-include' diff --git a/config/config.mk b/config/config.mk index c17d4f65e493..dff8806b695f 100644 --- a/config/config.mk +++ b/config/config.mk @@ -106,14 +106,6 @@ VERSION_NUMBER = 50 CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config AUTOCONF_TOOLS = $(MOZILLA_DIR)/build/autoconf -ifeq (msvc,$(CC_TYPE)) -# clang-cl is smart enough to generate dependencies directly. -ifeq (,$(MOZ_USING_SCCACHE)) -CC_WRAPPER ?= $(call py_action,cl) -CXX_WRAPPER ?= $(call py_action,cl) -endif # MOZ_USING_SCCACHE -endif # CC_TYPE - CC := $(CC_WRAPPER) $(CC) CXX := $(CXX_WRAPPER) $(CXX) MKDIR ?= mkdir @@ -441,9 +433,3 @@ endif endif PLY_INCLUDE = -I$(MOZILLA_DIR)/other-licenses/ply - -export CL_INCLUDES_PREFIX -# Make sure that the build system can handle non-ASCII characters -# in environment variables to prevent it from breking silently on -# non-English systems. -export NONASCII diff --git a/config/external/icu/defs.mozbuild b/config/external/icu/defs.mozbuild index 66e6c4267586..cfb8b784a93e 100644 --- a/config/external/icu/defs.mozbuild +++ b/config/external/icu/defs.mozbuild @@ -49,14 +49,3 @@ if CONFIG['CC_TYPE'] == 'clang-cl': '-Wno-macro-redefined', '-Wno-microsoft-include', ] - -if CONFIG['CC_TYPE'] == 'msvc': - CFLAGS += [ - '-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition - '-wd4996', # The compiler encountered a deprecated declaration. - ] - CXXFLAGS += [ - '-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition - '-wd4333', # '>>' : right shift by too large amount, data loss - '-wd4996', # The compiler encountered a deprecated declaration. - ] diff --git a/config/external/moz.build b/config/external/moz.build index 138002a7a33c..1885abfbf59e 100644 --- a/config/external/moz.build +++ b/config/external/moz.build @@ -13,10 +13,9 @@ DIRS += [ if not CONFIG['MOZ_SYSTEM_JPEG']: external_dirs += ['media/libjpeg'] -if CONFIG['MOZ_LIBPRIO']: - DIRS += [ - 'prio', - ] +DIRS += [ + 'prio', +] # There's no "native" brotli or woff2 yet, but probably in the future... external_dirs += ['modules/brotli'] diff --git a/config/external/msgpack/moz.build b/config/external/msgpack/moz.build index 3dc3955bf237..e2906048037e 100644 --- a/config/external/msgpack/moz.build +++ b/config/external/msgpack/moz.build @@ -4,6 +4,4 @@ # 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/. -if CONFIG['MOZ_LIBPRIO']: - DIRS += ['/third_party/msgpack'] - +DIRS += ['/third_party/msgpack'] diff --git a/config/moz.build b/config/moz.build index 8fd459d2fc01..44aac05c4f37 100644 --- a/config/moz.build +++ b/config/moz.build @@ -43,7 +43,7 @@ if CONFIG['WRAP_STL_INCLUDES']: stl_compiler = None if CONFIG['CC_TYPE'] in ('clang', 'gcc'): stl_compiler = 'gcc' - elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + elif CONFIG['CC_TYPE'] == 'clang-cl': stl_compiler = 'msvc' if stl_compiler: diff --git a/config/rules.mk b/config/rules.mk index 946638f482ae..e96f75427915 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -359,7 +359,7 @@ else # Windows-to-Windows cross compiles should always use MSVC-style options for # host compiles. ifeq (WINNT_WINNT,$(HOST_OS_ARCH)_$(OS_ARCH)) -ifneq (,$(filter-out msvc clang-cl,$(HOST_CC_TYPE))) +ifneq (,$(filter-out clang-cl,$(HOST_CC_TYPE))) $(error MSVC-style compilers should be used for host compilations!) endif HOST_OUTOPTION = -Fo# eol @@ -517,13 +517,6 @@ define EXPAND_CC_OR_CXX $(if $(PROG_IS_C_ONLY_$(1)),$(CC),$(CCC)) endef -# Workaround a bug of MSVC 2017 Update 8 (see bug 1485224) -ifeq ($(CC_TYPE)_$(HOST_OS_ARCH)_$(MOZ_PROFILE_GENERATE),msvc_WINNT_1) -LINKER_OUT=$(subst /,\,$1) -else -LINKER_OUT=$1 -endif - # # PROGRAM = Foo # creates OBJS, links with LIBS to create Foo @@ -532,7 +525,7 @@ $(PROGRAM): $(PROGOBJS) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(EXTRA_DEPS) $(RESFIL $(REPORT_BUILD) @$(RM) $@.manifest ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) - $(LINKER) -NOLOGO -OUT:$(call LINKER_OUT,$@) -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(SHARED_LIBS) $(OS_LIBS) + $(LINKER) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(SHARED_LIBS) $(OS_LIBS) ifdef MSMANIFEST_TOOL @if test -f $@.manifest; then \ if test -f '$(srcdir)/$(notdir $@).manifest'; then \ @@ -659,7 +652,7 @@ endif $(HOST_SHARED_LIBRARY): Makefile $(REPORT_BUILD) $(RM) $@ -ifneq (,$(filter msvc clang-cl,$(HOST_CC_TYPE))) +ifneq (,$(filter clang-cl,$(HOST_CC_TYPE))) $(HOST_LINKER) -NOLOGO -DLL -OUT:$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LINKER_LIBPATHS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) else $(HOST_CXX) $(HOST_OUTOPTION)$@ $($(notdir $@)_OBJS) $(HOST_CXX_LDFLAGS) $(HOST_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS) diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build index 4bb6d8b853fb..7e4b18e0c637 100644 --- a/dom/bindings/moz.build +++ b/dom/bindings/moz.build @@ -7,9 +7,6 @@ with Files("**"): BUG_COMPONENT = ("Core", "DOM") -if CONFIG['CC_TYPE'] == 'msvc': - CXXFLAGS += ['-bigobj'] - TEST_DIRS += ['test'] XPIDL_SOURCES += [ @@ -98,8 +95,7 @@ LOCAL_INCLUDES += [ '/media/webrtc/trunk/', ] -if CONFIG['MOZ_LIBPRIO']: - LOCAL_INCLUDES += ['/third_party/msgpack/include'] +LOCAL_INCLUDES += ['/third_party/msgpack/include'] DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build index 8d4c4b236ac6..4eb1f60e2161 100644 --- a/dom/chrome-webidl/moz.build +++ b/dom/chrome-webidl/moz.build @@ -69,8 +69,7 @@ if CONFIG['MOZ_PLACES']: 'PlacesObservers.webidl', ] -if CONFIG['MOZ_LIBPRIO']: - WEBIDL_FILES += [ - 'PrioEncoder.webidl', - ] +WEBIDL_FILES += [ + 'PrioEncoder.webidl', +] diff --git a/dom/media/moz.build b/dom/media/moz.build index 1cbaa8fbc9f7..19ca04827649 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -304,8 +304,7 @@ SOURCES += [ # Some codec-related code uses multi-character constants, which GCC and clang # warn about. Suppress turning this warning into an error. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - SOURCES['DecoderTraits.cpp'].flags += ['-Wno-error=multichar'] +SOURCES['DecoderTraits.cpp'].flags += ['-Wno-error=multichar'] EXTRA_COMPONENTS += [ 'PeerConnection.js', diff --git a/dom/media/mp4/moz.build b/dom/media/mp4/moz.build index 15783ea9365a..f286f81299ce 100644 --- a/dom/media/mp4/moz.build +++ b/dom/media/mp4/moz.build @@ -41,7 +41,7 @@ SOURCES += [ FINAL_LIBRARY = 'xul' # Supress warnnings for now. -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CFLAGS += [ '-wd4013', # 'function' undefined; assuming extern returning int '-wd4101', # unreferenced local variable diff --git a/dom/media/platforms/agnostic/bytestreams/moz.build b/dom/media/platforms/agnostic/bytestreams/moz.build index 8236c4186227..1205eacf956c 100644 --- a/dom/media/platforms/agnostic/bytestreams/moz.build +++ b/dom/media/platforms/agnostic/bytestreams/moz.build @@ -26,7 +26,7 @@ LOCAL_INCLUDES += [ FINAL_LIBRARY = 'xul' # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CFLAGS += [ '-wd4013', # 'function' undefined; assuming extern returning int '-wd4101', # unreferenced local variable diff --git a/dom/media/platforms/ffmpeg/ffvpx/moz.build b/dom/media/platforms/ffmpeg/ffvpx/moz.build index 2b703f108c83..394d36d88a3b 100644 --- a/dom/media/platforms/ffmpeg/ffvpx/moz.build +++ b/dom/media/platforms/ffmpeg/ffvpx/moz.build @@ -34,7 +34,7 @@ if CONFIG['CC_TYPE'] == 'clang': CXXFLAGS += [ '-Wno-unknown-attributes', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4996', # deprecated declaration ] diff --git a/dom/media/platforms/omx/moz.build b/dom/media/platforms/omx/moz.build index d1912aec0616..809a4c16c666 100644 --- a/dom/media/platforms/omx/moz.build +++ b/dom/media/platforms/omx/moz.build @@ -31,9 +31,6 @@ FINAL_LIBRARY = 'xul' if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += ['-Wno-error=shadow'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): - # Avoid warnings from third-party code that we can not modify. - if CONFIG['CC_TYPE'] == 'clang-cl': - CXXFLAGS += ['-Wno-invalid-source-encoding'] - else: - CXXFLAGS += ['-validate-charset-'] +# Avoid warnings from third-party code that we can not modify. +if CONFIG['CC_TYPE'] == 'clang-cl': + CXXFLAGS += ['-Wno-invalid-source-encoding'] diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build index dcd9ac2e0db2..9c77b46d3fe7 100644 --- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -48,7 +48,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': UNIFIED_SOURCES += ['OSXRunLoopSingleton.cpp'] EXPORTS += ['OSXRunLoopSingleton.h'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' # This is intended as a temporary workaround to enable building with VS2015. diff --git a/dom/media/webrtc/moz.build b/dom/media/webrtc/moz.build index c8b469fa2208..07d458a42b40 100644 --- a/dom/media/webrtc/moz.build +++ b/dom/media/webrtc/moz.build @@ -77,16 +77,15 @@ include('/ipc/chromium/chromium-config.mozbuild') # - about attributes on forward declarations for types that are already # defined, which complains about important MOZ_EXPORT attributes for # android API types -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wno-error=attributes', - '-Wno-error=shadow', - ] +CXXFLAGS += [ + '-Wno-error=attributes', + '-Wno-error=shadow', +] DEFINES['TRACING'] = True FINAL_LIBRARY = 'xul' -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4275', # non dll-interface class used as base for dll-interface class '-wd4312', # This is intended as a temporary hack to support building with VS2015 diff --git a/dom/moz.build b/dom/moz.build index 7c2240efcfe2..ffcc1f791592 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -104,11 +104,9 @@ DIRS += [ 'simpledb', 'reporting', 'localstorage', + 'prio', ] -if CONFIG['MOZ_LIBPRIO']: - DIRS += ['prio'] - if CONFIG['OS_ARCH'] == 'WINNT': DIRS += ['plugins/ipc/hangui'] diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build index 14ffb1da521c..9c4b60d6705d 100644 --- a/dom/plugins/ipc/moz.build +++ b/dom/plugins/ipc/moz.build @@ -148,7 +148,7 @@ CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += ['-Wno-error=shadow'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # conversion from 'X' to 'Y' requires a narrowing conversion CXXFLAGS += ['-wd4838'] diff --git a/dom/plugins/test/testplugin/testplugin.mozbuild b/dom/plugins/test/testplugin/testplugin.mozbuild index 2951b8644544..18ee35af2bc9 100644 --- a/dom/plugins/test/testplugin/testplugin.mozbuild +++ b/dom/plugins/test/testplugin/testplugin.mozbuild @@ -55,7 +55,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3': OS_LIBS += CONFIG['XLIBS'] OS_LIBS += CONFIG['XEXT_LIBS'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # conversion from 'X' to 'Y' requires a narrowing conversion CXXFLAGS += ['-wd4838'] diff --git a/gfx/cairo/cairo/src/moz.build b/gfx/cairo/cairo/src/moz.build index 1ff74eac2623..b33dc8ab9d9f 100755 --- a/gfx/cairo/cairo/src/moz.build +++ b/gfx/cairo/cairo/src/moz.build @@ -210,55 +210,34 @@ if CONFIG['MOZ_TREE_FREETYPE']: DEFINES['FT_LCD_FILTER_H'] = '%s/modules/freetype2/include/freetype/ftlcdfil.h' % TOPSRCDIR # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): +CFLAGS += [ + '-Wno-enum-compare', + '-Wno-int-to-pointer-cast', + '-Wno-int-conversion', + '-Wno-incompatible-pointer-types', + '-Wno-sign-compare', + '-Wno-type-limits', + '-Wno-missing-field-initializers', + '-Wno-conversion', + '-Wno-narrowing', + '-Wno-switch', + '-Wno-unused', + '-Wno-unused-variable', + '-Wno-error=uninitialized', +] +if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += [ - '-Wno-enum-compare', - '-Wno-int-to-pointer-cast', - '-Wno-int-conversion', + '-Wno-absolute-value', + '-Wno-deprecated-register', '-Wno-incompatible-pointer-types', - '-Wno-sign-compare', - '-Wno-type-limits', - '-Wno-missing-field-initializers', - '-Wno-conversion', - '-Wno-narrowing', - '-Wno-switch', - '-Wno-unused', - '-Wno-unused-variable', - '-Wno-error=uninitialized', - ] - if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): - CFLAGS += [ - '-Wno-absolute-value', - '-Wno-deprecated-register', - '-Wno-incompatible-pointer-types', - '-Wno-macro-redefined', - '-Wno-shift-negative-value', - '-Wno-tautological-compare', - '-Wno-tautological-constant-out-of-range-compare', - '-Wno-unreachable-code', - ] - else: - CFLAGS += ['-Wno-unused-but-set-variable'] - -if CONFIG['CC_TYPE'] == 'msvc': - CFLAGS += [ - '-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition - '-wd4018', # '>' : signed/unsigned mismatch - '-wd4047', # different levels of indirection - '-wd4101', # unreferenced local variable - '-wd4133', # 'function' : incompatible types - '-wd4146', # unary minus operator applied to unsigned type - '-wd4311', # 'variable' : pointer truncation from 'type' to 'type' - '-wd4477', # format string '%s' requires an argument of type 'type' - '-wd4996', # The compiler encountered a deprecated declaration. - ] - CXXFLAGS += [ - '-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition - '-wd4018', # '>' : signed/unsigned mismatch - '-wd4146', # unary minus operator applied to unsigned type - '-wd4828', # illegal in the current source character set - '-wd4838', # requires a narrowing conversion + '-Wno-macro-redefined', + '-Wno-shift-negative-value', + '-Wno-tautological-compare', + '-Wno-tautological-constant-out-of-range-compare', + '-Wno-unreachable-code', ] +else: + CFLAGS += ['-Wno-unused-but-set-variable'] # See bug 386897. if CONFIG['CC_TYPE'] in ('clang', 'gcc') and CONFIG['OS_TARGET'] == 'Android' and CONFIG['MOZ_OPTIMIZE']: diff --git a/gfx/cairo/libpixman/src/moz.build b/gfx/cairo/libpixman/src/moz.build index 42732717be77..e2cfe6aa26ab 100644 --- a/gfx/cairo/libpixman/src/moz.build +++ b/gfx/cairo/libpixman/src/moz.build @@ -85,7 +85,7 @@ use_arm_neon_gcc = False if CONFIG['INTEL_ARCHITECTURE']: use_sse2 = True if CONFIG['CPU_ARCH'] == 'x86': - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': use_mmx = True if CONFIG['CC_TYPE'] in ('clang', 'gcc'): use_mmx = True @@ -150,14 +150,13 @@ if CONFIG['OS_TARGET'] == 'Android' and (use_arm_neon_gcc or use_arm_simd_gcc): ] # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CFLAGS += [ - '-Wno-address', - '-Wno-missing-field-initializers', - '-Wno-sign-compare', - '-Wno-incompatible-pointer-types', - '-Wno-unused', # too many unused warnings; ignore - ] +CFLAGS += [ + '-Wno-address', + '-Wno-missing-field-initializers', + '-Wno-sign-compare', + '-Wno-incompatible-pointer-types', + '-Wno-unused', # too many unused warnings; ignore +] if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += [ '-Wno-incompatible-pointer-types', @@ -168,14 +167,6 @@ if CONFIG['CC_TYPE'] == 'clang-cl': CFLAGS += [ '-Wno-unused-variable', ] -if CONFIG['CC_TYPE'] == 'msvc': - CFLAGS += [ - '-wd4047', # different levels of indirection - '-wd4101', # unreferenced local variable - '-wd4133', # 'function' : incompatible types - '-wd4146', # unary minus operator applied to unsigned type - '-wd4311', # 'variable' : pointer truncation from 'type' to 'type' - ] # See bug 386897. if CONFIG['OS_TARGET'] == 'Android' and CONFIG['MOZ_OPTIMIZE']: diff --git a/gfx/qcms/moz.build b/gfx/qcms/moz.build index eb57def8f93e..fdd2ea443b2a 100644 --- a/gfx/qcms/moz.build +++ b/gfx/qcms/moz.build @@ -27,7 +27,7 @@ use_sse2 = False use_altivec = False if CONFIG['INTEL_ARCHITECTURE']: use_sse2 = True - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': if CONFIG['OS_ARCH'] != 'WINNT' or CONFIG['CPU_ARCH'] != 'x86_64': use_sse1 = True else: diff --git a/gfx/skia/generate_mozbuild.py b/gfx/skia/generate_mozbuild.py index b230f491e9e1..7e7142d5069e 100755 --- a/gfx/skia/generate_mozbuild.py +++ b/gfx/skia/generate_mozbuild.py @@ -24,7 +24,7 @@ header = """ skia_opt_flags = [] if CONFIG['MOZ_OPTIMIZE']: - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': skia_opt_flags += ['-O2'] elif CONFIG['CC_TYPE'] in ('clang', 'gcc'): skia_opt_flags += ['-O3'] @@ -79,7 +79,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': # We should autogenerate these SSE related flags. -if CONFIG['INTEL_ARCHITECTURE'] and (CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc')): +if CONFIG['INTEL_ARCHITECTURE']: SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3'] SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] @@ -88,17 +88,6 @@ if CONFIG['INTEL_ARCHITECTURE'] and (CONFIG['CC_TYPE'] in ('clang', 'clang-cl', SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-msse4.2'] SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx'] SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-mavx2', '-mf16c', '-mfma'] -elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl') and CONFIG['INTEL_ARCHITECTURE']: - # MSVC doesn't need special compiler flags, but Skia needs to be told that these files should - # be built with the required SSE level or it will simply compile in stubs and cause runtime crashes - SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20'] - SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31'] - SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20'] - SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31'] - SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=41'] - SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=42'] - SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=51'] - SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=52'] elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += CONFIG['NEON_FLAGS'] elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang', 'gcc'): @@ -116,15 +105,14 @@ if CONFIG['MOZ_TREE_FREETYPE']: DEFINES['SK_CAN_USE_DLOPEN'] = 0 # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wno-deprecated-declarations', - '-Wno-overloaded-virtual', - '-Wno-shadow', - '-Wno-sign-compare', - '-Wno-unreachable-code', - '-Wno-unused-function', - ] +CXXFLAGS += [ + '-Wno-deprecated-declarations', + '-Wno-overloaded-virtual', + '-Wno-shadow', + '-Wno-sign-compare', + '-Wno-unreachable-code', + '-Wno-unused-function', +] if CONFIG['CC_TYPE'] == 'gcc': CXXFLAGS += [ '-Wno-logical-op', @@ -456,7 +444,7 @@ def write_mozbuild(sources): write_sources(f, sources['arm'], 4) write_cflags(f, sources['arm'], opt_whitelist, 'skia_opt_flags', 4) - f.write("elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang-cl', 'clang', 'gcc'):\n") + f.write("elif CONFIG['CPU_ARCH'] == 'aarch64':\n") write_sources(f, sources['arm64'], 4) write_cflags(f, sources['arm64'], opt_whitelist, 'skia_opt_flags', 4) diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build index a5bdda0f5d82..623c3fedec63 100755 --- a/gfx/skia/moz.build +++ b/gfx/skia/moz.build @@ -17,7 +17,7 @@ skia_opt_flags = [] if CONFIG['MOZ_OPTIMIZE']: - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': skia_opt_flags += ['-O2'] elif CONFIG['CC_TYPE'] in ('clang', 'gcc'): skia_opt_flags += ['-O3'] @@ -686,7 +686,7 @@ elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'): SOURCES['skia/src/opts/SkBlitMask_opts_arm_neon.cpp'].flags += skia_opt_flags SOURCES['skia/src/opts/SkBlitRow_opts_arm.cpp'].flags += skia_opt_flags SOURCES['skia/src/opts/SkBlitRow_opts_arm_neon.cpp'].flags += skia_opt_flags -elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang-cl', 'clang', 'gcc'): +elif CONFIG['CPU_ARCH'] == 'aarch64': SOURCES += [ 'skia/src/opts/SkBitmapProcState_arm_neon.cpp', 'skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp', @@ -759,7 +759,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': # We should autogenerate these SSE related flags. -if CONFIG['INTEL_ARCHITECTURE'] and (CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc')): +if CONFIG['INTEL_ARCHITECTURE']: SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3'] SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] @@ -768,17 +768,6 @@ if CONFIG['INTEL_ARCHITECTURE'] and (CONFIG['CC_TYPE'] in ('clang', 'clang-cl', SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-msse4.2'] SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx'] SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-mavx2', '-mf16c', '-mfma'] -elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl') and CONFIG['INTEL_ARCHITECTURE']: - # MSVC doesn't need special compiler flags, but Skia needs to be told that these files should - # be built with the required SSE level or it will simply compile in stubs and cause runtime crashes - SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20'] - SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31'] - SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20'] - SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31'] - SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=41'] - SOURCES['skia/src/opts/SkOpts_sse42.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=42'] - SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=51'] - SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=52'] elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += CONFIG['NEON_FLAGS'] elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] in ('clang', 'gcc'): @@ -796,15 +785,14 @@ if CONFIG['MOZ_TREE_FREETYPE']: DEFINES['SK_CAN_USE_DLOPEN'] = 0 # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wno-deprecated-declarations', - '-Wno-overloaded-virtual', - '-Wno-shadow', - '-Wno-sign-compare', - '-Wno-unreachable-code', - '-Wno-unused-function', - ] +CXXFLAGS += [ + '-Wno-deprecated-declarations', + '-Wno-overloaded-virtual', + '-Wno-shadow', + '-Wno-sign-compare', + '-Wno-unreachable-code', + '-Wno-unused-function', +] if CONFIG['CC_TYPE'] == 'gcc': CXXFLAGS += [ '-Wno-logical-op', diff --git a/gfx/vr/service/moz.build b/gfx/vr/service/moz.build index f58d8aaa1c39..7ee4e3aa6a91 100644 --- a/gfx/vr/service/moz.build +++ b/gfx/vr/service/moz.build @@ -40,7 +40,7 @@ if CONFIG['OS_TARGET'] in ('WINNT', 'Linux', 'Darwin'): FINAL_LIBRARY = 'xul' # This is intended as a temporary hack to enable VS2015 builds. -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # ovr_capi_dynamic.h '': Alignment specifier is less than # actual alignment (8), and will be ignored CXXFLAGS += ['-wd4359'] diff --git a/gfx/ycbcr/moz.build b/gfx/ycbcr/moz.build index c3c133794725..c643fbaf406b 100644 --- a/gfx/ycbcr/moz.build +++ b/gfx/ycbcr/moz.build @@ -24,7 +24,7 @@ if CONFIG['INTEL_ARCHITECTURE']: SOURCES['yuv_convert_sse2.cpp'].flags += CONFIG['SSE2_FLAGS'] # MSVC doesn't support MMX when targeting AMD64. - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': if CONFIG['CPU_ARCH'] == 'x86': SOURCES += [ 'yuv_convert_mmx.cpp', @@ -33,7 +33,7 @@ if CONFIG['INTEL_ARCHITECTURE']: SOURCES += ['yuv_convert_mmx.cpp'] SOURCES['yuv_convert_mmx.cpp'].flags += CONFIG['MMX_FLAGS'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': if CONFIG['CPU_ARCH'] == 'x86_64' or \ (CONFIG['CPU_ARCH'] == 'x86' and CONFIG['CC_TYPE'] == 'clang-cl'): SOURCES += [ diff --git a/ipc/app/moz.build b/ipc/app/moz.build index d3b18616bb2c..665ec600b1de 100644 --- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -59,7 +59,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin': 'mozsandbox', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # Always enter a Windows program through wmain, whether or not we're # a console application. WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/ipc/chromium/chromium-config.mozbuild b/ipc/chromium/chromium-config.mozbuild index b3bb34106769..1dd914f29480 100644 --- a/ipc/chromium/chromium-config.mozbuild +++ b/ipc/chromium/chromium-config.mozbuild @@ -31,7 +31,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'WIN32_LEAN_AND_MEAN': True, }) - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': DEFINES['COMPILER_MSVC'] = True else: diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index cf602a14f1e4..08110bd05ab1 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -189,7 +189,7 @@ else: 'GeckoChildProcessHost.cpp', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size SOURCES['BackgroundChildImpl.cpp'].flags += ['-wd4312'] diff --git a/ipc/ipdl/test/cxx/app/moz.build b/ipc/ipdl/test/cxx/app/moz.build index 7d0fd9791686..35aaabf583a0 100644 --- a/ipc/ipdl/test/cxx/app/moz.build +++ b/ipc/ipdl/test/cxx/app/moz.build @@ -16,5 +16,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/js/src/js-cxxflags.mozbuild b/js/src/js-cxxflags.mozbuild index 6e0fd0285f7d..96b294a972ba 100644 --- a/js/src/js-cxxflags.mozbuild +++ b/js/src/js-cxxflags.mozbuild @@ -7,7 +7,7 @@ # ICU pkg-config flags CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # C4805 warns mixing bool with other integral types in computation. # But given the conversion from bool is specified, and this is a # pattern widely used in code in js/src, suppress this warning here. diff --git a/js/src/moz.build b/js/src/moz.build index 1ab4a0380fa4..2690de939433 100755 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -393,8 +393,7 @@ if CONFIG['MOZ_VTUNE']: 'vtune/jitprofiling.c', 'vtune/VTuneWrapper.cpp', ] - if CONFIG['CC_TYPE'] != 'msvc': - SOURCES['vtune/ittnotify_static.c'].flags += ['-Wno-varargs', '-Wno-unknown-pragmas'] + SOURCES['vtune/ittnotify_static.c'].flags += ['-Wno-varargs', '-Wno-unknown-pragmas'] if CONFIG['HAVE_LINUX_PERF_EVENT_H']: SOURCES += [ diff --git a/js/src/shell/moz.build b/js/src/shell/moz.build index ca29c6035bda..65e3c4e7458d 100644 --- a/js/src/shell/moz.build +++ b/js/src/shell/moz.build @@ -26,12 +26,6 @@ UNIFIED_SOURCES += [ DEFINES['EXPORT_JS_API'] = True -if CONFIG['CC_TYPE'] == 'msvc': - # PGO is unnecessary for the js shell, but clang/gcc cannot turn off PGO - # because we need to resolve symbols from PGO runtime library when our - # object files have been compiled for PGO. - NO_PGO = True - LOCAL_INCLUDES += [ '!..', '..', diff --git a/js/xpconnect/shell/moz.build b/js/xpconnect/shell/moz.build index c9f1137bdab5..a0708708679e 100644 --- a/js/xpconnect/shell/moz.build +++ b/js/xpconnect/shell/moz.build @@ -21,7 +21,7 @@ LOCAL_INCLUDES += [ '/toolkit/xre', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # Always enter a Windows program through wmain, whether or not we're # a console application. WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/js/xpconnect/wrappers/moz.build b/js/xpconnect/wrappers/moz.build index 67e7affebf5b..6f67efc555a4 100644 --- a/js/xpconnect/wrappers/moz.build +++ b/js/xpconnect/wrappers/moz.build @@ -22,7 +22,7 @@ SOURCES += [ ] # warning C4661 for FilteringWrapper -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4661', # no suitable definition provided for explicit template instantiation request ] diff --git a/layout/base/moz.build b/layout/base/moz.build index ae37debd6ff2..73ac55440b57 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -165,7 +165,7 @@ MARIONETTE_LAYOUT_MANIFESTS += ['tests/marionette/manifest.ini'] MOCHITEST_MANIFESTS += ['tests/mochitest.ini'] MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # 'type cast': conversion from 'unsigned int' to 'void *' of greater size CXXFLAGS += ['-wd4312'] diff --git a/layout/painting/moz.build b/layout/painting/moz.build index f86e8c961a86..a804d258c444 100644 --- a/layout/painting/moz.build +++ b/layout/painting/moz.build @@ -68,7 +68,7 @@ FINAL_LIBRARY = 'xul' CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # 'type cast': conversion from 'unsigned int' to 'void *' of greater size CXXFLAGS += ['-wd4312'] diff --git a/layout/style/moz.build b/layout/style/moz.build index 6e7b4981ae4a..4d309271a71d 100644 --- a/layout/style/moz.build +++ b/layout/style/moz.build @@ -227,11 +227,6 @@ SOURCES += [ # windows.h. 'nsLayoutStylesheetCache.cpp', ] -if CONFIG['CC_TYPE'] == 'msvc': - # Needed for gCSSAnonBoxAtoms. - SOURCES['nsCSSAnonBoxes.cpp'].flags += ['-Zc:externConstexpr'] - # Needed for gCSSPseudoElementAtoms. - SOURCES['nsCSSPseudoElements.cpp'].flags += ['-Zc:externConstexpr'] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/media/ffvpx/ffvpxcommon.mozbuild b/media/ffvpx/ffvpxcommon.mozbuild index 9836fa486ae3..2e3d58567376 100644 --- a/media/ffvpx/ffvpxcommon.mozbuild +++ b/media/ffvpx/ffvpxcommon.mozbuild @@ -29,71 +29,42 @@ LOCAL_INCLUDES += ['/media/ffvpx'] AllowCompilerWarnings() # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): +CFLAGS += [ + '-Wno-parentheses', + '-Wno-pointer-sign', + '-Wno-sign-compare', + '-Wno-switch', + '-Wno-type-limits', + '-Wno-unused-function', + # XXX This does not seem to have any effect on some versions of GCC. + '-Wno-deprecated-declarations', +] +if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += [ - '-Wno-parentheses', - '-Wno-pointer-sign', - '-Wno-sign-compare', - '-Wno-switch', - '-Wno-type-limits', - '-Wno-unused-function', - # XXX This does not seem to have any effect on some versions of GCC. - '-Wno-deprecated-declarations', + '-Wno-absolute-value', + '-Wno-incompatible-pointer-types', + '-Wno-string-conversion', + '-Wno-visibility', ] - if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': CFLAGS += [ - '-Wno-absolute-value', - '-Wno-incompatible-pointer-types', - '-Wno-string-conversion', - '-Wno-visibility', + '-Wno-inconsistent-dllimport', + '-Wno-macro-redefined', # 'WIN32_LEAN_AND_MEAN' macro redefined ] - if CONFIG['CC_TYPE'] == 'clang-cl': - CFLAGS += [ - '-Wno-inconsistent-dllimport', - '-Wno-macro-redefined', # 'WIN32_LEAN_AND_MEAN' macro redefined - ] - if CONFIG['CC_TYPE'] == 'clang': - CFLAGS += [ - # Workaround for https://bugs.llvm.org/show_bug.cgi?id=26828#c4 : - '-ffreestanding', - ] - else: + if CONFIG['CC_TYPE'] == 'clang': CFLAGS += [ - '-Wno-discarded-qualifiers', - '-Wno-maybe-uninitialized', + # Workaround for https://bugs.llvm.org/show_bug.cgi?id=26828#c4 : + '-ffreestanding', ] - if CONFIG['CC_TYPE'] in ('clang', 'gcc'): - # Force visibility of cpu and av_log symbols. - CFLAGS += ['-include', 'libavutil_visibility.h'] -elif CONFIG['CC_TYPE'] == 'msvc': +else: CFLAGS += [ - '-wd4090', # 'return' : different 'const' qualifiers - '-wd4018', # '>' : signed/unsigned mismatch - '-wd4305', # 'initializing' : truncation from '__int64' to 'double' - '-wd4554', # '>>' : check operator precedence for possible error - '-wd4307', # '+' : integral constant overflow' - '-wd4028', # formal parameter 1 different from declaration - '-wd4056', # overflow in floating-point constant arithmetic - '-wd4756', # overflow in constant arithmetic - '-wd4005', #'WIN32_LEAN_AND_MEAN' : macro redefinition - '-wd4054', # 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' - '-wd4189', # local variable is initialized but not referenced - '-wd4133', # 'function' : incompatible types - from 'AVSampleFormat *' to 'int *' - '-wd4221', # nonstandard extension used - '-wd4206', # nonstandard extension used - '-wd4702', # unreachable code - '-wd4101', # unreferenced local variable - '-wd4245', # conversion from 'int' to 'uint32_t', signed/unsigned mismatch - '-wd4703', # potentially uninitialized local pointer - '-wd4293', # '<<' : shift count negative or too big, undefined behavior - '-wd4334', # '<<' : result of 32-bit shift implicitly converted to 64 bits - '-wd4996', # The compiler encountered a deprecated declaration. - # from FFmpeg configure - '-wd4244', '-wd4127', '-wd4018', '-wd4389', '-wd4146', '-wd4701', - '-wd4057', '-wd4204', '-wd4706', '-wd4305', '-wd4152', '-wd4324', - '-we4013', '-wd4100', '-wd4214', '-wd4307', '-wd4273', '-wd4554', + '-Wno-discarded-qualifiers', + '-Wno-maybe-uninitialized', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] in ('clang', 'gcc'): + # Force visibility of cpu and av_log symbols. + CFLAGS += ['-include', 'libavutil_visibility.h'] +if CONFIG['CC_TYPE'] == 'clang-cl': LOCAL_INCLUDES += ['/media/ffvpx/compat/atomics/win32'] DEFINES['HAVE_AV_CONFIG_H'] = True diff --git a/media/gmp-clearkey/0.1/moz.build b/media/gmp-clearkey/0.1/moz.build index 9b18b4dd1c6f..e6d0573ad7f6 100644 --- a/media/gmp-clearkey/0.1/moz.build +++ b/media/gmp-clearkey/0.1/moz.build @@ -58,23 +58,18 @@ DEFINES['MOZ_NO_MOZALLOC'] = True USE_LIBS += ['psshparser'] # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CFLAGS += [ - '-Wno-missing-braces', - '-Wno-pointer-to-int-cast', - '-Wno-sign-compare', - ] -elif CONFIG['CC_TYPE'] == 'msvc': - CFLAGS += [ - '-wd4090', # '=' : different 'const' qualifiers - ] +CFLAGS += [ + '-Wno-missing-braces', + '-Wno-pointer-to-int-cast', + '-Wno-sign-compare', +] if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CFLAGS += [ '-include', 'stdio.h', # for sprintf() prototype '-include', 'unistd.h', # for getpid() prototype ] -elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +elif CONFIG['CC_TYPE'] == 'clang-cl': CFLAGS += [ '-FI', 'stdio.h', # for sprintf() prototype ] diff --git a/media/libaom/moz.build b/media/libaom/moz.build index de4f8887a2a7..5f169b39418d 100644 --- a/media/libaom/moz.build +++ b/media/libaom/moz.build @@ -99,34 +99,25 @@ if CONFIG['OS_TARGET'] == 'Android': '%%%s/sources/android/cpufeatures/cpu-features.c' % CONFIG['ANDROID_NDK'], ] -if CONFIG['CC_TYPE'] != 'msvc': - for f in SOURCES: - if f.endswith('sse2.c'): - SOURCES[f].flags += CONFIG['SSE2_FLAGS'] - elif f.endswith('ssse3.c'): - SOURCES[f].flags += ['-mssse3'] - elif f.endswith('sse4.c'): - SOURCES[f].flags += ['-msse4.1'] - elif f.endswith('sse42.c'): - SOURCES[f].flags += ['-msse4.2'] - elif f.endswith('avx.c'): - SOURCES[f].flags += ['-mavx'] - elif f.endswith('avx2.c'): - SOURCES[f].flags += ['-mavx2'] - -if CONFIG['CC_TYPE'] == 'msvc' and CONFIG['INTEL_ARCHITECTURE']: - for f in SOURCES: - if f.endswith('avx.c'): - SOURCES[f].flags += ['-arch:AVX'] - if f.endswith('avx2.c'): - SOURCES[f].flags += ['-arch:AVX2'] +for f in SOURCES: + if f.endswith('sse2.c'): + SOURCES[f].flags += CONFIG['SSE2_FLAGS'] + elif f.endswith('ssse3.c'): + SOURCES[f].flags += ['-mssse3'] + elif f.endswith('sse4.c'): + SOURCES[f].flags += ['-msse4.1'] + elif f.endswith('sse42.c'): + SOURCES[f].flags += ['-msse4.2'] + elif f.endswith('avx.c'): + SOURCES[f].flags += ['-mavx'] + elif f.endswith('avx2.c'): + SOURCES[f].flags += ['-mavx2'] # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CFLAGS += [ - '-Wno-sign-compare', - '-Wno-unused-function', # so many of these warnings; just ignore them - ] +CFLAGS += [ + '-Wno-sign-compare', + '-Wno-unused-function', # so many of these warnings; just ignore them +] if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += [ '-Wno-unreachable-code', diff --git a/media/libcubeb/src/moz.build b/media/libcubeb/src/moz.build index 7cc6921c098e..f76805bda6b4 100644 --- a/media/libcubeb/src/moz.build +++ b/media/libcubeb/src/moz.build @@ -72,7 +72,7 @@ if CONFIG['OS_TARGET'] == 'WINNT': OS_LIBS += [ "avrt", ] - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += ['-wd4005'] # C4005: '_USE_MATH_DEFINES' : macro redefinition if CONFIG['OS_TARGET'] == 'Android': diff --git a/media/libdav1d/moz.build b/media/libdav1d/moz.build index 05c968c13a46..cf0078d85bc3 100644 --- a/media/libdav1d/moz.build +++ b/media/libdav1d/moz.build @@ -159,11 +159,6 @@ if CONFIG['OS_TARGET'] == 'WINNT': '../../third_party/dav1d/src/win32/thread.c' ] -if CONFIG['CC_TYPE'] == 'msvc': - LOCAL_INCLUDES += ['../../third_party/dav1d/include/compat/msvc/'] - EXPORTS.dav1d += ['../../third_party/dav1d/include/compat/msvc/stdatomic.h'] - CFLAGS += ['-wd4028'] - if CONFIG['CC_TYPE'] == 'gcc': LOCAL_INCLUDES += ['../../third_party/dav1d/include/compat/gcc/'] EXPORTS.dav1d += ['../../third_party/dav1d/include/compat/gcc/stdatomic.h'] diff --git a/media/libopus/moz.build b/media/libopus/moz.build index a26a38e6d3b8..cc82c8e6a616 100644 --- a/media/libopus/moz.build +++ b/media/libopus/moz.build @@ -99,16 +99,15 @@ if CONFIG['CPU_ARCH'] in ('x86', 'x86_64'): SOURCES += silk_sources_sse4_1 if not CONFIG['MOZ_SAMPLE_TYPE_FLOAT32']: SOURCES += silk_sources_fixed_sse4_1 - if CONFIG['CC_TYPE'] != 'msvc': - for f in SOURCES: - if f in celt_sources_sse: - SOURCES[f].flags += CONFIG['SSE_FLAGS'] - if f in celt_sources_sse2: - SOURCES[f].flags += CONFIG['SSE2_FLAGS'] - if f in celt_sources_sse4_1 or \ - f in silk_sources_sse4_1 or \ - f in silk_sources_fixed_sse4_1: - SOURCES[f].flags += ['-msse4.1'] + for f in SOURCES: + if f in celt_sources_sse: + SOURCES[f].flags += CONFIG['SSE_FLAGS'] + if f in celt_sources_sse2: + SOURCES[f].flags += CONFIG['SSE2_FLAGS'] + if f in celt_sources_sse4_1 or \ + f in silk_sources_sse4_1 or \ + f in silk_sources_fixed_sse4_1: + SOURCES[f].flags += ['-msse4.1'] if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_AS']: SOURCES += celt_sources_arm diff --git a/media/libspeex_resampler/src/moz.build b/media/libspeex_resampler/src/moz.build index 94f9bdb5058b..b99b8d92ce10 100644 --- a/media/libspeex_resampler/src/moz.build +++ b/media/libspeex_resampler/src/moz.build @@ -49,9 +49,3 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: # Suppress warnings in third-party code. if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CFLAGS += ['-Wno-sign-compare'] - -if CONFIG['CC_TYPE'] == 'msvc': - CFLAGS += [ - '-wd4018', # '<' : signed/unsigned mismatch - '-wd4101', # unreferenced local variable - ] diff --git a/media/libtheora/moz.build b/media/libtheora/moz.build index 29ac37f81257..11fc04653994 100644 --- a/media/libtheora/moz.build +++ b/media/libtheora/moz.build @@ -22,8 +22,7 @@ FINAL_LIBRARY = 'gkmedias' DEFINES['THEORA_DISABLE_ENCODE'] = True # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CFLAGS += ['-Wno-type-limits'] +CFLAGS += ['-Wno-type-limits'] if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += ['-Wno-tautological-compare'] if CONFIG['CC_TYPE'] == 'clang-cl': @@ -58,18 +57,16 @@ if CONFIG['INTEL_ARCHITECTURE']: DEFINES['OC_X86_ASM'] = True if CONFIG['CPU_ARCH'] == 'x86_64': DEFINES['OC_X86_64_ASM'] = True - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): - if CONFIG['CC_TYPE'] == 'clang-cl': - # clang-cl can't handle libtheora's inline asm. - pass - elif CONFIG['CPU_ARCH'] == 'x86': - SOURCES += [ - 'lib/x86_vc/mmxfrag.c', - 'lib/x86_vc/mmxidct.c', - 'lib/x86_vc/mmxstate.c', - 'lib/x86_vc/x86cpu.c', - 'lib/x86_vc/x86state.c', - ] + if CONFIG['CC_TYPE'] == 'clang-cl': + # clang-cl can't handle libtheora's inline asm. + pass + #SOURCES += [ + # 'lib/x86_vc/mmxfrag.c', + # 'lib/x86_vc/mmxidct.c', + # 'lib/x86_vc/mmxstate.c', + # 'lib/x86_vc/x86cpu.c', + # 'lib/x86_vc/x86state.c', + #] else: SOURCES += [ 'lib/x86/mmxfrag.c', diff --git a/media/libvpx/moz.build b/media/libvpx/moz.build index c9d0a3b8c31a..4c7e76e11edd 100644 --- a/media/libvpx/moz.build +++ b/media/libvpx/moz.build @@ -109,34 +109,24 @@ if CONFIG['OS_TARGET'] == 'Android': '%%%s/sources/android/cpufeatures/cpu-features.c' % CONFIG['ANDROID_NDK'], ] -if CONFIG['CC_TYPE'] != 'msvc': - for f in SOURCES: - if f.endswith('.c'): - if 'sse2.c' in f: - SOURCES[f].flags += CONFIG['SSE2_FLAGS'] - if 'ssse3.c' in f: - SOURCES[f].flags += ['-mssse3'] - if 'sse4.c' in f: - SOURCES[f].flags += ['-msse4.1'] - if 'avx.c' in f: - SOURCES[f].flags += ['-mavx'] - if 'avx2.c' in f: - SOURCES[f].flags += ['-mavx2'] - -if CONFIG['CC_TYPE'] == 'msvc' and CONFIG['INTEL_ARCHITECTURE']: - for f in SOURCES: - if f.endswith('.c'): - if 'avx.c' in f: - SOURCES[f].flags += ['-arch:AVX'] - if 'avx2.c' in f: - SOURCES[f].flags += ['-arch:AVX2'] +for f in SOURCES: + if f.endswith('.c'): + if 'sse2.c' in f: + SOURCES[f].flags += CONFIG['SSE2_FLAGS'] + if 'ssse3.c' in f: + SOURCES[f].flags += ['-mssse3'] + if 'sse4.c' in f: + SOURCES[f].flags += ['-msse4.1'] + if 'avx.c' in f: + SOURCES[f].flags += ['-mavx'] + if 'avx2.c' in f: + SOURCES[f].flags += ['-mavx2'] # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CFLAGS += [ - '-Wno-sign-compare', - '-Wno-unused-function', # so many of these warnings; just ignore them - ] +CFLAGS += [ + '-Wno-sign-compare', + '-Wno-unused-function', # so many of these warnings; just ignore them +] if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): CFLAGS += [ '-Wno-unreachable-code', diff --git a/media/libwebp/src/dsp/moz.build b/media/libwebp/src/dsp/moz.build index 87b4bcd13214..7f3df556c30a 100644 --- a/media/libwebp/src/dsp/moz.build +++ b/media/libwebp/src/dsp/moz.build @@ -36,7 +36,7 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: for f in SOURCES: if f.endswith('neon.c'): SOURCES[f].flags += CONFIG['NEON_FLAGS'] -elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['CC_TYPE'] != 'msvc': +elif CONFIG['CPU_ARCH'] == 'aarch64': SOURCES += [ 'alpha_processing_neon.c', 'dec_neon.c', diff --git a/media/webrtc/moz.build b/media/webrtc/moz.build index 7ddbfe4d7860..d8a4409ff09f 100644 --- a/media/webrtc/moz.build +++ b/media/webrtc/moz.build @@ -101,15 +101,9 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']: GYP_DIRS['trunk/third_party/gflags'].variables = gyp_vars_copy GYP_DIRS['trunk/third_party/gflags'].sandbox_vars['COMPILE_FLAGS'] = {'WARNINGS_AS_ERRORS': []} - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): - # Avoid warnings from third-party code that we can not modify. - if CONFIG['CC_TYPE'] == 'clang-cl': - CXXFLAGS += ['-Wno-invalid-source-encoding'] - else: - CXXFLAGS += [ - '-validate-charset-', - '-wd5038', # C5038 initializer list order warnings - ] + # Avoid warnings from third-party code that we can not modify. + if CONFIG['CC_TYPE'] == 'clang-cl': + CXXFLAGS += ['-Wno-invalid-source-encoding'] if CONFIG['ENABLE_TESTS']: TEST_DIRS += [ diff --git a/media/webrtc/signaling/gtest/moz.build b/media/webrtc/signaling/gtest/moz.build index 0a10d18363bf..d21b9f892e20 100644 --- a/media/webrtc/signaling/gtest/moz.build +++ b/media/webrtc/signaling/gtest/moz.build @@ -42,7 +42,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'uikit' and CONFIG['OS_TARGET'] != 'Android': FINAL_LIBRARY = 'xul-gtest' -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary workaround to enable warning free building # with VS2015. # reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size diff --git a/media/webrtc/trunk/gtest/moz.build b/media/webrtc/trunk/gtest/moz.build index 8b25daf7f9f8..fc486a0275b2 100644 --- a/media/webrtc/trunk/gtest/moz.build +++ b/media/webrtc/trunk/gtest/moz.build @@ -481,7 +481,7 @@ if CONFIG['OS_TARGET'] in ['Darwin', 'Linux', 'WINNT']: if CONFIG['CC_TYPE'] == 'clang': CXXFLAGS += ['-Wno-comma'] - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary workaround to enable warning free building # with VS2015. # reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size diff --git a/media/webrtc/webrtc.mozbuild b/media/webrtc/webrtc.mozbuild index ace183728a2a..c9d061de5b12 100644 --- a/media/webrtc/webrtc.mozbuild +++ b/media/webrtc/webrtc.mozbuild @@ -22,7 +22,7 @@ if CONFIG['MOZ_WEBRTC']: elif CONFIG['OS_TARGET'] == 'Android': DEFINES['WEBRTC_ANDROID'] = True - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' if CONFIG['CC_TYPE'] in ('clang', 'gcc'): diff --git a/memory/build/moz.build b/memory/build/moz.build index 84e3d6281607..ae4426e9027a 100644 --- a/memory/build/moz.build +++ b/memory/build/moz.build @@ -46,7 +46,7 @@ if CONFIG['OS_TARGET'] == 'Android' and CONFIG['CC_TYPE'] == 'clang': if CONFIG['MOZ_BUILD_APP'] != 'memory': FINAL_LIBRARY = 'mozglue' -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += ['-wd4273'] # inconsistent dll linkage (bug 558163) if CONFIG['MOZ_REPLACE_MALLOC_STATIC']: diff --git a/memory/mozalloc/moz.build b/memory/mozalloc/moz.build index 15f9646789b6..69f5bcfdc4e2 100644 --- a/memory/mozalloc/moz.build +++ b/memory/mozalloc/moz.build @@ -14,7 +14,7 @@ EXPORTS.mozilla += [ if CONFIG['WRAP_STL_INCLUDES']: if CONFIG['CC_TYPE'] in ('clang', 'gcc'): EXPORTS.mozilla += ['throw_gcc.h'] - elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + elif CONFIG['CC_TYPE'] == 'clang-cl': DEFINES['_HAS_EXCEPTIONS'] = 0 SOURCES += [ 'msvc_raise_wrappers.cpp', diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 093822c64394..6194db674418 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -81,7 +81,7 @@ DEFINES['IMPL_MFBT'] = True DisableStlWrapping() -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4275', # non dll-interface class used as base for dll-interface class '-wd4530', # C++ exception handler used, but unwind semantics are not enabled diff --git a/modules/brotli/moz.build b/modules/brotli/moz.build index 37a673036ec2..6b511601442a 100644 --- a/modules/brotli/moz.build +++ b/modules/brotli/moz.build @@ -56,7 +56,7 @@ HOST_SOURCES += [ 'tools/brotli.c', ] -if CONFIG['HOST_CC_TYPE'] not in ('msvc', 'clang-cl'): +if CONFIG['HOST_CC_TYPE'] != 'clang-cl': HOST_OS_LIBS += [ 'm' # for log2() function used by Brotli encoder ] diff --git a/modules/fdlibm/src/moz.build b/modules/fdlibm/src/moz.build index 8655789fcb6e..2a931d0d2c6f 100644 --- a/modules/fdlibm/src/moz.build +++ b/modules/fdlibm/src/moz.build @@ -21,7 +21,7 @@ if CONFIG['CC_TYPE'] == 'clang': '-Wno-dangling-else', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4018', # signed/unsigned mismatch '-wd4146', # unary minus operator applied to unsigned type diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 4a8eb266d814..4eabdc1e84ac 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5998,9 +5998,7 @@ pref("dom.datatransfer.mozAtAPIs", true); #endif // Whether or not Prio is supported on this platform. -#ifdef MOZ_LIBPRIO pref("prio.enabled", false); -#endif // External.AddSearchProvider is deprecated and it will be removed in the next // cycles. diff --git a/moz.configure b/moz.configure index e93b99fa6153..2727219a86b4 100755 --- a/moz.configure +++ b/moz.configure @@ -180,7 +180,7 @@ def library_name_info_template(host_or_target): if host_or_target.kernel == 'WINNT': # There aren't artifacts for mingw builds, so it's OK that the # results are inaccurate in that case. - if compiler and compiler.type not in ('msvc', 'clang-cl'): + if compiler and compiler.type != 'clang-cl': return namespace( dll=namespace(prefix='', suffix='.dll'), lib=namespace(prefix='lib', suffix='a'), diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index fd3db244211f..431252dd9634 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -58,8 +58,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']: '/memory/build', ] - if CONFIG['CC_TYPE'] == "msvc": - SOURCES += ['WindowsCFGStatus.cpp'] SOURCES += [ 'Authenticode.cpp', 'UntrustedDllsHandler.cpp', diff --git a/python/mozbuild/mozbuild/action/check_binary.py b/python/mozbuild/mozbuild/action/check_binary.py index cd9301f21a73..8e9e23c33383 100644 --- a/python/mozbuild/mozbuild/action/check_binary.py +++ b/python/mozbuild/mozbuild/action/check_binary.py @@ -247,7 +247,7 @@ def check_nsmodules(target, binary): # MSVC linker, when doing incremental linking, adds padding when # merging sections. Allow there to be more space between the NSModule # symbols, as long as they are in the right order. - test_msvc = (buildconfig.substs.get('CC_TYPE') in ('msvc', 'clang-cl') and \ + test_msvc = (buildconfig.substs.get('CC_TYPE') == 'clang-cl' and \ buildconfig.substs.get('DEVELOPER_OPTIONS')) test_clang = (buildconfig.substs.get('CC_TYPE') == 'clang' and \ buildconfig.substs.get('OS_ARCH') == 'WINNT') diff --git a/python/mozbuild/mozbuild/action/cl.py b/python/mozbuild/mozbuild/action/cl.py deleted file mode 100644 index 8c8b5de778ff..000000000000 --- a/python/mozbuild/mozbuild/action/cl.py +++ /dev/null @@ -1,127 +0,0 @@ -# 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/. - -from __future__ import absolute_import - -import ctypes -import os -import sys - -from mozprocess.processhandler import ProcessHandlerMixin -from mozbuild.makeutil import Makefile - -CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:") - -GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW -GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW - - -# cl.exe likes to print inconsistent paths in the showIncludes output -# (some lowercased, some not, with different directions of slashes), -# and we need the original file case for make/pymake to be happy. -# As this is slow and needs to be called a lot of times, use a cache -# to speed things up. -_normcase_cache = {} - -def normcase(path): - # Get*PathName want paths with backslashes - path = path.replace('/', os.sep) - dir = os.path.dirname(path) - # name is fortunately always going to have the right case, - # so we can use a cache for the directory part only. - name = os.path.basename(path) - if dir in _normcase_cache: - result = _normcase_cache[dir] - else: - path = ctypes.create_unicode_buffer(dir) - length = GetShortPathName(path, None, 0) - shortpath = ctypes.create_unicode_buffer(length) - GetShortPathName(path, shortpath, length) - length = GetLongPathName(shortpath, None, 0) - if length > len(path): - path = ctypes.create_unicode_buffer(length) - GetLongPathName(shortpath, path, length) - result = _normcase_cache[dir] = path.value - return os.path.join(result, name) - - -def InvokeClWithDependencyGeneration(cmdline): - target = "" - # Figure out what the target is - for arg in cmdline: - if arg.startswith("-Fo"): - target = arg[3:] - break - - if target is None: - print >>sys.stderr, "No target set" - return 1 - - # Assume the source file is the last argument - source = cmdline[-1] - assert not source.startswith('-') - - # The deps target lives here - depstarget = os.path.basename(target) + ".pp" - - showincludes = '-showIncludes' in cmdline - cmdline += ['-showIncludes'] - - mk = Makefile() - rule = mk.create_rule([target]) - rule.add_dependencies([normcase(source)]) - - def on_line(line): - # cl -showIncludes prefixes every header with "Note: including file:" - # and an indentation corresponding to the depth (which we don't need) - if line.startswith(CL_INCLUDES_PREFIX): - dep = line[len(CL_INCLUDES_PREFIX):].strip() - # We can't handle pathes with spaces properly in mddepend.pl, but - # we can assume that anything in a path with spaces is a system - # header and throw it away. - dep = normcase(dep) - if ' ' not in dep: - rule.add_dependencies([dep]) - # Hide the line by returning early - if not showincludes: - return - # Make sure we preserve the relevant output from cl. mozprocess - # swallows the newline delimiter, so we need to re-add it. - sys.stdout.write(line) - sys.stdout.write('\n') - - # We need to ignore children because MSVC can fire up a background process - # during compilation. This process is cleaned up on its own. If we kill it, - # we can run into weird compilation issues. - p = ProcessHandlerMixin(cmdline, processOutputLine=[on_line], - ignore_children=True) - p.run() - p.processOutput() - ret = p.wait() - - if ret != 0 or target == "": - # p.wait() returns a long. Somehow sys.exit(long(0)) is like - # sys.exit(1). Don't ask why. - return int(ret) - - depsdir = os.path.normpath(os.path.join(os.curdir, ".deps")) - depstarget = os.path.join(depsdir, depstarget) - if not os.path.isdir(depsdir): - try: - os.makedirs(depsdir) - except OSError: - pass # This suppresses the error we get when the dir exists, at the - # cost of masking failure to create the directory. We'll just - # die on the next line though, so it's not that much of a loss. - - with open(depstarget, "w") as f: - mk.dump(f) - - return 0 - -def main(args): - return InvokeClWithDependencyGeneration(args) - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py index 3aa706bf610a..d7478609f4b8 100644 --- a/python/mozbuild/mozbuild/frontend/context.py +++ b/python/mozbuild/mozbuild/frontend/context.py @@ -484,12 +484,6 @@ class CompileFlags(BaseCompileFlags): def _warnings_as_errors(self): warnings_as_errors = self._context.config.substs.get('WARNINGS_AS_ERRORS') - if self._context.config.substs.get('MOZ_PGO'): - # Don't use warnings-as-errors in MSVC PGO builds because it is suspected of - # causing problems in that situation. (See bug 437002.) - if self._context.config.substs.get('CC_TYPE') == 'msvc': - warnings_as_errors = None - if warnings_as_errors: return [warnings_as_errors] diff --git a/python/mozbuild/mozbuild/frontend/gyp_reader.py b/python/mozbuild/mozbuild/frontend/gyp_reader.py index 0dabdf249778..36381221709a 100644 --- a/python/mozbuild/mozbuild/frontend/gyp_reader.py +++ b/python/mozbuild/mozbuild/frontend/gyp_reader.py @@ -243,7 +243,7 @@ def process_gyp_result(gyp_result, gyp_dir_attrs, path, config, output, context['UNIFIED_SOURCES'] = alphabetical_sorted(unified_sources) defines = target_conf.get('defines', []) - if config.substs['CC_TYPE'] in ('msvc', 'clang-cl') and no_chromium: + if config.substs['CC_TYPE'] == 'clang-cl' and no_chromium: msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, {}) defines.extend(msvs_settings.GetComputedDefines(c)) for define in defines: @@ -380,7 +380,7 @@ class GypProcessor(object): # gyp expects plain str instead of unicode. The frontend code gives us # unicode strings, so convert them. path = encode(path) - if config.substs['CC_TYPE'] in ('msvc', 'clang-cl'): + if config.substs['CC_TYPE'] == 'clang-cl': # This isn't actually used anywhere in this generator, but it's needed # to override the registry detection of VC++ in gyp. os.environ['GYP_MSVS_OVERRIDE_PATH'] = 'fake_path' diff --git a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py index 38967e14c95d..3b4aa9f532e8 100755 --- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py +++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py @@ -70,8 +70,6 @@ def GCC_BASE(version): '__GNUC_MINOR__': version.minor, '__GNUC_PATCHLEVEL__': version.patch, '__STDC__': 1, - '__ORDER_LITTLE_ENDIAN__': 1234, - '__ORDER_BIG_ENDIAN__': 4321, }) @@ -102,10 +100,14 @@ DEFAULT_GCC = GCC_6 DEFAULT_GXX = GXX_6 GCC_PLATFORM_LITTLE_ENDIAN = { + '__ORDER_LITTLE_ENDIAN__': 1234, + '__ORDER_BIG_ENDIAN__': 4321, '__BYTE_ORDER__': 1234, } GCC_PLATFORM_BIG_ENDIAN = { + '__ORDER_LITTLE_ENDIAN__': 1234, + '__ORDER_BIG_ENDIAN__': 4321, '__BYTE_ORDER__': 4321, } @@ -234,14 +236,6 @@ def VS(version): }) -VS_2013u2 = VS('18.00.30501') -VS_2013u3 = VS('18.00.30723') -VS_2015 = VS('19.00.23026') -VS_2015u1 = VS('19.00.23506') -VS_2015u2 = VS('19.00.23918') -VS_2015u3 = VS('19.00.24213') -VS_2017u4 = VS('19.11.25547') -VS_2017u6 = VS('19.13.26128') VS_2017u8 = VS('19.15.26726') VS_PLATFORM_X86 = { @@ -265,8 +259,10 @@ CLANG_CL_3_9 = (CLANG_BASE('3.9.0') + VS('18.00.00000') + DEFAULT_C11 + }, } -CLANG_CL_PLATFORM_X86 = FakeCompiler(VS_PLATFORM_X86, GCC_PLATFORM_X86[None]) -CLANG_CL_PLATFORM_X86_64 = FakeCompiler(VS_PLATFORM_X86_64, GCC_PLATFORM_X86_64[None]) +CLANG_CL_PLATFORM_X86 = FakeCompiler( + VS_PLATFORM_X86, GCC_PLATFORM_X86[None], GCC_PLATFORM_LITTLE_ENDIAN) +CLANG_CL_PLATFORM_X86_64 = FakeCompiler( + VS_PLATFORM_X86_64, GCC_PLATFORM_X86_64[None], GCC_PLATFORM_LITTLE_ENDIAN) LIBRARY_NAME_INFOS = { 'linux-gnu': { @@ -385,7 +381,7 @@ class BaseToolchainTest(BaseConfigureTest): target_os = getattr(self, 'TARGET', self.HOST).split('-', 2)[2] if target_os == 'mingw32': compiler_type = sandbox._value_for(sandbox['c_compiler']).type - if compiler_type in ('msvc', 'clang-cl'): + if compiler_type == 'clang-cl': target_os = 'msvc' elif target_os == 'linux-gnuabi64': target_os = 'linux-gnu' @@ -874,14 +870,6 @@ class WindowsToolchainTest(BaseToolchainTest): # For the purpose of this test, it doesn't matter that the paths are not # real Windows paths. PATHS = { - '/opt/VS_2013u2/bin/cl': VS_2013u2 + VS_PLATFORM_X86, - '/opt/VS_2013u3/bin/cl': VS_2013u3 + VS_PLATFORM_X86, - '/opt/VS_2015/bin/cl': VS_2015 + VS_PLATFORM_X86, - '/opt/VS_2015u1/bin/cl': VS_2015u1 + VS_PLATFORM_X86, - '/opt/VS_2015u2/bin/cl': VS_2015u2 + VS_PLATFORM_X86, - '/opt/VS_2015u3/bin/cl': VS_2015u3 + VS_PLATFORM_X86, - '/opt/VS_2017u4/bin/cl': VS_2017u4 + VS_PLATFORM_X86, - '/opt/VS_2017u6/bin/cl': VS_2017u6 + VS_PLATFORM_X86, '/usr/bin/cl': VS_2017u8 + VS_PLATFORM_X86, '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86, '/usr/bin/gcc': DEFAULT_GCC + GCC_PLATFORM_X86_WIN, @@ -900,32 +888,6 @@ class WindowsToolchainTest(BaseToolchainTest): '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_WIN, } - VS_FAILURE_MESSAGE = ( - 'This version (%s) of the MSVC compiler is not supported.\nYou must' - ' install Visual C++ 2017 Update 8 or later in order to build.\n' - 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') - VS_2013u2_RESULT = VS_FAILURE_MESSAGE % '18.00.30501' - VS_2013u3_RESULT = VS_FAILURE_MESSAGE % '18.00.30723' - VS_2015_RESULT = VS_FAILURE_MESSAGE % '19.00.23026' - VS_2015u1_RESULT = VS_FAILURE_MESSAGE % '19.00.23506' - VS_2015u2_RESULT = VS_FAILURE_MESSAGE % '19.00.23918' - VS_2015u3_RESULT = VS_FAILURE_MESSAGE % '19.00.24213' - VS_2017u4_RESULT = VS_FAILURE_MESSAGE % '19.11.25547' - VS_2017u6_RESULT = VS_FAILURE_MESSAGE % '19.13.26128' - VS_2017u8_RESULT = CompilerResult( - flags=[], - version='19.15.26726', - type='msvc', - compiler='/usr/bin/cl', - language='C', - ) - VSXX_2017u8_RESULT = CompilerResult( - flags=[], - version='19.15.26726', - type='msvc', - compiler='/usr/bin/cl', - language='C++', - ) CLANG_CL_3_9_RESULT = CompilerResult( version='3.9.0', flags=['-Xclang', '-std=gnu99'], @@ -953,65 +915,11 @@ class WindowsToolchainTest(BaseToolchainTest): DEFAULT_GCC_RESULT = LinuxToolchainTest.DEFAULT_GCC_RESULT DEFAULT_GXX_RESULT = LinuxToolchainTest.DEFAULT_GXX_RESULT - # VS2017u6 or greater is required. - def test_msvc(self): - # We'll pick msvc if clang-cl can't be found. - paths = { - k: v for k, v in self.PATHS.iteritems() - if os.path.basename(k) != 'clang-cl' - } - self.do_toolchain_test(paths, { - 'c_compiler': self.VS_2017u8_RESULT, - 'cxx_compiler': self.VSXX_2017u8_RESULT, - }) - def test_unsupported_msvc(self): self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2017u6_RESULT, + 'c_compiler': 'Unknown compiler or compiler not supported.' }, environ={ - 'CC': '/opt/VS_2017u6/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2017u4_RESULT, - }, environ={ - 'CC': '/opt/VS_2017u4/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2015u3_RESULT, - }, environ={ - 'CC': '/opt/VS_2015u3/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2015u2_RESULT, - }, environ={ - 'CC': '/opt/VS_2015u2/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2015u1_RESULT, - }, environ={ - 'CC': '/opt/VS_2015u1/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2015_RESULT, - }, environ={ - 'CC': '/opt/VS_2015/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2013u3_RESULT, - }, environ={ - 'CC': '/opt/VS_2013u3/bin/cl', - }) - - self.do_toolchain_test(self.PATHS, { - 'c_compiler': self.VS_2013u2_RESULT, - }, environ={ - 'CC': '/opt/VS_2013u2/bin/cl', + 'CC': '/usr/bin/cl', }) def test_clang_cl(self): @@ -1060,15 +968,6 @@ class WindowsToolchainTest(BaseToolchainTest): 'CXX': 'clang++-3.3', }) - def test_cannot_cross(self): - paths = { - '/usr/bin/cl': VS_2017u8 + VS_PLATFORM_X86_64, - } - self.do_toolchain_test(paths, { - 'c_compiler': ('Target C compiler target CPU (x86_64) ' - 'does not match --target CPU (i686)'), - }) - class Windows64ToolchainTest(WindowsToolchainTest): HOST = 'x86_64-pc-mingw32' @@ -1076,14 +975,6 @@ class Windows64ToolchainTest(WindowsToolchainTest): # For the purpose of this test, it doesn't matter that the paths are not # real Windows paths. PATHS = { - '/opt/VS_2013u2/bin/cl': VS_2013u2 + VS_PLATFORM_X86_64, - '/opt/VS_2013u3/bin/cl': VS_2013u3 + VS_PLATFORM_X86_64, - '/opt/VS_2015/bin/cl': VS_2015 + VS_PLATFORM_X86_64, - '/opt/VS_2015u1/bin/cl': VS_2015u1 + VS_PLATFORM_X86_64, - '/opt/VS_2015u2/bin/cl': VS_2015u2 + VS_PLATFORM_X86_64, - '/opt/VS_2015u3/bin/cl': VS_2015u3 + VS_PLATFORM_X86_64, - '/opt/VS_2017u4/bin/cl': VS_2017u4 + VS_PLATFORM_X86_64, - '/opt/VS_2017u6/bin/cl': VS_2017u6 + VS_PLATFORM_X86_64, '/usr/bin/cl': VS_2017u8 + VS_PLATFORM_X86_64, '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86_64, '/usr/bin/gcc': DEFAULT_GCC + GCC_PLATFORM_X86_64_WIN, @@ -1104,15 +995,6 @@ class Windows64ToolchainTest(WindowsToolchainTest): '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64_WIN, } - def test_cannot_cross(self): - paths = { - '/usr/bin/cl': VS_2017u8 + VS_PLATFORM_X86, - } - self.do_toolchain_test(paths, { - 'c_compiler': ('Target C compiler target CPU (x86) ' - 'does not match --target CPU (x86_64)'), - }) - class LinuxCrossCompileToolchainTest(BaseToolchainTest): TARGET = 'arm-unknown-linux-gnu' @@ -1454,18 +1336,6 @@ class WindowsCrossToolchainTest(BaseToolchainTest): DEFAULT_CLANG_RESULT = LinuxToolchainTest.DEFAULT_CLANG_RESULT DEFAULT_CLANGXX_RESULT = LinuxToolchainTest.DEFAULT_CLANGXX_RESULT - def test_wsl_cross(self): - paths = { - '/usr/bin/cl': VS_2017u8 + VS_PLATFORM_X86_64, - } - paths.update(LinuxToolchainTest.PATHS) - self.do_toolchain_test(paths, { - 'c_compiler': WindowsToolchainTest.VS_2017u8_RESULT, - 'cxx_compiler': WindowsToolchainTest.VSXX_2017u8_RESULT, - 'host_c_compiler': self.DEFAULT_CLANG_RESULT, - 'host_cxx_compiler': self.DEFAULT_CLANGXX_RESULT, - }) - def test_clang_cl_cross(self): paths = { '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86_64, diff --git a/python/mozbuild/mozbuild/test/test_util.py b/python/mozbuild/mozbuild/test/test_util.py index 053b94fd8169..cc0761e0e21a 100644 --- a/python/mozbuild/mozbuild/test/test_util.py +++ b/python/mozbuild/mozbuild/test/test_util.py @@ -868,15 +868,14 @@ class TestMisc(unittest.TestCase): class TestEnumString(unittest.TestCase): def test_string(self): - CompilerType = EnumString.subclass('msvc', 'gcc', 'clang', 'clang-cl') + CompilerType = EnumString.subclass('gcc', 'clang', 'clang-cl') - type = CompilerType('msvc') - self.assertEquals(type, 'msvc') - self.assertNotEquals(type, 'gcc') + type = CompilerType('gcc') + self.assertEquals(type, 'gcc') self.assertNotEquals(type, 'clang') self.assertNotEquals(type, 'clang-cl') - self.assertIn(type, ('msvc', 'clang-cl')) - self.assertNotIn(type, ('gcc', 'clang')) + self.assertIn(type, ('gcc', 'clang-cl')) + self.assertNotIn(type, ('clang', 'clang-cl')) with self.assertRaises(EnumStringComparisonError): self.assertEquals(type, 'foo') diff --git a/security/certverifier/moz.build b/security/certverifier/moz.build index 5772ed3e62d8..f4df7a2fb8ff 100644 --- a/security/certverifier/moz.build +++ b/security/certverifier/moz.build @@ -45,88 +45,15 @@ if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += ['-Xclang'] CXXFLAGS += ['-Wall'] -if CONFIG['CC_TYPE'] == 'msvc': - # -Wall with Visual C++ enables too many problematic warnings - CXXFLAGS += [ - '-wd4324', # structure was padded due to __declspec(align()) - '-wd4355', # 'this' used in base member initializer list - '-wd4464', # relative include path contains '..' - '-wd4480', # nonstandard extension used: specifying underlying type for - # enum 'enum' - '-wd4481', # nonstandard extension used: override specifier 'keyword' - '-wd4510', # default constructor could not be generated - '-wd4512', # assignment operator could not be generated - '-wd4514', # 'function': unreferenced inline function has been removed - '-wd4610', # struct 'symbol' can never be instantiated - user defined - # constructor required - '-wd4619', # pragma warning: there is no warning 'warning' - '-wd4623', # default constructor could not be generated because a base - # class default constructor is inaccessible or deleted - '-wd4625', # copy constructor could not be generated because a base - # class copy constructor is inaccessible or deleted - '-wd4626', # assignment operator could not be generated because a base - # class assignment operator is inaccessible or deleted - '-wd4628', # digraphs not supported with -Ze (nsThreadUtils.h includes - # what would be the digraph "<:" in the expression - # "mozilla::EnableIf<::detail::...". Since we don't want it - # interpreted as a digraph anyway, we can disable the - # warning.) - '-wd4640', # construction of local static object is not thread-safe - '-wd4710', # 'function': function not inlined - '-wd4711', # function 'function' selected for inline expansion - '-wd4820', # 'bytes' bytes padding added after construct 'member_name' - ] +CXXFLAGS += [ + '-Wextra', + '-Wunreachable-code', +] - # Disable Spectre diagnostics only if optimization is disabled. - # AArch64 MSVC apparently warns about Spectre even if optimization is - # enabled, so disable the diagnostic there too. - if not CONFIG['MOZ_OPTIMIZE'] or CONFIG['CPU_ARCH'] == 'aarch64': - CXXFLAGS += [ - '-wd5045', # Compiler will insert Spectre mitigation for memory - # load if /Qspectre switch specified - ] - - # MSVC 2010's headers trigger these - CXXFLAGS += [ - '-wd4548', # expression before comma has no effect; ... - '-wd4668', # 'symbol' is not defined as a preprocessor macro... - '-wd4987', # nonstandard extension used - ] - - # MSVC 2015 triggers these - CXXFLAGS += [ - '-wd4456', # declaration of 'rv' hides previous local declaration - '-wd4458', # declaration of 'input' hides class member - ] - - # The following warnings are disabled because MSVC 2017 headers aren't - # warning free at the -Wall level. - CXXFLAGS += [ - '-wd4061', # enumerator 'identifier' in switch of enum 'enumeration' is - # not explicitly handled by a case label - '-wd4365', # 'action' : conversion from 'type_1' to 'type_2', - # signed/unsigned mismatch - '-wd4774', # '' : format string expected in argument - # is not a string literal - ] - - # Gecko headers aren't warning-free enough for us to enable these warnings - CXXFLAGS += [ - '-wd4100', # 'symbol' : unreferenced formal parameter - '-wd4127', # conditional expression is constant - '-wd4946', # reinterpret_cast used between related types - ] - -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wextra', - '-Wunreachable-code', - ] - - # Gecko headers aren't warning-free enough for us to enable these warnings. - CXXFLAGS += [ - '-Wno-unused-parameter', - ] +# Gecko headers aren't warning-free enough for us to enable these warnings. +CXXFLAGS += [ + '-Wno-unused-parameter', +] FINAL_LIBRARY = 'xul' diff --git a/security/ct/moz.build b/security/ct/moz.build index cff5d75e7614..3051a93099a4 100644 --- a/security/ct/moz.build +++ b/security/ct/moz.build @@ -43,81 +43,15 @@ if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += ['-Xclang'] CXXFLAGS += ['-Wall'] -if CONFIG['CC_TYPE'] == 'msvc': - # -Wall with Visual C++ enables too many problematic warnings - CXXFLAGS += [ - '-wd4324', # structure was padded due to __declspec(align()) - '-wd4355', # 'this' used in base member initializer list - '-wd4464', # relative include path contains '..' - '-wd4480', # nonstandard extension used: specifying underlying type for - # enum 'enum' - '-wd4481', # nonstandard extension used: override specifier 'keyword' - '-wd4510', # default constructor could not be generated - '-wd4512', # assignment operator could not be generated - '-wd4514', # 'function': unreferenced inline function has been removed - '-wd4610', # struct 'symbol' can never be instantiated - user defined - # constructor required - '-wd4619', # pragma warning: there is no warning 'warning' - '-wd4623', # default constructor could not be generated because a base - # class default constructor is inaccessible or deleted - '-wd4625', # copy constructor could not be generated because a base - # class copy constructor is inaccessible or deleted - '-wd4626', # assignment operator could not be generated because a base - # class assignment operator is inaccessible or deleted - '-wd4640', # construction of local static object is not thread-safe - '-wd4710', # 'function': function not inlined - '-wd4711', # function 'function' selected for inline expansion - '-wd4820', # 'bytes' bytes padding added after construct 'member_name' - ] +CXXFLAGS += [ + '-Wextra', + '-Wunreachable-code', +] - # Disable Spectre diagnostics only if optimization is disabled. - if not CONFIG['MOZ_OPTIMIZE']: - CXXFLAGS += [ - '-wd5045', # Compiler will insert Spectre mitigation for memory - # load if /Qspectre switch specified - ] - - # MSVC 2010's headers trigger these - CXXFLAGS += [ - '-wd4548', # expression before comma has no effect; ... - '-wd4668', # 'symbol' is not defined as a preprocessor macro... - '-wd4987', # nonstandard extension used - ] - - # MSVC 2015 triggers these - CXXFLAGS += [ - '-wd4456', # declaration of 'rv' hides previous local declaration - '-wd4458', # declaration of 'input' hides class member - ] - - # The following warnings are disabled because MSVC 2017 headers aren't - # warning free at the -Wall level. - CXXFLAGS += [ - '-wd4061', # enumerator 'identifier' in switch of enum 'enumeration' is - # not explicitly handled by a case label - '-wd4365', # 'action' : conversion from 'type_1' to 'type_2', - # signed/unsigned mismatch - '-wd4774', # '' : format string expected in argument - # is not a string literal - ] - - # Gecko headers aren't warning-free enough for us to enable these warnings - CXXFLAGS += [ - '-wd4100', # 'symbol' : unreferenced formal parameter - '-wd4127', # conditional expression is constant - '-wd4946', # reinterpret_cast used between related types - ] - -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wextra', - '-Wunreachable-code', - ] - - # Gecko headers aren't warning-free enough for us to enable these warnings. - CXXFLAGS += [ - '-Wno-unused-parameter', - ] +# Gecko headers aren't warning-free enough for us to enable these warnings. +CXXFLAGS += [ + '-Wno-unused-parameter', +] FINAL_LIBRARY = 'xul' diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index 52e896a04568..97cf2e5dda9f 100755 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -169,7 +169,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT': DisableStlWrapping() # Suppress warnings in third-party code. - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4275', # non dll-interface class exception used as base for dll-interface class '-wd4717', # recursive on all control paths, function will cause runtime stack overflow diff --git a/toolkit/components/jsoncpp/src/lib_json/moz.build b/toolkit/components/jsoncpp/src/lib_json/moz.build index e515c5680673..0c60bcd3f448 100644 --- a/toolkit/components/jsoncpp/src/lib_json/moz.build +++ b/toolkit/components/jsoncpp/src/lib_json/moz.build @@ -21,7 +21,7 @@ if CONFIG['CC_TYPE'] == 'clang-cl': '-Xclang', '-fcxx-exceptions', ] -elif CONFIG['CC_TYPE'] not in ('msvc', 'clang-cl'): +elif CONFIG['CC_TYPE'] != 'clang-cl': CXXFLAGS += [ '-fexceptions', ] @@ -32,7 +32,7 @@ DisableStlWrapping() Library('jsoncpp') # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4005', # macro redefinition ] @@ -47,10 +47,9 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): '-Wno-c++11-narrowing', ] -if CONFIG['CC_TYPE'] in ('clang', 'clang-cl', 'gcc'): - CXXFLAGS += [ - '-Wno-implicit-fallthrough', - ] +CXXFLAGS += [ + '-Wno-implicit-fallthrough', +] if CONFIG['CC_TYPE'] == 'clang-cl': AllowCompilerWarnings() # workaround for bug 1090497 diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build index 9f4eda9202c8..46f9b4cc409d 100644 --- a/toolkit/components/maintenanceservice/moz.build +++ b/toolkit/components/maintenanceservice/moz.build @@ -34,7 +34,7 @@ LOCAL_INCLUDES += [ USE_STATIC_LIBS = True -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] RCINCLUDE = 'maintenanceservice.rc' diff --git a/toolkit/components/protobuf/moz.build b/toolkit/components/protobuf/moz.build index b3823938f180..22b1002a1c21 100644 --- a/toolkit/components/protobuf/moz.build +++ b/toolkit/components/protobuf/moz.build @@ -136,7 +136,7 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'): '-Wno-null-conversion', '-Wno-unused-local-typedef', ] -elif CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +elif CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4005', # 'WIN32_LEAN_AND_MEAN' : macro redefinition '-wd4018', # '<' : signed/unsigned mismatch diff --git a/toolkit/crashreporter/crashreporter.mozbuild b/toolkit/crashreporter/crashreporter.mozbuild index b8469abad6eb..2a12070b9d70 100644 --- a/toolkit/crashreporter/crashreporter.mozbuild +++ b/toolkit/crashreporter/crashreporter.mozbuild @@ -10,7 +10,7 @@ LOCAL_INCLUDES += [ ] # Suppress warnings in third-party code. -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += [ '-wd4005', # macro redefinition '-wd4146', # negative unsigned @@ -34,7 +34,7 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): '-Wno-c++11-narrowing', ] -if CONFIG['CC_TYPE'] not in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] != 'clang-cl': CXXFLAGS += [ '-Wno-implicit-fallthrough', ] diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/moz.build b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/moz.build index c7d381cb3329..26414cadc9a4 100644 --- a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/moz.build +++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/moz.build @@ -19,7 +19,7 @@ HOST_CXXFLAGS += [ '-O2', ] -if CONFIG['HOST_CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['HOST_CC_TYPE'] == 'clang-cl': HOST_CXXFLAGS += [ '-EHsc', '-MD' diff --git a/toolkit/crashreporter/test/moz.build b/toolkit/crashreporter/test/moz.build index abea73981f45..a060850e5dea 100755 --- a/toolkit/crashreporter/test/moz.build +++ b/toolkit/crashreporter/test/moz.build @@ -36,7 +36,7 @@ if CONFIG['CC_TYPE'] == 'clang-cl': '-Xclang', '-fcxx-exceptions', ] -elif CONFIG['CC_TYPE'] not in ('msvc', 'clang-cl'): +else: SOURCES['ExceptionThrower.cpp'].flags += [ '-fexceptions', ] @@ -57,5 +57,5 @@ include('/toolkit/crashreporter/crashreporter.mozbuild') NO_PGO = True # Temporary workaround for an issue in upstream breakpad -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': CXXFLAGS += ['-wd4334'] diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index 760320e05617..968bcb792e8c 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -85,7 +85,7 @@ def Libxul(name, output_category=None): LDFLAGS += ['-Wl,-U,_OBJC_CLASS_$_NSCustomTouchBarItem'] LDFLAGS += ['-lresolv'] - if CONFIG['MOZ_DEBUG_SYMBOLS'] and CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['MOZ_DEBUG_SYMBOLS'] and CONFIG['CC_TYPE'] == 'clang-cl': LDFLAGS += ['-NATVIS:%s/toolkit/library/gecko.natvis' % TOPSRCDIR] if CONFIG['RUSTC_NATVIS_LDFLAGS']: LDFLAGS += CONFIG['RUSTC_NATVIS_LDFLAGS'] @@ -323,7 +323,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'dhcpcsvc', ] - if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): + if CONFIG['CC_TYPE'] == 'clang-cl': OS_LIBS += [ 'runtimeobject', ] diff --git a/toolkit/moz.configure b/toolkit/moz.configure index a42c6c49b630..0ef3b344f913 100644 --- a/toolkit/moz.configure +++ b/toolkit/moz.configure @@ -425,16 +425,9 @@ imply_option('--enable-fmp4', ffmpeg, '--enable-ffmpeg') option('--disable-av1', help='Disable av1 video support') -@depends('--enable-av1', target, c_compiler) -def av1(value, target, c_compiler): - enabled = bool(value) - if value.origin == 'default': - if target.os == 'WINNT' and target.cpu == 'x86' and \ - c_compiler and c_compiler.type == 'msvc': - enabled = False - else: - enabled = True - if enabled: +@depends('--enable-av1') +def av1(value): + if value: return True @depends(target, nasm_version, when=av1 & compile_environment) @@ -1141,23 +1134,20 @@ midl = check_prog('MIDL', midl_names, when=check_for_midl, allow_missing=True, when=depends(midl, target)(lambda m, t: m and t.kernel == 'WINNT')) @imports(_from='mozbuild.shellutil', _import='quote') def midl_flags(c_compiler, target, toolchain_search_path): - if c_compiler and c_compiler.type in ('msvc', 'clang-cl'): + if c_compiler and c_compiler.type == 'clang-cl': env = { 'x86': 'win32', 'x86_64': 'x64', 'aarch64': 'arm64', }[target.cpu] flags = ['-env', env] - if c_compiler.type == 'msvc': - flags += ['-cpp_cmd', c_compiler.compiler] - else: - # Ideally, we'd use the same flags setup as for msvc, but clang-cl - # currently doesn't work as a preprocessor for midl, so we need to - # find cl. https://bugs.llvm.org/show_bug.cgi?id=40140 - cl = find_program('cl', paths=toolchain_search_path) - if not cl: - die('Could not find Microsoft Visual C/C++ compiler for MIDL') - flags += ['-cpp_cmd', cl] + # Ideally, we'd use ['-cpp_cmd', c_compiler.compiler], but clang-cl + # currently doesn't work as a preprocessor for midl, so we need to + # find cl. https://bugs.llvm.org/show_bug.cgi?id=40140 + cl = find_program('cl', paths=toolchain_search_path) + if not cl: + die('Could not find Microsoft Visual C/C++ compiler for MIDL') + flags += ['-cpp_cmd', cl] return flags # mingw @@ -1243,18 +1233,6 @@ def launcher(value, target): set_config('MOZ_LAUNCHER_PROCESS', launcher) set_define('MOZ_LAUNCHER_PROCESS', launcher) -# Prio -# ============================================================== -@depends(c_compiler) -def libprio(info): - if info: - # MSVC is not supported by libprio. - if info.type in ('msvc',): - return None - return True - -set_config('MOZ_LIBPRIO', libprio) - # Maintenance service (Windows only) # ============================================================== diff --git a/toolkit/mozapps/update/updater/updater-common.build b/toolkit/mozapps/update/updater/updater-common.build index 61ff150b1cb6..4ce082f3b167 100644 --- a/toolkit/mozapps/update/updater/updater-common.build +++ b/toolkit/mozapps/update/updater/updater-common.build @@ -101,7 +101,7 @@ DELAYLOAD_DLLS += [ 'wsock32.dll', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] elif CONFIG['OS_ARCH'] == 'WINNT': WIN32_EXE_LDFLAGS += ['-municode'] diff --git a/widget/windows/moz.build b/widget/windows/moz.build index 46b041626d01..fc592ce5974a 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -151,7 +151,7 @@ OS_LIBS += [ 'rpcrt4', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': SOURCES += [ 'ToastNotification.cpp', 'ToastNotificationHandler.cpp', diff --git a/xpcom/ds/moz.build b/xpcom/ds/moz.build index 504569d200d9..b63d1f36b2f7 100644 --- a/xpcom/ds/moz.build +++ b/xpcom/ds/moz.build @@ -133,12 +133,6 @@ UNIFIED_SOURCES += [ SOURCES += [ 'nsGkAtoms.cpp', ] -if CONFIG['CC_TYPE'] == 'msvc': - # Needed for gGkAtoms. - SOURCES['nsGkAtoms.cpp'].flags += [ - '-constexpr:steps300000', - '-Zc:externConstexpr', - ] LOCAL_INCLUDES += [ '../io', diff --git a/xpcom/glue/standalone/moz.build b/xpcom/glue/standalone/moz.build index c41bdc33d680..85a16c4489b0 100644 --- a/xpcom/glue/standalone/moz.build +++ b/xpcom/glue/standalone/moz.build @@ -13,7 +13,7 @@ Library('xpcomglue') FORCE_STATIC_LIB = True -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': DEFINES['_USE_ANSI_CPP'] = True # Don't include directives about which CRT to use CFLAGS += ['-Zl'] diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build index 8ecd7e08f4ea..fcc1988ba187 100644 --- a/xpcom/io/moz.build +++ b/xpcom/io/moz.build @@ -135,9 +135,6 @@ UNIFIED_SOURCES += [ SOURCES += [ 'nsDirectoryService.cpp', ] -if CONFIG['CC_TYPE'] == 'msvc': - # Needed for gDirectoryAtoms. - SOURCES['nsDirectoryService.cpp'].flags += ['-Zc:externConstexpr'] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': SOURCES += [ @@ -156,7 +153,7 @@ LOCAL_INCLUDES += [ '../build', ] -if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'): +if CONFIG['CC_TYPE'] == 'clang-cl': # This is intended as a temporary hack to support building with VS2015. # '_snwprintf' : format string '%s' requires an argument of type 'wchar_t *', # but variadic argument 3 has type 'char16ptr_t' From 2980c6fe0b9a712a46d226da4dd2c6f4b2acf895 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 14 Feb 2019 18:56:29 +0000 Subject: [PATCH 83/84] Bug 1512504 - Remove now unused CFG test. r=tjr Depends on D19615 Differential Revision: https://phabricator.services.mozilla.com/D19616 --HG-- extra : moz-landing-system : lando --- mozglue/build/WindowsCFGStatus.cpp | 164 --------------------- mozglue/build/WindowsCFGStatus.h | 33 ----- mozglue/build/moz.build | 1 - toolkit/xre/test/browser.ini | 4 - toolkit/xre/test/browser_checkcfgstatus.js | 79 ---------- 5 files changed, 281 deletions(-) delete mode 100644 mozglue/build/WindowsCFGStatus.cpp delete mode 100644 mozglue/build/WindowsCFGStatus.h delete mode 100644 toolkit/xre/test/browser_checkcfgstatus.js diff --git a/mozglue/build/WindowsCFGStatus.cpp b/mozglue/build/WindowsCFGStatus.cpp deleted file mode 100644 index 97c778e2d409..000000000000 --- a/mozglue/build/WindowsCFGStatus.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 -#include -#include -#include - -#include - -#include "WindowsCFGStatus.h" - -// Inspired by -// https://github.com/trailofbits/cfg-showcase/blob/master/cfg_icall.cpp - -jmp_buf env; - -#pragma optimize("", off) -void not_entry_point() { - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - __nop(); - - longjmp(env, 1); - return; -} -#pragma optimize("", on) - -typedef void (*fn_ptr)(); - -/* - * Tests for Microsoft's Control Flow Guard compiler security feature. - * This function will crash if CFG is enabled, and return false if it is - * not enabled. - * - * CFG protects indirect function calls and ensures they call a valid entry - * point. We create a function pointer that calls an invalid entry point. - * That invalid entry point is a nop sled. - * - * Jumping into the nop sled skips the preamble that a function normally - * performs, so if we hit the return (ret) we would mess up the stack. - * To 'return' from the function safely we jump back to our original - * function - no preamble and no return. - * - * We use setjmp/longjmp because inline asm instructions aren't supported - * in x64 by MSVC. - */ -MFBT_API bool CFG_DisabledOrCrash() { - // setjmp returns 0 on the initial call and whatever value is given - // to longjmp (here it is 1) when it is jumped back to. - int val = setjmp(env); - - if (val == 0) { - fn_ptr slide_to_the_left = (fn_ptr)((uintptr_t)(not_entry_point) + 0x20); - - // If CFG is enabled, we're going to crash on the next line - slide_to_the_left(); - } - - return false; -} diff --git a/mozglue/build/WindowsCFGStatus.h b/mozglue/build/WindowsCFGStatus.h deleted file mode 100644 index 62154576c807..000000000000 --- a/mozglue/build/WindowsCFGStatus.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 mozilla_windowscfgstatus_h -#define mozilla_windowscfgstatus_h - -#if defined(_MSC_VER) && \ - (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64)) - -# include -# include "mozilla/Attributes.h" -# include "mozilla/Types.h" - -extern "C" { - -/** - * Tests for Microsoft's Control Flow Guard compiler security feature. - * This function will crash if CFG is enabled. - * - * There is a dependency on the calling convention in - * toolkit/xre/test/browser_checkcfgstatus.js so be sure to update that - * if it changes. - * - * @returns false if CFG is not enabled. Crashes if CFG is enabled. - * It will never return true. - */ -MFBT_API bool CFG_DisabledOrCrash(); -} - -#endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) -#endif // mozilla_windowscfgstatus_h diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 431252dd9634..e47f3be7968b 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -90,7 +90,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']: 'arm.h', 'mips.h', 'SSE.h', - 'WindowsCFGStatus.h', 'WindowsDllBlocklist.h', ] diff --git a/toolkit/xre/test/browser.ini b/toolkit/xre/test/browser.ini index d879aa2b0a18..5e1878b20d1c 100644 --- a/toolkit/xre/test/browser.ini +++ b/toolkit/xre/test/browser.ini @@ -2,7 +2,3 @@ [browser_checkdllblockliststate.js] skip-if = os != "win" || (os == "win" && os_version == "10.0") # Bug 1401250 - -[browser_checkcfgstatus.js] -# CFG is only supported on MSVC-compiled Windows 10+, only run it there -skip-if = cc_type != "msvc" || os != "win" || os_version == "6.1" || os_version == "6.3" diff --git a/toolkit/xre/test/browser_checkcfgstatus.js b/toolkit/xre/test/browser_checkcfgstatus.js deleted file mode 100644 index 183b451e31ab..000000000000 --- a/toolkit/xre/test/browser_checkcfgstatus.js +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable mozilla/no-arbitrary-setTimeout */ -"use strict"; - -/** - * Returns the id of the crash minidump. - * - * @param subject (nsISupports) - * The subject passed through the ipc:content-shutdown - * observer notification when a content process crash has - * occurred. - * @returns {String} The crash dump id. - */ -function getCrashDumpId(subject) { - Assert.ok(subject instanceof Ci.nsIPropertyBag2, - "Subject needs to be a nsIPropertyBag2 to clean up properly"); - - return subject.getPropertyAsAString("dumpID"); -} - -// Calls a function that should crash when CFG is enabled -add_task(async function test_cfg_enabled() { - // On debug builds, crashing tabs results in much thinking, which - // slows down the test and results in intermittent test timeouts, - // so we'll pump up the expected timeout for this test. - requestLongerTimeout(2); - - if (!gMultiProcessBrowser) { - Assert.ok(false, "This test should only be run in multi-process mode."); - return; - } - - await BrowserTestUtils.withNewTab({ - gBrowser, - url: "http://example.com", - }, async function(browser) { - // First, sanity check... - Assert.ok(browser.isRemoteBrowser, - "This browser needs to be remote if this test is going to " + - "work properly."); - let contentProcessGone = TestUtils.topicObserved("ipc:content-shutdown"); - - ContentTask.spawn(browser, null, function() { - // Until 1342564 is fixed, we need to disable this call or it will cause False Positives - privateNoteIntentionalCrash(); - - const {ctypes} = ChromeUtils.import("resource://gre/modules/ctypes.jsm"); - let mozglue = ctypes.open("mozglue.dll"); - let CFG_DisabledOrCrash = mozglue.declare("CFG_DisabledOrCrash", ctypes.default_abi, ctypes.bool); - CFG_DisabledOrCrash(); - // ^-- this line should have crashed us. If we get to the next line, no bueno - - Assert.ok(false, "This test should cause a crash when CFG is enabled. If it " + - "does not, this false assertion will trigger. It means CFG is not enabled " + - "and we have lost compiler hardening features."); - }); - - // If we don't crash within 5 seconds, give up. - let timeout = new Promise(resolve => setTimeout(resolve, 5000, [null])); - - // We crash or timeout - let [subject /* , data */] = await Promise.race([timeout, contentProcessGone]); - - if (!subject) { - // We timed out, or otherwise didn't crash properly - Assert.ok(false, "This test should cause a crash when CFG is enabled. We didn't " + - "observe a crash. This specific assertion should be redundant to a false assertion " + - "immediately prior to it. If it occurs alone, then something strange has occured " + - "and CFG status and this test should be investigated."); - } else { - // We crashed properly, clean up... - info("Content process is gone!"); - - // If we don't clean up the minidump, the harness will complain. - let dumpID = getCrashDumpId(subject); - - Assert.ok(dumpID == "", "There should NOT be a dumpID, but we have one: " + dumpID); - } - }); -}); From 9c34e0b91489b764d8303d03164158251addf59e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 14 Feb 2019 18:56:29 +0000 Subject: [PATCH 84/84] Bug 1512504 - Don't set __PRETTY_FUNCTION__ on clang-cl. r=froydnj clang-cl defines it on its own, although the value is slightly different from __FUNCSIG__ (it doesn't contain the ABI, which doesn't really matter). We've only been setting it this was on clang-cl by extension of setting it for msvc. Depends on D19616 Differential Revision: https://phabricator.services.mozilla.com/D19617 --HG-- extra : moz-landing-system : lando --- dom/media/systemservices/moz.build | 2 -- dom/media/webrtc/moz.build | 1 - media/webrtc/webrtc.mozbuild | 3 --- 3 files changed, 6 deletions(-) diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build index 9c77b46d3fe7..72efa2c86887 100644 --- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -49,8 +49,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': EXPORTS += ['OSXRunLoopSingleton.h'] if CONFIG['CC_TYPE'] == 'clang-cl': - DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' - # This is intended as a temporary workaround to enable building with VS2015. # media\webrtc\trunk\webrtc/base/criticalsection.h(59): warning C4312: # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size diff --git a/dom/media/webrtc/moz.build b/dom/media/webrtc/moz.build index 07d458a42b40..d8918515a77e 100644 --- a/dom/media/webrtc/moz.build +++ b/dom/media/webrtc/moz.build @@ -91,4 +91,3 @@ if CONFIG['CC_TYPE'] == 'clang-cl': '-wd4312', # This is intended as a temporary hack to support building with VS2015 # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size ] - DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' diff --git a/media/webrtc/webrtc.mozbuild b/media/webrtc/webrtc.mozbuild index c9d061de5b12..1009e88fca44 100644 --- a/media/webrtc/webrtc.mozbuild +++ b/media/webrtc/webrtc.mozbuild @@ -22,8 +22,5 @@ if CONFIG['MOZ_WEBRTC']: elif CONFIG['OS_TARGET'] == 'Android': DEFINES['WEBRTC_ANDROID'] = True - if CONFIG['CC_TYPE'] == 'clang-cl': - DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__' - if CONFIG['CC_TYPE'] in ('clang', 'gcc'): CXXFLAGS += ['-Wno-error=shadow']