|
1 <?xml version="1.0"?> |
|
2 <!-- This Source Code Form is subject to the terms of the Mozilla Public |
|
3 - License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
|
5 |
|
6 |
|
7 <!DOCTYPE bindings SYSTEM "chrome://mozapps/locale/update/updates.dtd"> |
|
8 |
|
9 <bindings id="updatesBindings" |
|
10 xmlns="http://www.mozilla.org/xbl" |
|
11 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
12 xmlns:xbl="http://www.mozilla.org/xbl"> |
|
13 |
|
14 <binding id="remotecontent"> |
|
15 <content> |
|
16 <xul:vbox flex="1" class="loadingBox"> |
|
17 <xul:hbox align="start"> |
|
18 <xul:image class="remoteLoadingThrobber" xbl:inherits="state"/> |
|
19 <xul:vbox flex="1"> |
|
20 <xul:description flex="1" class="remoteLoadingMessage" crop="right"/> |
|
21 </xul:vbox> |
|
22 </xul:hbox> |
|
23 </xul:vbox> |
|
24 <xul:vbox flex="1"> |
|
25 <xul:browser class="remoteContent" type="content" disablehistory="true" |
|
26 flex="1"/> |
|
27 </xul:vbox> |
|
28 <xul:stringbundle anonid="strings" |
|
29 src="chrome://mozapps/locale/update/updates.properties"/> |
|
30 </content> |
|
31 <implementation> |
|
32 <constructor><![CDATA[ |
|
33 // just to be safe, turn off js, auth, plugins, and subframes |
|
34 var docShell = this._content.docShell; |
|
35 docShell.allowJavascript = false; |
|
36 docShell.allowAuth = false; |
|
37 docShell.allowPlugins = false; |
|
38 //allow redirects |
|
39 //docShell.allowMetaRedirects = false; |
|
40 docShell.allowSubframes = false; |
|
41 //allow images |
|
42 //docShell.allowImages = false; |
|
43 ]]></constructor> |
|
44 |
|
45 <destructor><![CDATA[ |
|
46 // clean up the listener but you may not have one if you never showed |
|
47 // the page with a <remotecontent> element |
|
48 if (this._remoteProgressListener) |
|
49 this._content.webProgress |
|
50 .removeProgressListener(this._remoteProgressListener); |
|
51 ]]></destructor> |
|
52 |
|
53 <field name="_message"> |
|
54 document.getAnonymousElementByAttribute(this, "class", "remoteLoadingMessage"); |
|
55 </field> |
|
56 <field name="_content"> |
|
57 document.getAnonymousElementByAttribute(this, "class", "remoteContent"); |
|
58 </field> |
|
59 <field name="_strings"> |
|
60 document.getAnonymousElementByAttribute(this, "anonid", "strings"); |
|
61 </field> |
|
62 |
|
63 <field name="update_name">null</field> |
|
64 <field name="update_version">null</field> |
|
65 <field name="_remoteProgressListener">null</field> |
|
66 |
|
67 <method name="_setMessageValue"> |
|
68 <parameter name="value"/> |
|
69 <body><![CDATA[ |
|
70 while (this._message.hasChildNodes()) |
|
71 this._message.removeChild(this._message.firstChild); |
|
72 this._message.appendChild(document.createTextNode(value)); |
|
73 ]]></body> |
|
74 </method> |
|
75 |
|
76 <method name="onError"> |
|
77 <body><![CDATA[ |
|
78 this.setAttribute("selectedIndex", "0"); |
|
79 |
|
80 var errorPropertyName = this.getAttribute("id") + "NotFound"; |
|
81 var statusText = this._strings.getFormattedString(errorPropertyName, |
|
82 [this.update_name]); |
|
83 this._setMessageValue(statusText); |
|
84 this.setAttribute("state", "error"); |
|
85 var e = document.createEvent("Events"); |
|
86 e.initEvent("load", false, true); |
|
87 this.dispatchEvent(e); |
|
88 ]]></body> |
|
89 </method> |
|
90 |
|
91 <method name="onLoad"> |
|
92 <body><![CDATA[ |
|
93 var doc = this._content.contentDocument; |
|
94 var type = this.getAttribute("remotetype"); |
|
95 if (!doc.body.hasAttribute(type)) { |
|
96 this.onError(); |
|
97 return; |
|
98 } |
|
99 // The remote html can tell us to zoom out the page if the page |
|
100 // will create scrollbars by adding a zoomOutToFit attribute to the |
|
101 // body of the billboard's html. Since zooming out will not always |
|
102 // remove the scrollbars even though the page fits in the client |
|
103 // region after zooming out the web page should hide the scrollbar(s) |
|
104 // using css. If you choose to use zoomOutToFit you should also verify |
|
105 // it is working the way you expect it to with the billboard you have |
|
106 // created. Possible values for zoomOutToFit are: |
|
107 // both: zoom out if the width or height is greater than the client |
|
108 // region. |
|
109 // height: zoom out if the height is greater than the client region. |
|
110 // width: zoom out if the width is greater than the client region. |
|
111 if (doc.body.hasAttribute("zoomOutToFit")) { |
|
112 let zoomAdjustWidth = 1; |
|
113 let zoomAdjustHeight = 1; |
|
114 let zoomOutType = doc.body.getAttribute("zoomOutToFit"); |
|
115 if ((zoomOutType == "both" || zoomOutType == "width") && |
|
116 doc.width > this.clientWidth) |
|
117 zoomAdjustWidth = Math.floor((this.clientWidth / doc.width) * 100) * .01; |
|
118 |
|
119 if ((zoomOutType == "both" || zoomOutType == "height") && |
|
120 doc.height > this.clientHeight) |
|
121 zoomAdjustHeight = Math.floor((this.clientHeight / doc.height) * 100) * .01; |
|
122 |
|
123 var zoomAdjust = zoomAdjustWidth < zoomAdjustHeight ? zoomAdjustWidth |
|
124 : zoomAdjustHeight; |
|
125 if (zoomAdjust < 1) |
|
126 this._content.markupDocumentViewer.fullZoom = zoomAdjust; |
|
127 } |
|
128 |
|
129 this.setAttribute("selectedIndex", "1"); |
|
130 this.setAttribute("state", "loaded"); |
|
131 |
|
132 var e = document.createEvent("Events"); |
|
133 e.initEvent("load", false, true); |
|
134 this.dispatchEvent(e); |
|
135 ]]></body> |
|
136 </method> |
|
137 |
|
138 <method name="onStart"> |
|
139 <body><![CDATA[ |
|
140 this.setAttribute("selectedIndex", "0"); |
|
141 |
|
142 this.setAttribute("state", "loading"); |
|
143 var loadingPropertyName = this.getAttribute("id") + "Downloading"; |
|
144 this._setMessageValue(this._strings.getFormattedString( |
|
145 loadingPropertyName, [this.update_name, this.update_version])); |
|
146 ]]></body> |
|
147 </method> |
|
148 |
|
149 <property name="url"> |
|
150 <getter><![CDATA[ |
|
151 return this.getAttribute("url"); |
|
152 ]]></getter> |
|
153 <setter><![CDATA[ |
|
154 if (this._remoteProgressListener) |
|
155 this._content.webProgress |
|
156 .removeProgressListener(this._remoteProgressListener); |
|
157 |
|
158 var self = this; |
|
159 |
|
160 this._remoteProgressListener = { |
|
161 QueryInterface: function(aIID) |
|
162 { |
|
163 if (aIID.equals(Components.interfaces.nsIWebProgressListener) || |
|
164 aIID.equals(Components.interfaces.nsISupportsWeakReference) || |
|
165 aIID.equals(Components.interfaces.nsISupports)) |
|
166 return this; |
|
167 throw Components.results.NS_NOINTERFACE; |
|
168 }, |
|
169 onLocationChange: function() {}, |
|
170 onProgressChange: function() {}, |
|
171 onStatusChange: function() {}, |
|
172 onSecurityChange: function() {}, |
|
173 onStateChange: function(aWebProgress, aRequest, |
|
174 aStateFlags, aStatus) |
|
175 { |
|
176 if (!aRequest) |
|
177 return; |
|
178 |
|
179 const nsIWebProgressListener = |
|
180 Components.interfaces.nsIWebProgressListener; |
|
181 |
|
182 if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) |
|
183 { |
|
184 if (aStateFlags & nsIWebProgressListener.STATE_START) |
|
185 self.onStart(); |
|
186 else if (aStateFlags & nsIWebProgressListener.STATE_STOP) |
|
187 { |
|
188 const nsIHttpChannel = Components.interfaces.nsIHttpChannel; |
|
189 try { |
|
190 var channel = aRequest.QueryInterface(nsIHttpChannel); |
|
191 if (channel.requestSucceeded) |
|
192 { |
|
193 // if we get here, the load was OK, report success |
|
194 self.onLoad(); |
|
195 return; |
|
196 } |
|
197 } |
|
198 catch (ex) |
|
199 { |
|
200 // the channel.requestSucceeded can throw |
|
201 // NS_ERROR_NOT_AVAILABLE if you can't reach the server |
|
202 // so we treat that as an error |
|
203 } |
|
204 |
|
205 // everything else (like a 404) is an error |
|
206 self.onError(); |
|
207 } |
|
208 } |
|
209 } |
|
210 } |
|
211 |
|
212 this._content.webProgress |
|
213 .addProgressListener(this._remoteProgressListener, |
|
214 Components.interfaces.nsIWebProgress.NOTIFY_ALL); |
|
215 |
|
216 // load the url now that the listener is registered |
|
217 this._content.setAttribute("src", val); |
|
218 ]]></setter> |
|
219 </property> |
|
220 |
|
221 <property name="testFileUrl"> |
|
222 <getter><![CDATA[ |
|
223 return this.getAttribute("testFileUrl"); |
|
224 ]]></getter> |
|
225 <setter><![CDATA[ |
|
226 this._content.setAttribute("src", val); |
|
227 this.onLoad() |
|
228 ]]></setter> |
|
229 </property> |
|
230 |
|
231 <method name="stopDownloading"> |
|
232 <body><![CDATA[ |
|
233 this._content.stop(); |
|
234 ]]></body> |
|
235 </method> |
|
236 </implementation> |
|
237 </binding> |
|
238 |
|
239 <binding id="updateheader" extends="chrome://global/content/bindings/wizard.xml#wizard-header"> |
|
240 <resources> |
|
241 <stylesheet src="chrome://global/skin/wizard.css"/> |
|
242 </resources> |
|
243 <content> |
|
244 <xul:hbox class="wizard-header update-header" flex="1"> |
|
245 <xul:vbox class="wizard-header-box-1"> |
|
246 <xul:vbox class="wizard-header-box-text"> |
|
247 <xul:label class="wizard-header-label" xbl:inherits="value=label"/> |
|
248 </xul:vbox> |
|
249 </xul:vbox> |
|
250 </xul:hbox> |
|
251 </content> |
|
252 </binding> |
|
253 |
|
254 <binding id="update" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> |
|
255 <content> |
|
256 <xul:hbox> |
|
257 <xul:label class="update-name" xbl:inherits="value=name" flex="1" crop="right"/> |
|
258 <xul:label xbl:inherits="href=detailsURL,hidden=hideDetailsURL" class="text-link" |
|
259 value="&update.details.label;"/> |
|
260 </xul:hbox> |
|
261 <xul:label class="update-type" xbl:inherits="value=type"/> |
|
262 <xul:grid> |
|
263 <xul:columns> |
|
264 <xul:column class="update-label-column"/> |
|
265 <xul:column flex="1"/> |
|
266 </xul:columns> |
|
267 <xul:rows> |
|
268 <xul:row> |
|
269 <xul:label class="update-installedOn-label">&update.installedOn.label;</xul:label> |
|
270 <xul:label class="update-installedOn-value" xbl:inherits="value=installDate" flex="1" crop="right"/> |
|
271 </xul:row> |
|
272 <xul:row> |
|
273 <xul:label class="update-status-label">&update.status.label;</xul:label> |
|
274 <xul:description class="update-status-value" flex="1"/> |
|
275 </xul:row> |
|
276 </xul:rows> |
|
277 </xul:grid> |
|
278 </content> |
|
279 <implementation> |
|
280 <property name="name" |
|
281 onget="return this.getAttribute('name');" |
|
282 onset="this.setAttribute('name', val); return val;"/> |
|
283 <property name="detailsURL" |
|
284 onget="return this.getAttribute('detailsURL');" |
|
285 onset="this.setAttribute('detailsURL', val); return val;"/> |
|
286 <property name="installDate" |
|
287 onget="return this.getAttribute('installDate');" |
|
288 onset="this.setAttribute('installDate', val); return val;"/> |
|
289 <property name="type" |
|
290 onget="return this.getAttribute('type');" |
|
291 onset="this.setAttribute('type', val); return val;"/> |
|
292 <property name="hideDetailsURL" |
|
293 onget="return this.getAttribute('hideDetailsURL');" |
|
294 onset="this.setAttribute('hideDetailsURL', val); return val;"/> |
|
295 <property name="status" |
|
296 onget="return this.getAttribute('status');"> |
|
297 <setter><![CDATA[ |
|
298 this.setAttribute("status", val); |
|
299 var field = document.getAnonymousElementByAttribute(this, "class", "update-status-value"); |
|
300 while (field.hasChildNodes()) |
|
301 field.removeChild(field.firstChild); |
|
302 field.appendChild(document.createTextNode(val)); |
|
303 return val; |
|
304 ]]></setter> |
|
305 </property> |
|
306 </implementation> |
|
307 </binding> |
|
308 </bindings> |
|
309 |