Completed
Push — master ( b8372c...d4a4bf )
by Elbert
01:15
created

w.driver.init   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 9.4285
1
/**
2
 * WebExtension driver
3
 */
4
5
(function() {
6
	if ( wappalyzer == null ) {
0 ignored issues
show
Bug introduced by
The variable wappalyzer seems to be never declared. If this is a global, consider adding a /** global: wappalyzer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
7
		return;
8
	}
9
10
	var w = wappalyzer,
11
		firstRun = false,
12
		upgraded = false,
13
		tab,
14
		tabCache = {},
15
		headersCache = {};
16
17
	w.driver = {
18
		timeout: 1000,
19
20
		/**
21
		 * Log messages to console
22
		 */
23
		log: function(args) {
24
			console.log('[wappalyzer ' + args.type + '] ' + args.message);
1 ignored issue
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
25
		},
26
27
		/**
28
		 * Get a value from localStorage
29
		 */
30
		getOption: function(name, defaultValue, callback) {
31
			browser.storage.local.get(name).then(function(item) {
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
32
				callback(item.hasOwnProperty(name) ? item[name] : defaultValue);
33
			});
34
		},
35
36
		/**
37
		 * Set a value in localStorage
38
		 */
39
		setOption: function(name, value) {
40
			var option = {};
41
42
			option[name] = value;
43
44
			browser.storage.local.set(option);
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
45
		},
46
47
		/**
48
		 * Initialize
49
		 */
50
		init: function() {
51
			w.log('init');
52
53
			// Load apps.json
54
			var xhr = new XMLHttpRequest();
0 ignored issues
show
Bug introduced by
The variable XMLHttpRequest seems to be never declared. If this is a global, consider adding a /** global: XMLHttpRequest */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
55
56
			xhr.open('GET', 'apps.json', true);
57
58
			xhr.overrideMimeType('application/json');
59
60
			xhr.onload = function() {
61
				var json = JSON.parse(xhr.responseText);
62
63
				w.categories = json.categories;
64
				w.apps       = json.apps;
65
66
				w.driver.categoryOrder = Object.keys(w.categories).sort(function(a, b) {
67
					return w.categories[a].priority - w.categories[b].priority;
68
				});
69
			};
70
71
			xhr.send(null);
72
73
			// Version check
74
			try {
75
				var version = browser.runtime.getManifest().version;
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
76
77
				w.driver.getOption('version', null, function(previousVersion) {
78
					if ( previousVersion === null ) {
79
						w.driver.goToURL({
80
						 	url: w.config.websiteURL + 'installed'
81
						});
82
					} else if ( version !== previousVersion ) {
83
						w.driver.getOption('upgradeMessage', true, function(upgradeMessage) {
84
							if ( upgradeMessage ) {
85
								w.driver.goToURL({
86
									url: w.config.websiteURL + 'upgraded',
87
									background: true
88
								});
89
							}
90
						});
91
					}
92
93
					w.driver.setOption('version', version);
94
				});
95
			} catch(e) {
96
				// Do nothing
97
			}
98
99
      if ( typeof chrome === 'undefined' ) {
0 ignored issues
show
Bug introduced by
The variable chrome seems to be never declared. If this is a global, consider adding a /** global: chrome */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
100
        browser.runtime.onMessage.addListener(w.driver.onMessage);
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
101
      } else {
102
        chrome.runtime.onMessage.addListener(w.driver.onMessage);
103
      }
104
105
			var callback = function(tabs) {
106
				tabs.forEach(function(tab) {
107
					if ( tab.url.match(/^https?:\/\//) ) {
108
						browser.tabs.executeScript(tab.id, { file: 'js/content.js' });
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
109
					}
110
				})
111
			};
112
113
			try {
114
				browser.tabs.query({}).then(callback);
115
			} catch ( e ) {
116
				browser.tabs.query({}, callback);
117
			}
118
119
			browser.tabs.onRemoved.addListener(function(tabId) {
120
				w.log('remove tab');
121
122
				tabCache[tabId] = null;
123
			});
124
125
			// Live intercept headers using webRequest API
126
			browser.webRequest.onCompleted.addListener(function(details) {
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
127
				var responseHeaders = {};
128
129
				if ( details.responseHeaders ) {
130
					var uri = details.url.replace(/#.*$/, ''); // Remove hash
131
132
					details.responseHeaders.forEach(function(header) {
133
						responseHeaders[header.name.toLowerCase()] = header.value || '' + header.binaryValue;
134
					});
135
136
					if ( headersCache.length > 50 ) {
137
						headersCache = {};
138
					}
139
140
					if ( /text\/html/.test(responseHeaders['content-type']) ) {
141
						if ( headersCache[uri] === undefined ) {
142
							headersCache[uri] = {};
143
						}
144
145
						for ( var header in responseHeaders ) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
146
							headersCache[uri][header] = responseHeaders[header];
147
						}
148
					}
149
150
					w.log(JSON.stringify({ uri: uri, headers: responseHeaders }));
151
				}
152
			}, { urls: [ 'http://*/*', 'https://*/*' ], types: [ 'main_frame' ] }, [ 'responseHeaders' ]);
153
154
			if ( firstRun ) {
155
				w.driver.goToURL({ url: w.config.websiteURL + 'installed', medium: 'install' });
156
157
				firstRun = false;
158
			}
159
160
			if ( upgraded ) {
161
				w.driver.goToURL({ url: w.config.websiteURL + 'upgraded', medium: 'upgrade', background: true });
162
163
				upgraded = false;
164
			}
165
		},
166
167
		onMessage: function(message, sender, sendResponse) {
168
			var
169
				hostname,
170
				response,
171
				a = document.createElement('a');
172
173
			if ( typeof message.id != 'undefined' ) {
174
				w.log('message: ' + message.id);
175
176
				switch ( message.id ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
177
					case 'log':
178
						w.log(message.message);
179
180
						break;
181
					case 'analyze':
182
						tab = sender.tab;
183
184
						a.href = tab.url.replace(/#.*$/, '');
185
186
						hostname = a.hostname;
187
188
						if ( headersCache[a.href] !== undefined ) {
189
							message.subject.headers = headersCache[a.href];
190
						}
191
192
						w.analyze(hostname, a.href, message.subject);
193
194
						break;
195
					case 'ad_log':
196
						w.adCache.push(message.subject);
197
198
						break;
199
					case 'get_apps':
200
						response = {
201
							tabCache:   tabCache[message.tab.id],
202
							apps:       w.apps,
203
							categories: w.categories
204
						};
205
206
						break;
207
				}
208
209
				sendResponse(response);
1 ignored issue
show
Bug introduced by
The variable response seems to not be initialized for all possible execution paths. Are you sure sendResponse handles undefined variables?
Loading history...
210
			}
211
212
		},
213
214
		/**
215
		 * Open a tab
216
		 */
217
		goToURL: function(args) {
218
			browser.tabs.create({
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
219
				url: args.url,
220
				active: args.background === undefined || !args.background
221
			});
222
		},
223
224
		/**
225
		 * Display apps
226
		 */
227
		displayApps: function() {
228
			var
229
				url   = tab.url.replace(/#.*$/, ''),
230
				count = w.detected[url] ? Object.keys(w.detected[url]).length.toString() : '0';
231
232
			if ( tabCache[tab.id] == null ) {
233
				tabCache[tab.id] = {
234
					count: 0,
235
					appsDetected: []
236
					};
237
			}
238
239
			tabCache[tab.id].count        = count;
240
			tabCache[tab.id].appsDetected = w.detected[url];
241
242
			if ( count > 0 ) {
243
				w.driver.getOption('dynamicIcon', true, function(dynamicIcon) {
244
					var appName, found = false;
245
246
					// Find the main application to display
247
					w.driver.categoryOrder.forEach(function(match) {
248
						for ( appName in w.detected[url] ) {
249
							w.apps[appName].cats.forEach(function(cat) {
1 ignored issue
show
introduced by
The variable appName is changed by the for-each loop on line 248. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
250
								var icon = w.apps[appName].icon || 'default.svg';
1 ignored issue
show
introduced by
The variable appName is changed by the for-each loop on line 248. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
251
252
								if ( !dynamicIcon ) {
253
									icon = 'default.svg';
254
								}
255
256
								if ( cat === match && !found ) {
257
									if ( /\.svg$/i.test(icon) ) {
258
										icon = 'converted/' + icon + '.png';
259
									}
260
261
									browser.pageAction.setIcon({
0 ignored issues
show
Bug introduced by
The variable browser seems to be never declared. If this is a global, consider adding a /** global: browser */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
262
										tabId: tab.id,
263
										path: 'images/icons/' + icon
264
									});
265
266
									found = true;
267
								}
268
							});
269
						}
270
					});
271
272
					if ( typeof chrome !== 'undefined' ) {
0 ignored issues
show
Bug introduced by
The variable chrome seems to be never declared. If this is a global, consider adding a /** global: chrome */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
273
						// Browser polyfill doesn't seem to work here
274
						chrome.pageAction.show(tab.id);
275
					} else {
276
						browser.pageAction.show(tab.id);
277
					}
278
				});
279
			};
280
		},
281
282
		/**
283
		 * Anonymously track detected applications for research purposes
284
		 */
285
		ping: function() {
286
			w.driver.getOption('tracking', true, function(tracking) {
287
				if ( Object.keys(w.ping.hostnames).length && tracking ) {
288
					w.driver.post('http://ping.wappalyzer.com/v2/', w.ping);
289
290
					w.log('w.driver.ping: ' + JSON.stringify(w.ping));
291
292
					w.ping = { hostnames: {} };
293
294
					w.driver.post('https://ad.wappalyzer.com/log/wp/', w.adCache);
295
296
					w.adCache = [];
297
				}
298
			});
299
		},
300
301
		/**
302
		 * Make POST request
303
		 */
304
		post: function(url, data) {
305
			var xhr = new XMLHttpRequest();
0 ignored issues
show
Bug introduced by
The variable XMLHttpRequest seems to be never declared. If this is a global, consider adding a /** global: XMLHttpRequest */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
306
307
			xhr.open('POST', url, true);
308
309
			xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
310
311
			xhr.onreadystatechange = function(e) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
312
				if ( xhr.readyState == 4 ) {
313
					w.log('w.driver.post: status ' + xhr.status + ' (' + url + ')');
314
				}
315
			};
316
317
			xhr.send('json=' + encodeURIComponent(JSON.stringify(data)));
318
		}
319
	};
320
321
	w.init();
322
}());
323