|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
3 */ |
|
4 |
|
5 // Tests the dialog open by the Options button for addons that provide a |
|
6 // custom chrome-like protocol for optionsURL. |
|
7 |
|
8 let CustomChromeProtocol = { |
|
9 scheme: "khrome", |
|
10 defaultPort: -1, |
|
11 protocolFlags: Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD | |
|
12 Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | |
|
13 Ci.nsIProtocolHandler.URI_NORELATIVE | |
|
14 Ci.nsIProtocolHandler.URI_NOAUTH, |
|
15 |
|
16 newURI: function CCP_newURI(aSpec, aOriginCharset, aBaseUri) { |
|
17 let uri = Cc["@mozilla.org/network/simple-uri;1"]. |
|
18 createInstance(Ci.nsIURI); |
|
19 uri.spec = aSpec; |
|
20 return uri; |
|
21 }, |
|
22 |
|
23 newChannel: function CCP_newChannel(aURI) { |
|
24 let url = "chrome:" + aURI.path; |
|
25 let ch = NetUtil.newChannel(url); |
|
26 ch.originalURI = aURI; |
|
27 return ch; |
|
28 }, |
|
29 |
|
30 allowPort: function CCP_allowPort(aPort, aScheme) { |
|
31 return false; |
|
32 }, |
|
33 |
|
34 QueryInterface: XPCOMUtils.generateQI([ |
|
35 Ci.nsIProtocolHandler |
|
36 ]), |
|
37 |
|
38 classID: Components.ID("{399cb2d1-05dd-4363-896f-63b78e008cf8}"), |
|
39 |
|
40 factory: { |
|
41 registrar: Components.manager.QueryInterface(Ci.nsIComponentRegistrar), |
|
42 |
|
43 register: function CCP_register() { |
|
44 this.registrar.registerFactory( |
|
45 CustomChromeProtocol.classID, |
|
46 "CustomChromeProtocol", |
|
47 "@mozilla.org/network/protocol;1?name=khrome", |
|
48 this |
|
49 ); |
|
50 }, |
|
51 |
|
52 unregister: function CCP_register() { |
|
53 this.registrar.unregisterFactory(CustomChromeProtocol.classID, this); |
|
54 }, |
|
55 |
|
56 // nsIFactory |
|
57 createInstance: function BNPH_createInstance(aOuter, aIID) { |
|
58 if (aOuter) { |
|
59 throw Components.Exception("Class does not allow aggregation", |
|
60 Components.results.NS_ERROR_NO_AGGREGATION); |
|
61 } |
|
62 return CustomChromeProtocol.QueryInterface(aIID); |
|
63 }, |
|
64 |
|
65 lockFactory: function BNPH_lockFactory(aLock) { |
|
66 throw Components.Exception("Function lockFactory is not implemented", |
|
67 Components.results.NS_ERROR_NOT_IMPLEMENTED); |
|
68 }, |
|
69 |
|
70 QueryInterface: XPCOMUtils.generateQI([ |
|
71 Ci.nsIFactory |
|
72 ]) |
|
73 } |
|
74 } |
|
75 |
|
76 function test() { |
|
77 waitForExplicitFinish(); |
|
78 requestLongerTimeout(2); |
|
79 |
|
80 info("Registering custom chrome-like protocol."); |
|
81 CustomChromeProtocol.factory.register(); |
|
82 registerCleanupFunction(function () CustomChromeProtocol.factory.unregister()); |
|
83 |
|
84 const ADDONS_LIST = [ |
|
85 { id: "test1@tests.mozilla.org", |
|
86 name: "Test add-on 1", |
|
87 optionsURL: CHROMEROOT + "addon_prefs.xul" }, |
|
88 { id: "test2@tests.mozilla.org", |
|
89 name: "Test add-on 2", |
|
90 optionsURL: (CHROMEROOT + "addon_prefs.xul").replace("chrome:", "khrome:") }, |
|
91 ]; |
|
92 |
|
93 var gProvider = new MockProvider(); |
|
94 gProvider.createAddons(ADDONS_LIST); |
|
95 |
|
96 open_manager("addons://list/extension", function(aManager) { |
|
97 let addonList = aManager.document.getElementById("addon-list"); |
|
98 let currentAddon; |
|
99 let instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply"); |
|
100 |
|
101 function getAddonByName(aName) { |
|
102 for (let addonItem of addonList.childNodes) { |
|
103 if (addonItem.hasAttribute("name") && |
|
104 addonItem.getAttribute("name") == aName) |
|
105 return addonItem; |
|
106 } |
|
107 return null; |
|
108 } |
|
109 |
|
110 function observer(aSubject, aTopic, aData) { |
|
111 switch (aTopic) { |
|
112 case "domwindowclosed": |
|
113 // Give the preference window a chance to finish closing before |
|
114 // closing the add-ons manager. |
|
115 waitForFocus(function () { |
|
116 test_next_addon(); |
|
117 }); |
|
118 break; |
|
119 case "domwindowopened": |
|
120 let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); |
|
121 waitForFocus(function () { |
|
122 // If the openDialog privileges are wrong a new browser window |
|
123 // will open, let the test proceed (and fail) rather than timeout. |
|
124 if (win.location != currentAddon.optionsURL && |
|
125 win.location != "chrome://browser/content/browser.xul") |
|
126 return; |
|
127 |
|
128 is(win.location, currentAddon.optionsURL, |
|
129 "The correct addon pref window should have opened"); |
|
130 |
|
131 let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor). |
|
132 getInterface(Ci.nsIWebNavigation). |
|
133 QueryInterface(Ci.nsIDocShellTreeItem).treeOwner. |
|
134 QueryInterface(Ci.nsIInterfaceRequestor). |
|
135 getInterface(Ci.nsIXULWindow).chromeFlags; |
|
136 ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME && |
|
137 (instantApply || chromeFlags & Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG), |
|
138 "Window was open as a chrome dialog."); |
|
139 |
|
140 win.close(); |
|
141 }, win); |
|
142 break; |
|
143 } |
|
144 } |
|
145 |
|
146 function test_next_addon() { |
|
147 currentAddon = ADDONS_LIST.shift(); |
|
148 if (!currentAddon) { |
|
149 Services.ww.unregisterNotification(observer); |
|
150 close_manager(aManager, finish); |
|
151 return; |
|
152 } |
|
153 |
|
154 info("Testing " + currentAddon.name); |
|
155 let addonItem = getAddonByName(currentAddon.name, addonList); |
|
156 let optionsBtn = |
|
157 aManager.document.getAnonymousElementByAttribute(addonItem, "anonid", |
|
158 "preferences-btn"); |
|
159 is(optionsBtn.hidden, false, "Prefs button should be visible.") |
|
160 |
|
161 addonList.ensureElementIsVisible(addonItem); |
|
162 EventUtils.synthesizeMouseAtCenter(optionsBtn, { }, aManager); |
|
163 } |
|
164 |
|
165 Services.ww.registerNotification(observer); |
|
166 test_next_addon(); |
|
167 }); |
|
168 |
|
169 } |