Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /** |
michael@0 | 2 | * Dispatches |handler| to |element|, as if fired in response to |event|. |
michael@0 | 3 | */ |
michael@0 | 4 | function send(element, event, handler) { |
michael@0 | 5 | function unique_handler() { return handler.apply(this, arguments) } |
michael@0 | 6 | element.addEventListener(event, unique_handler, false); |
michael@0 | 7 | try { sendMouseEvent({ type: event }, element.id) } |
michael@0 | 8 | finally { element.removeEventListener(event, unique_handler, false) } |
michael@0 | 9 | } |
michael@0 | 10 | |
michael@0 | 11 | /** |
michael@0 | 12 | * Because it's not nice to leave popup windows open after the tests are |
michael@0 | 13 | * finished, we need a foolproof way to close some/all window.opened windows. |
michael@0 | 14 | */ |
michael@0 | 15 | (function(originalOpen) { |
michael@0 | 16 | var wins = []; |
michael@0 | 17 | (window.open = function() { |
michael@0 | 18 | var win = originalOpen.apply(window, arguments); |
michael@0 | 19 | if (win) |
michael@0 | 20 | wins[wins.length] = win; |
michael@0 | 21 | return win; |
michael@0 | 22 | }).close = function(n) { |
michael@0 | 23 | if (arguments.length < 1) |
michael@0 | 24 | n = wins.length; |
michael@0 | 25 | while (n --> 0) { |
michael@0 | 26 | var win = wins.pop(); |
michael@0 | 27 | if (win) win.close(); |
michael@0 | 28 | else break; |
michael@0 | 29 | } |
michael@0 | 30 | }; |
michael@0 | 31 | })(window.open); |
michael@0 | 32 | |
michael@0 | 33 | function _alter_helper(uri, fn) { |
michael@0 | 34 | var hash_splat = uri.split("#"), |
michael@0 | 35 | splat = hash_splat.shift().split("/"); |
michael@0 | 36 | fn(splat); |
michael@0 | 37 | hash_splat.unshift(splat.join("/")); |
michael@0 | 38 | return hash_splat.join("#"); |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | function alter_host(uri, host) { |
michael@0 | 42 | return _alter_helper(uri, function(splat) { |
michael@0 | 43 | splat.splice(2, 1, host); |
michael@0 | 44 | }); |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | function alter_file(uri, file) { |
michael@0 | 48 | return _alter_helper(uri, function(splat) { |
michael@0 | 49 | splat[splat.length - 1] = file; |
michael@0 | 50 | }); |
michael@0 | 51 | } |
michael@0 | 52 | |
michael@0 | 53 | (function() { |
michael@0 | 54 | |
michael@0 | 55 | var prefService = SpecialPowers.Cc["@mozilla.org/preferences-service;1"] |
michael@0 | 56 | .getService(SpecialPowers.Ci.nsIPrefService), |
michael@0 | 57 | pm = SpecialPowers.Cc["@mozilla.org/permissionmanager;1"] |
michael@0 | 58 | .getService(SpecialPowers.Ci.nsIPermissionManager), |
michael@0 | 59 | ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"] |
michael@0 | 60 | .getService(SpecialPowers.Ci.nsIIOService); |
michael@0 | 61 | |
michael@0 | 62 | ALLOW_ACTION = pm.ALLOW_ACTION; |
michael@0 | 63 | DENY_ACTION = pm.DENY_ACTION; |
michael@0 | 64 | UNKNOWN_ACTION = pm.UNKNOWN_ACTION; |
michael@0 | 65 | |
michael@0 | 66 | /** |
michael@0 | 67 | * This ridiculously over-engineered function makes an accessor function from |
michael@0 | 68 | * any given preference string. Such accessors may be passed as the first |
michael@0 | 69 | * parameter to the |hold| function defined below. |
michael@0 | 70 | */ |
michael@0 | 71 | makePrefAccessor = function(pref) { |
michael@0 | 72 | var splat = pref.split('.'), |
michael@0 | 73 | basePref = splat.pop(), |
michael@0 | 74 | branch, kind; |
michael@0 | 75 | |
michael@0 | 76 | try { |
michael@0 | 77 | branch = prefService.getBranch(splat.join('.') + '.'); |
michael@0 | 78 | } catch (x) { |
michael@0 | 79 | alert("Calling prefService.getBranch failed: " + |
michael@0 | 80 | "did you forget to enable UniversalXPConnect?"); |
michael@0 | 81 | throw x; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | switch (branch.getPrefType(basePref)) { |
michael@0 | 85 | case branch.PREF_STRING: kind = "CharPref"; break; |
michael@0 | 86 | case branch.PREF_INT: kind = "IntPref"; break; |
michael@0 | 87 | case branch.PREF_BOOL: kind = "BoolPref"; break; |
michael@0 | 88 | case branch.PREF_INVALID: kind = "ComplexValue"; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | return function(value) { |
michael@0 | 92 | var oldValue = branch['get' + kind](basePref); |
michael@0 | 93 | if (arguments.length > 0) |
michael@0 | 94 | branch['set' + kind](basePref, value); |
michael@0 | 95 | return oldValue; |
michael@0 | 96 | }; |
michael@0 | 97 | }; |
michael@0 | 98 | |
michael@0 | 99 | makePopupPrivAccessor = function(uri) { |
michael@0 | 100 | uri = ioService.newURI(uri, null, null); |
michael@0 | 101 | var principal = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"] |
michael@0 | 102 | .getService(SpecialPowers.Ci.nsIScriptSecurityManager) |
michael@0 | 103 | .getNoAppCodebasePrincipal(uri); |
michael@0 | 104 | |
michael@0 | 105 | return function(permission) { |
michael@0 | 106 | var old = pm.testPermissionFromPrincipal(principal, "popup"); |
michael@0 | 107 | if (arguments.length) { |
michael@0 | 108 | pm.removeFromPrincipal(principal, "popup"); |
michael@0 | 109 | pm.addFromPrincipal(principal, "popup", permission); |
michael@0 | 110 | } |
michael@0 | 111 | return old; |
michael@0 | 112 | }; |
michael@0 | 113 | }; |
michael@0 | 114 | |
michael@0 | 115 | })(); |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * This function takes an accessor function, a new value, and a callback |
michael@0 | 119 | * function. It assigns the new value to the accessor, saving the old value, |
michael@0 | 120 | * then calls the callback function with the new and old values. Before |
michael@0 | 121 | * returning, |hold| sets the accessor back to the old value, even if the |
michael@0 | 122 | * callback function misbehaved (i.e., threw). |
michael@0 | 123 | * |
michael@0 | 124 | * For sanity's sake, |hold| also ensures that the accessor still has the new |
michael@0 | 125 | * value at the time the old value is reassigned. The accessor's value might |
michael@0 | 126 | * have changed to something entirely different during the execution of the |
michael@0 | 127 | * callback function, but it must have changed back. |
michael@0 | 128 | * |
michael@0 | 129 | * Without such a mechanism it would be very difficult to verify that these |
michael@0 | 130 | * tests leave the browser's preferences/privileges as they were originally. |
michael@0 | 131 | */ |
michael@0 | 132 | function hold(accessor, value, body) { |
michael@0 | 133 | var old_value = accessor(value); |
michael@0 | 134 | try { return body(value, old_value) } |
michael@0 | 135 | finally { |
michael@0 | 136 | old_value = accessor(old_value); |
michael@0 | 137 | if (old_value !== value) |
michael@0 | 138 | throw [accessor, value, old_value]; |
michael@0 | 139 | } |
michael@0 | 140 | } |