From 1151dd21cc2f732acf3d7295a00c2c9bcc28ac36 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 26 Mar 2018 13:35:04 -0400 Subject: [PATCH] Bug 1448398. Stop returning unwrapped Components.interfaces from SpecialPowers.Ci. r=kmag --- .../test/favicons/browser_favicon_load.js | 2 +- .../chrome/test_windowProxyDeadWrapper.html | 2 +- .../specialpowers/content/specialpowersAPI.js | 40 ++++++++++++++----- .../tests/mochitest/test_donottrack.html | 3 -- ...st_privatebrowsing_trackingprotection.html | 3 -- .../test_trackingprotection_bug1157081.html | 3 -- .../test_trackingprotection_bug1312515.html | 3 -- .../test_trackingprotection_whitelist.html | 3 -- 8 files changed, 33 insertions(+), 26 deletions(-) diff --git a/browser/base/content/test/favicons/browser_favicon_load.js b/browser/base/content/test/favicons/browser_favicon_load.js index 044d73a82f4a..0d6dd2a25319 100644 --- a/browser/base/content/test/favicons/browser_favicon_load.js +++ b/browser/base/content/test/favicons/browser_favicon_load.js @@ -27,7 +27,7 @@ let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); function clearAllImageCaches() { var tools = Cc["@mozilla.org/image/tools;1"] - .getService(SpecialPowers.Ci.imgITools); + .getService(Ci.imgITools); var imageCache = tools.getImgCacheForDocument(window.document); imageCache.clearCache(true); // true=chrome imageCache.clearCache(false); // false=content diff --git a/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html index b1dc6a251751..ff6e1328a633 100644 --- a/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html +++ b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html @@ -50,7 +50,7 @@ function go() { frame.remove(); TestUtils.topicObserved("outer-window-nuked", (subject, data) => { - let id = subject.QueryInterface(SpecialPowers.Ci.nsISupportsPRUint64).data; + let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data; return id == winID; }).then(() => { ok(checkDead(), "Expected a dead object wrapper"); diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js index 4e23cdd93da4..cacaf9a99855 100644 --- a/testing/specialpowers/content/specialpowersAPI.js +++ b/testing/specialpowers/content/specialpowersAPI.js @@ -180,6 +180,13 @@ function unwrapPrivileged(x) { return obj; } +function specialPowersHasInstance(value) { + // Because we return wrapped versions of this function, when it's called its + // wrapper will unwrap the "this" as well as the function itself. So our + // "this" is the unwrapped thing we started out with. + return value instanceof this; +} + function SpecialPowersHandler(wrappedObject) { this.wrappedObject = wrappedObject; } @@ -224,7 +231,16 @@ SpecialPowersHandler.prototype = { return this.wrappedObject; let obj = waiveXraysIfAppropriate(this.wrappedObject, prop); - return wrapIfUnwrapped(Reflect.get(obj, prop)); + let val = Reflect.get(obj, prop); + if (val === undefined && prop == Symbol.hasInstance) { + // Special-case Symbol.hasInstance to pass the hasInstance check on to our + // target. We only do this when the target doesn't have its own + // Symbol.hasInstance already. Once we get rid of JS engine class + // instance hooks (bug 1448218) and always use Symbol.hasInstance, we can + // remove this bit (bug 1448400). + return wrapPrivileged(specialPowersHasInstance); + } + return wrapIfUnwrapped(val); }, set(target, prop, val, receiver) { @@ -256,8 +272,19 @@ SpecialPowersHandler.prototype = { let obj = waiveXraysIfAppropriate(this.wrappedObject, prop); let desc = Reflect.getOwnPropertyDescriptor(obj, prop); - if (desc === undefined) + if (desc === undefined) { + if (prop == Symbol.hasInstance) { + // Special-case Symbol.hasInstance to pass the hasInstance check on to + // our target. We only do this when the target doesn't have its own + // Symbol.hasInstance already. Once we get rid of JS engine class + // instance hooks (bug 1448218) and always use Symbol.hasInstance, we + // can remove this bit (bug 1448400). + return { value: wrapPrivileged(specialPowersHasInstance), + writeable: true, configurable: true, enumerable: false }; + } + return undefined; + } // Transitively maintain the wrapper membrane. function wrapIfExists(key) { @@ -653,15 +680,10 @@ SpecialPowersAPI.prototype = { }, /* - * Convenient shortcuts to the standard Components abbreviations. Note that - * we don't SpecialPowers-wrap Components.interfaces, because it's available - * to untrusted content, and wrapping it confuses QI and identity checks. + * Convenient shortcuts to the standard Components abbreviations. */ get Cc() { return wrapPrivileged(this.getFullComponents().classes); }, - get Ci() { - return this.Components ? this.Components.interfaces - : Ci; -}, + get Ci() { return wrapPrivileged(this.getFullComponents().interfaces); }, get Cu() { return wrapPrivileged(this.getFullComponents().utils); }, get Cr() { return wrapPrivileged(this.Components.results); }, diff --git a/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html b/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html index 78d207d9f483..122743c4f1e0 100644 --- a/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html +++ b/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html @@ -14,9 +14,6 @@