Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 4 | */ |
michael@0 | 5 | |
michael@0 | 6 | /* General MAR File Download Tests */ |
michael@0 | 7 | |
michael@0 | 8 | const INC_CONTRACT_ID = "@mozilla.org/network/incremental-download;1"; |
michael@0 | 9 | |
michael@0 | 10 | var gIncrementalDownloadClassID, gIncOldFactory; |
michael@0 | 11 | // gIncrementalDownloadErrorType is used to loop through each of the connection |
michael@0 | 12 | // error types in the Mock incremental downloader. |
michael@0 | 13 | var gIncrementalDownloadErrorType = 0; |
michael@0 | 14 | |
michael@0 | 15 | var gNextRunFunc; |
michael@0 | 16 | var gExpectedStatusResult; |
michael@0 | 17 | |
michael@0 | 18 | function run_test() { |
michael@0 | 19 | setupTestCommon(); |
michael@0 | 20 | |
michael@0 | 21 | logTestInfo("testing mar downloads, mar hash verification, and " + |
michael@0 | 22 | "mar download interrupted recovery"); |
michael@0 | 23 | |
michael@0 | 24 | Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false); |
michael@0 | 25 | // The HTTP server is only used for the mar file downloads since it is slow |
michael@0 | 26 | start_httpserver(); |
michael@0 | 27 | setUpdateURLOverride(gURLData + "update.xml"); |
michael@0 | 28 | // The mock XMLHttpRequest is MUCH faster |
michael@0 | 29 | overrideXHR(callHandleEvent); |
michael@0 | 30 | standardInit(); |
michael@0 | 31 | do_execute_soon(run_test_pt1); |
michael@0 | 32 | } |
michael@0 | 33 | |
michael@0 | 34 | // The HttpServer must be stopped before calling do_test_finished |
michael@0 | 35 | function finish_test() { |
michael@0 | 36 | stop_httpserver(doTestFinish); |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | function end_test() { |
michael@0 | 40 | cleanupMockIncrementalDownload(); |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | // Callback function used by the custom XMLHttpRequest implementation to |
michael@0 | 44 | // call the nsIDOMEventListener's handleEvent method for onload. |
michael@0 | 45 | function callHandleEvent() { |
michael@0 | 46 | gXHR.status = 400; |
michael@0 | 47 | gXHR.responseText = gResponseBody; |
michael@0 | 48 | try { |
michael@0 | 49 | var parser = AUS_Cc["@mozilla.org/xmlextras/domparser;1"]. |
michael@0 | 50 | createInstance(AUS_Ci.nsIDOMParser); |
michael@0 | 51 | gXHR.responseXML = parser.parseFromString(gResponseBody, "application/xml"); |
michael@0 | 52 | } catch (e) { |
michael@0 | 53 | } |
michael@0 | 54 | var e = { target: gXHR }; |
michael@0 | 55 | gXHR.onload(e); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | // Helper function for testing mar downloads that have the correct size |
michael@0 | 59 | // specified in the update xml. |
michael@0 | 60 | function run_test_helper_pt1(aMsg, aExpectedStatusResult, aNextRunFunc) { |
michael@0 | 61 | gUpdates = null; |
michael@0 | 62 | gUpdateCount = null; |
michael@0 | 63 | gStatusResult = null; |
michael@0 | 64 | gCheckFunc = check_test_helper_pt1_1; |
michael@0 | 65 | gNextRunFunc = aNextRunFunc; |
michael@0 | 66 | gExpectedStatusResult = aExpectedStatusResult; |
michael@0 | 67 | logTestInfo(aMsg, Components.stack.caller); |
michael@0 | 68 | gUpdateChecker.checkForUpdates(updateCheckListener, true); |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | function check_test_helper_pt1_1() { |
michael@0 | 72 | do_check_eq(gUpdateCount, 1); |
michael@0 | 73 | gCheckFunc = check_test_helper_pt1_2; |
michael@0 | 74 | var bestUpdate = gAUS.selectUpdate(gUpdates, gUpdateCount); |
michael@0 | 75 | var state = gAUS.downloadUpdate(bestUpdate, false); |
michael@0 | 76 | if (state == STATE_NONE || state == STATE_FAILED) |
michael@0 | 77 | do_throw("nsIApplicationUpdateService:downloadUpdate returned " + state); |
michael@0 | 78 | gAUS.addDownloadListener(downloadListener); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | function check_test_helper_pt1_2() { |
michael@0 | 82 | do_check_eq(gStatusResult, gExpectedStatusResult); |
michael@0 | 83 | gAUS.removeDownloadListener(downloadListener); |
michael@0 | 84 | gNextRunFunc(); |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | function setResponseBody(aHashFunction, aHashValue, aSize) { |
michael@0 | 88 | var patches = getRemotePatchString(null, null, |
michael@0 | 89 | aHashFunction, aHashValue, aSize); |
michael@0 | 90 | var updates = getRemoteUpdateString(patches); |
michael@0 | 91 | gResponseBody = getRemoteUpdatesXMLString(updates); |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | var newFactory = { |
michael@0 | 95 | createInstance: function(aOuter, aIID) { |
michael@0 | 96 | if (aOuter) |
michael@0 | 97 | throw Components.results.NS_ERROR_NO_AGGREGATION; |
michael@0 | 98 | return new IncrementalDownload().QueryInterface(aIID); |
michael@0 | 99 | }, |
michael@0 | 100 | lockFactory: function(aLock) { |
michael@0 | 101 | throw Components.results.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 102 | }, |
michael@0 | 103 | QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIFactory]) |
michael@0 | 104 | }; |
michael@0 | 105 | |
michael@0 | 106 | function initMockIncrementalDownload() { |
michael@0 | 107 | var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar); |
michael@0 | 108 | gIncrementalDownloadClassID = registrar.contractIDToCID(INC_CONTRACT_ID); |
michael@0 | 109 | gIncOldFactory = AUS_Cm.getClassObject(AUS_Cc[INC_CONTRACT_ID], |
michael@0 | 110 | AUS_Ci.nsIFactory); |
michael@0 | 111 | registrar.unregisterFactory(gIncrementalDownloadClassID, gIncOldFactory); |
michael@0 | 112 | var components = [IncrementalDownload]; |
michael@0 | 113 | registrar.registerFactory(gIncrementalDownloadClassID, "", |
michael@0 | 114 | INC_CONTRACT_ID, newFactory); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | function cleanupMockIncrementalDownload() { |
michael@0 | 118 | if (gIncOldFactory) { |
michael@0 | 119 | var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar); |
michael@0 | 120 | registrar.unregisterFactory(gIncrementalDownloadClassID, newFactory); |
michael@0 | 121 | registrar.registerFactory(gIncrementalDownloadClassID, "", |
michael@0 | 122 | INC_CONTRACT_ID, gIncOldFactory); |
michael@0 | 123 | } |
michael@0 | 124 | gIncOldFactory = null; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | /* This Mock incremental downloader is used to verify that connection |
michael@0 | 128 | * interrupts work correctly in updater code. The implementation of |
michael@0 | 129 | * the mock incremental downloader is very simple, it simply copies |
michael@0 | 130 | * the file to the destination location. |
michael@0 | 131 | */ |
michael@0 | 132 | |
michael@0 | 133 | function IncrementalDownload() { |
michael@0 | 134 | this.wrappedJSObject = this; |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | IncrementalDownload.prototype = { |
michael@0 | 138 | QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIIncrementalDownload]), |
michael@0 | 139 | |
michael@0 | 140 | /* nsIIncrementalDownload */ |
michael@0 | 141 | init: function(uri, file, chunkSize, intervalInSeconds) { |
michael@0 | 142 | this._destination = file; |
michael@0 | 143 | this._URI = uri; |
michael@0 | 144 | this._finalURI = uri; |
michael@0 | 145 | }, |
michael@0 | 146 | |
michael@0 | 147 | start: function(observer, ctxt) { |
michael@0 | 148 | var tm = Components.classes["@mozilla.org/thread-manager;1"]. |
michael@0 | 149 | getService(AUS_Ci.nsIThreadManager); |
michael@0 | 150 | // Do the actual operation async to give a chance for observers |
michael@0 | 151 | // to add themselves. |
michael@0 | 152 | tm.mainThread.dispatch(function() { |
michael@0 | 153 | this._observer = observer.QueryInterface(AUS_Ci.nsIRequestObserver); |
michael@0 | 154 | this._ctxt = ctxt; |
michael@0 | 155 | this._observer.onStartRequest(this, this.ctxt); |
michael@0 | 156 | let mar = getTestDirFile(FILE_SIMPLE_MAR); |
michael@0 | 157 | mar.copyTo(this._destination.parent, this._destination.leafName); |
michael@0 | 158 | var status = AUS_Cr.NS_OK |
michael@0 | 159 | switch (gIncrementalDownloadErrorType++) { |
michael@0 | 160 | case 0: |
michael@0 | 161 | status = AUS_Cr.NS_ERROR_NET_RESET; |
michael@0 | 162 | break; |
michael@0 | 163 | case 1: |
michael@0 | 164 | status = AUS_Cr.NS_ERROR_CONNECTION_REFUSED; |
michael@0 | 165 | break; |
michael@0 | 166 | case 2: |
michael@0 | 167 | status = AUS_Cr.NS_ERROR_NET_RESET; |
michael@0 | 168 | break; |
michael@0 | 169 | case 3: |
michael@0 | 170 | status = AUS_Cr.NS_OK; |
michael@0 | 171 | break; |
michael@0 | 172 | case 4: |
michael@0 | 173 | status = AUS_Cr.NS_ERROR_OFFLINE; |
michael@0 | 174 | // After we report offline, we want to eventually show offline |
michael@0 | 175 | // status being changed to online. |
michael@0 | 176 | var tm = Components.classes["@mozilla.org/thread-manager;1"]. |
michael@0 | 177 | getService(AUS_Ci.nsIThreadManager); |
michael@0 | 178 | tm.mainThread.dispatch(function() { |
michael@0 | 179 | Services.obs.notifyObservers(gAUS, |
michael@0 | 180 | "network:offline-status-changed", |
michael@0 | 181 | "online"); |
michael@0 | 182 | }, AUS_Ci.nsIThread.DISPATCH_NORMAL); |
michael@0 | 183 | break; |
michael@0 | 184 | } |
michael@0 | 185 | this._observer.onStopRequest(this, this._ctxt, status); |
michael@0 | 186 | }.bind(this), AUS_Ci.nsIThread.DISPATCH_NORMAL); |
michael@0 | 187 | }, |
michael@0 | 188 | |
michael@0 | 189 | get URI() { |
michael@0 | 190 | return this._URI; |
michael@0 | 191 | }, |
michael@0 | 192 | |
michael@0 | 193 | get currentSize() { |
michael@0 | 194 | throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 195 | }, |
michael@0 | 196 | |
michael@0 | 197 | get destination() { |
michael@0 | 198 | return this._destination; |
michael@0 | 199 | }, |
michael@0 | 200 | |
michael@0 | 201 | get finalURI() { |
michael@0 | 202 | return this._finalURI; |
michael@0 | 203 | }, |
michael@0 | 204 | |
michael@0 | 205 | get totalSize() { |
michael@0 | 206 | throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 207 | }, |
michael@0 | 208 | |
michael@0 | 209 | /* nsIRequest */ |
michael@0 | 210 | cancel: function(aStatus) { |
michael@0 | 211 | throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 212 | }, |
michael@0 | 213 | suspend: function() { |
michael@0 | 214 | throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 215 | }, |
michael@0 | 216 | isPending: function() { |
michael@0 | 217 | throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 218 | }, |
michael@0 | 219 | _loadFlags: 0, |
michael@0 | 220 | get loadFlags() { |
michael@0 | 221 | return this._loadFlags; |
michael@0 | 222 | }, |
michael@0 | 223 | set loadFlags(val) { |
michael@0 | 224 | this._loadFlags = val; |
michael@0 | 225 | }, |
michael@0 | 226 | |
michael@0 | 227 | _loadGroup: null, |
michael@0 | 228 | get loadGroup() { |
michael@0 | 229 | return this._loadGroup; |
michael@0 | 230 | }, |
michael@0 | 231 | set loadGroup(val) { |
michael@0 | 232 | this._loadGroup = val; |
michael@0 | 233 | }, |
michael@0 | 234 | |
michael@0 | 235 | _name: "", |
michael@0 | 236 | get name() { |
michael@0 | 237 | return this._name; |
michael@0 | 238 | }, |
michael@0 | 239 | |
michael@0 | 240 | _status: 0, |
michael@0 | 241 | get status() { |
michael@0 | 242 | return this._status; |
michael@0 | 243 | } |
michael@0 | 244 | } |
michael@0 | 245 | |
michael@0 | 246 | // Test disconnecting during an update |
michael@0 | 247 | function run_test_pt1() { |
michael@0 | 248 | initMockIncrementalDownload(); |
michael@0 | 249 | setResponseBody("MD5", MD5_HASH_SIMPLE_MAR); |
michael@0 | 250 | run_test_helper_pt1("mar download with connection interruption", |
michael@0 | 251 | AUS_Cr.NS_OK, run_test_pt2); |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | // Test disconnecting during an update |
michael@0 | 255 | function run_test_pt2() { |
michael@0 | 256 | gIncrementalDownloadErrorType = 0; |
michael@0 | 257 | Services.prefs.setIntPref(PREF_APP_UPDATE_SOCKET_ERRORS, 2); |
michael@0 | 258 | Services.prefs.setIntPref(PREF_APP_UPDATE_RETRY_TIMEOUT, 0); |
michael@0 | 259 | setResponseBody("MD5", MD5_HASH_SIMPLE_MAR); |
michael@0 | 260 | |
michael@0 | 261 | var expectedResult; |
michael@0 | 262 | if (IS_TOOLKIT_GONK) { |
michael@0 | 263 | // Gonk treats interrupted downloads differently. For gonk, if the state |
michael@0 | 264 | // is pending, this means that the download has completed and only the |
michael@0 | 265 | // staging needs to occur. So gonk will skip the download portion which |
michael@0 | 266 | // results in an NS_OK return. |
michael@0 | 267 | expectedResult = AUS_Cr.NS_OK; |
michael@0 | 268 | } else { |
michael@0 | 269 | expectedResult = AUS_Cr.NS_ERROR_NET_RESET; |
michael@0 | 270 | } |
michael@0 | 271 | run_test_helper_pt1("mar download with connection interruption without recovery", |
michael@0 | 272 | expectedResult, run_test_pt3); |
michael@0 | 273 | } |
michael@0 | 274 | |
michael@0 | 275 | // Test entering offline mode while downloading |
michael@0 | 276 | function run_test_pt3() { |
michael@0 | 277 | gIncrementalDownloadErrorType = 4; |
michael@0 | 278 | setResponseBody("MD5", MD5_HASH_SIMPLE_MAR); |
michael@0 | 279 | run_test_helper_pt1("mar download with offline mode", |
michael@0 | 280 | AUS_Cr.NS_OK, finish_test); |
michael@0 | 281 | } |