~didrocks/webapps-applications/port-python3

« back to all changes in this revision

Viewing changes to common/webapp.js

  • Committer: Tarmac
  • Author(s): Justin McPherson
  • Date: 2014-01-22 18:46:36 UTC
  • mfrom: (571.3.2 webapp-support)
  • Revision ID: tarmac-20140122184636-n9ae8z4isdg89pg1
Added a WebApp class for declaratively specifying a webapp.

Approved by Alexandre Abreu, PS Jenkins bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
function WebApp(appInfo, callbacks) {
 
3
    this._init(appInfo, callbacks);
 
4
}
 
5
 
 
6
WebApp.match = { FIRST: 0, ANY: 1, ALL: 2 };
 
7
WebApp.prototype = {
 
8
    _init: function (appInfo, callbacks) {
 
9
        this._appInfo = appInfo;
 
10
        this._totalWeight = 0.0;
 
11
        this._validItems = [];
 
12
        this._callbacks = callbacks;
 
13
        this._retries = 0;
 
14
    },
 
15
 
 
16
    _unityLoaded: function () {
 
17
        try {
 
18
            var i, nodeFunction = function () {
 
19
                return document.evaluate("(" + this.node + ")[" + this.index + "]",
 
20
                                         document,
 
21
                                         null,
 
22
                                         XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
 
23
                                         null).snapshotItem(0);
 
24
            };
 
25
 
 
26
            for (i = 0; i < this._validItems.length; i++) {
 
27
                var item = this._validItems[i];
 
28
                if (item.install !== undefined) {
 
29
                    item.install(nodeFunction.bind(item));
 
30
                }
 
31
            }
 
32
        } catch (e) {
 
33
            console.log("Exception attempting item install = " + e);
 
34
        }
 
35
 
 
36
        var indicatorsController = new Indicators(function () {
 
37
                return this._unityCallback();
 
38
            }.bind(this));
 
39
 
 
40
        if (this._callbacks.loaded !== undefined) {
 
41
            this._reportInfo("calling loaded callback");
 
42
            this._callbacks.loaded(indicatorsController);
 
43
        }
 
44
    },
 
45
 
 
46
    setupPage: function () {
 
47
        function nodeValue(node) {
 
48
            if (typeof node === 'string') {
 
49
                var resultSet = document.evaluate(node,
 
50
                                                  document,
 
51
                                                  null,
 
52
                                                  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
 
53
                                                  null);
 
54
                var i, arrayized = [];
 
55
                for (i = 0; i < resultSet.snapshotLength; i++) {
 
56
                    arrayized.push(resultSet.snapshotItem(i));
 
57
                }
 
58
                return arrayized;
 
59
            } else if (typeof node === 'function') {
 
60
                return node();
 
61
            }
 
62
 
 
63
            return [];
 
64
        }
 
65
 
 
66
        // Can we skip?
 
67
        if (this._totalWeight > 0.0) {
 
68
            if (this._appInfo.validator(this._totalWeight)) {
 
69
                return true;
 
70
            }
 
71
            this._totalWeight = 0.0;
 
72
        }
 
73
 
 
74
        var pageData = {};
 
75
 
 
76
        var i = 0, j = 0, k = 0;
 
77
 
 
78
        // Try and find login
 
79
        // Always collect login if available
 
80
        if (this._appInfo.login !== undefined) {
 
81
            var loginTests = this._appInfo.login;
 
82
            for (i = 0; i < loginTests.nodes.length; i++) {
 
83
                var nodeTest = {
 
84
                    name: loginTests.name,
 
85
                    query: loginTests.nodes[i],
 
86
                    validator: loginTests.validator,
 
87
                    fragment: loginTests.fragment,
 
88
                    value: loginTests.value
 
89
                };
 
90
 
 
91
                var loginNode = validatedNode(nodeTest);
 
92
                if (loginNode !== null) {
 
93
                    this._login = validatedNodeValue(nodeTest, loginNode);
 
94
                }
 
95
            }
 
96
            if (this._login === undefined) {
 
97
                if (this._shouldRetry()) {
 
98
                    this._reportWarning("Failed to find login will retry");
 
99
                    return false;
 
100
                } else {
 
101
                    this._reportError("Unable to obtain login information");
 
102
                    return true;
 
103
                }
 
104
            } else {
 
105
                this._reportInfo("Found login: " + this._login);
 
106
            }
 
107
        }
 
108
 
 
109
        // Check all items
 
110
        var itemsTests = this._appInfo.items;
 
111
        var valueFunction = function () {
 
112
                var result = document.evaluate("(" + this.node + ")[" + this.index + "]",
 
113
                                                 document,
 
114
                                                 null,
 
115
                                                 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
 
116
 
 
117
                return this.nativeValue(result);
 
118
            };
 
119
 
 
120
        for (i = 0; i < itemsTests.length; i++) {
 
121
            var found = false;
 
122
            var item = itemsTests[i];
 
123
 
 
124
            for (j = 0; j < item.nodes.length; j++) {
 
125
                var nodeSet = nodeValue(item.nodes[j]);
 
126
 
 
127
                for (k = 0; k < nodeSet.length; k++) {
 
128
                    var node = nodeSet[k];
 
129
 
 
130
                    if (item.validator(node)) {
 
131
                        if (item.weight) {
 
132
                            this._totalWeight += item.weight;
 
133
                        }
 
134
 
 
135
                        var itemData = {
 
136
                            name: item.name,
 
137
                            node: item.nodes[j],
 
138
                            index: k + 1
 
139
                        };
 
140
 
 
141
                        if (item.value !== undefined) {
 
142
                            itemData.nativeValue = item.value;
 
143
                            itemData.value = valueFunction;
 
144
                        }
 
145
 
 
146
                        if (item.install !== undefined) {
 
147
                            itemData.install = item.install;
 
148
                        }
 
149
 
 
150
                        // Save the node 
 
151
                        this._validItems.push(itemData);
 
152
                        this._reportInfo("Found item - " + item.name);
 
153
                        found = true;
 
154
 
 
155
                        if (item.match === WebApp.match.FIRST || item.match === WebApp.match.ANY) {
 
156
                            break;
 
157
                        }
 
158
                    }
 
159
                }
 
160
                if (found) {
 
161
                    break;
 
162
                }
 
163
            }
 
164
 
 
165
            if (!found) {
 
166
                if (item.fragment !== undefined) {
 
167
                    var fragmentOk, resultSet, testNode = document.createElement("div");
 
168
                    testNode.innerHTML = item.fragment;
 
169
                    resultSet = document.evaluate(item.nodes[0], testNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
 
170
                    fragmentOk = resultSet.snapshotLength > 0 && item.validator(resultSet.snapshotItem(0));
 
171
                    this._reportWarning("Item not found " + item.name + " fragment check " + (fragmentOk ? "OK" : "failed"));
 
172
                } else {
 
173
                    this._reportWarning("Item not found: " + item.name);
 
174
                }
 
175
            }
 
176
        }
 
177
 
 
178
        // Should we continue?
 
179
        if (!this._appInfo.validator(this._totalWeight)) {
 
180
            if (this._shouldRetry()) {
 
181
                this._reportWarning("Did not retrieve enough information to instantiate app, will retry");
 
182
                return false;
 
183
            } else {
 
184
                this._reportFailure(this._totalWeght);
 
185
                return true;
 
186
            }
 
187
        }
 
188
 
 
189
        // Build Pagedata for Unity.init()
 
190
        pageData.name = this._valueFromField(this._appInfo.name);
 
191
        pageData.iconUrl = this._valueFromField(this._appInfo.iconUrl);
 
192
        pageData.homepage = this._valueFromField(this._appInfo.homepage);
 
193
        pageData.domain = this._valueFromField(this._appInfo.domain);
 
194
        pageData.login = this._login;
 
195
        pageData.onInit = function () { this._unityLoaded(); }.bind(this);
 
196
 
 
197
        if (this._callbacks.success !== undefined) {
 
198
            this._reportInfo("calling success callback");
 
199
            this._callbacks.success(pageData);
 
200
        }
 
201
 
 
202
        return true;
 
203
    },
 
204
 
 
205
    _unityCallback: function () {
 
206
        // Collect all values
 
207
        var indicators = [];
 
208
        var i = 0;
 
209
 
 
210
        for (i = 0; i < this._validItems.length; i++) {
 
211
            var item = this._validItems[i];
 
212
 
 
213
            if (item.value !== undefined) {
 
214
                indicators.push(item.value());
 
215
            }
 
216
        }
 
217
 
 
218
        return indicators;
 
219
    },
 
220
 
 
221
    _valueFromField: function (value) {
 
222
        // Field can either be a value or a function to compute the value
 
223
        if (typeof value === 'function') {
 
224
            return value();
 
225
        }
 
226
        return value;
 
227
    },
 
228
 
 
229
    _reportInfo: function (msg) {
 
230
        if (this._callbacks.report) {
 
231
            this._callbacks.report("REPORT: INFO: " + msg);
 
232
        }
 
233
    },
 
234
 
 
235
    _reportWarning: function (msg) {
 
236
        if (this._callbacks.report) {
 
237
            this._callbacks.report("REPORT: WARNING: " + msg);
 
238
        }
 
239
    },
 
240
 
 
241
    _reportError: function (msg) {
 
242
        if (this._callbacks.report) {
 
243
            this._callbacks.report("REPORT: ERROR: " + msg);
 
244
        }
 
245
    },
 
246
 
 
247
    _reportFailure: function (weight) {
 
248
        if (this._callbacks.report) {
 
249
            this._callbacks.report("REPORT: ERROR: Failed to pass sufficient tests to continue " + weight);
 
250
        }
 
251
    },
 
252
 
 
253
    _shouldRetry: function () {
 
254
        if (this._appInfo.maxRetries !== undefined) {
 
255
            return this._retries++ < this._appInfo.maxRetries;
 
256
        }
 
257
        return true;
 
258
    }
 
259
};
 
260
 
 
261
 
 
262