|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
3 */ |
|
4 |
|
5 // Test how update window behaves when metadata ping times out |
|
6 // bug 965788 |
|
7 |
|
8 const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul"; |
|
9 |
|
10 const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; |
|
11 const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion"; |
|
12 |
|
13 Components.utils.import("resource://gre/modules/Promise.jsm"); |
|
14 |
|
15 let repo = {}; |
|
16 let ARContext = Components.utils.import("resource://gre/modules/addons/AddonRepository.jsm", repo); |
|
17 info("ARContext: " + Object.keys(ARContext).join(", ")); |
|
18 |
|
19 // Mock out the XMLHttpRequest factory for AddonRepository so |
|
20 // we can reply with a timeout |
|
21 let pXHRStarted = Promise.defer(); |
|
22 let oldXHRConstructor = ARContext.XHRequest; |
|
23 ARContext.XHRequest = function() { |
|
24 this._handlers = new Map(); |
|
25 this.mozBackgroundRequest = false; |
|
26 this.timeout = undefined; |
|
27 this.open = function(aMethod, aURI, aAsync) { |
|
28 this.method = aMethod; |
|
29 this.uri = aURI; |
|
30 this.async = aAsync; |
|
31 info("Opened XHR for " + aMethod + " " + aURI); |
|
32 }; |
|
33 this.overrideMimeType = function(aMimeType) { |
|
34 this.mimeType = aMimeType; |
|
35 }; |
|
36 this.addEventListener = function(aEvent, aHandler, aCapture) { |
|
37 this._handlers.set(aEvent, aHandler); |
|
38 }; |
|
39 this.send = function(aBody) { |
|
40 info("Send XHR for " + this.method + " " + this.uri + " handlers: " + [this._handlers.keys()].join(", ")); |
|
41 pXHRStarted.resolve(this); |
|
42 } |
|
43 }; |
|
44 |
|
45 |
|
46 // Returns promise{window}, resolves with a handle to the compatibility |
|
47 // check window |
|
48 function promise_open_compatibility_window(aInactiveAddonIds) { |
|
49 let deferred = Promise.defer(); |
|
50 // This will reset the longer timeout multiplier to 2 which will give each |
|
51 // test that calls open_compatibility_window a minimum of 60 seconds to |
|
52 // complete. |
|
53 requestLongerTimeout(100 /* XXX was 2 */); |
|
54 |
|
55 var variant = Cc["@mozilla.org/variant;1"]. |
|
56 createInstance(Ci.nsIWritableVariant); |
|
57 variant.setFromVariant(aInactiveAddonIds); |
|
58 |
|
59 // Cannot be modal as we want to interract with it, shouldn't cause problems |
|
60 // with testing though. |
|
61 var features = "chrome,centerscreen,dialog,titlebar"; |
|
62 var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. |
|
63 getService(Ci.nsIWindowWatcher); |
|
64 var win = ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant); |
|
65 |
|
66 win.addEventListener("load", function() { |
|
67 function page_shown(aEvent) { |
|
68 if (aEvent.target.pageid) |
|
69 info("Page " + aEvent.target.pageid + " shown"); |
|
70 } |
|
71 |
|
72 win.removeEventListener("load", arguments.callee, false); |
|
73 |
|
74 info("Compatibility dialog opened"); |
|
75 |
|
76 win.addEventListener("pageshow", page_shown, false); |
|
77 win.addEventListener("unload", function() { |
|
78 win.removeEventListener("unload", arguments.callee, false); |
|
79 win.removeEventListener("pageshow", page_shown, false); |
|
80 dump("Compatibility dialog closed\n"); |
|
81 }, false); |
|
82 |
|
83 deferred.resolve(win); |
|
84 }, false); |
|
85 return deferred.promise; |
|
86 } |
|
87 |
|
88 function promise_window_close(aWindow) { |
|
89 let deferred = Promise.defer(); |
|
90 aWindow.addEventListener("unload", function() { |
|
91 aWindow.removeEventListener("unload", arguments.callee, false); |
|
92 deferred.resolve(aWindow); |
|
93 }, false); |
|
94 return deferred.promise; |
|
95 } |
|
96 |
|
97 // Start the compatibility update dialog, but use the mock XHR to respond with |
|
98 // a timeout |
|
99 add_task(function* amo_ping_timeout() { |
|
100 Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); |
|
101 let compatWindow = yield promise_open_compatibility_window([]); |
|
102 |
|
103 let xhr = yield pXHRStarted.promise; |
|
104 is(xhr.timeout, 30000, "XHR request should have 30 second timeout"); |
|
105 ok(xhr._handlers.has("timeout"), "Timeout handler set on XHR"); |
|
106 // call back the timeout handler |
|
107 xhr._handlers.get("timeout")(); |
|
108 |
|
109 // Put the old XHR constructor back |
|
110 ARContext.XHRequest = oldXHRConstructor; |
|
111 // The window should close without further interaction |
|
112 yield promise_window_close(compatWindow); |
|
113 }); |