OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // If you set this variable to true, then compile and run Chrome, all messages | |
6 // sent with chrome.send() will be intercepted and their callback data will be | |
7 // recorded. You can later see the recorded data by executing chrome.mock() | |
8 // on Web Developer Tools' console. | |
9 var recordMockData = false; | |
10 | |
11 (recordMockData || !/^chrome:\/\/./.test(location.href)) && (function() { | |
12 | |
13 var __chrome__ = chrome; | |
14 var shouldRegisterData = !!window.chrome && !!window.chrome.send; | |
15 | |
16 var NO_CALLBACK = 1; | |
17 | |
18 // Only messages registered in the callback map will be intercepted. | |
19 var callbackMap = { | |
20 'appRemoved': 'ntp.appRemoved', | |
21 'blacklistURLFromMostVisited': NO_CALLBACK, | |
22 'clearMostVisitedURLsBlacklist': NO_CALLBACK, | |
23 'getApps': 'ntp.getAppsCallback', | |
24 'getForeignSessions': 'ntp.setForeignSessions', | |
25 'getMostVisited': 'ntp.setMostVisitedPages', | |
26 'getRecentlyClosedTabs': 'ntp.setRecentlyClosedTabs', | |
27 'metricsHandler:logEventTime': NO_CALLBACK, | |
28 'metricsHandler:recordInHistogram': NO_CALLBACK, | |
29 'removeURLsFromMostVisitedBlacklist': NO_CALLBACK, | |
30 'uninstallApp': NO_CALLBACK, | |
31 }; | |
32 | |
33 // TODO(pedrosimonetti): include automatically in the recorded data | |
34 // TODO(pedrosimonetti): document the special char replacement | |
35 var mockedThumbnailUrls = [ | |
36 'http---www.wikipedia.org-', | |
37 'http---www.deviantart.com-', | |
38 'http---wefunkradio.com-', | |
39 'http---youtube.com-', | |
40 'http---amazon.com-', | |
41 'http---nytimes.com-', | |
42 'http---news.ycombinator.com-', | |
43 'http---cnn.com-', | |
44 'http---ebay.com-', | |
45 'http---www.google.com-chrome-intl-en-welcome.html', | |
46 'https---chrome.google.com-webstore-hl-en', | |
47 ]; | |
48 | |
49 //---------------------------------------------------------------------------- | |
50 // Internals | |
51 //---------------------------------------------------------------------------- | |
52 | |
53 var dataMap = {}; | |
54 var recordedDataMap = {}; | |
55 var isInitialized = false; | |
56 | |
57 function initialize() { | |
58 if (shouldRegisterData || !namespace('ntp')) | |
59 return; | |
60 | |
61 isInitialized = true; | |
62 namespace('ntp.getThumbnailUrl', mockGetThumbnailUrl); | |
63 | |
64 var data = loadTimeData.data_; | |
65 document.documentElement.dir = data.textdirection; | |
66 document.body.style.fontSize = data.fontsize; | |
67 } | |
68 | |
69 function namespace(str, data) { | |
70 var ns = str.split('.'), name, object = window; | |
71 for (var i = 0, l = ns.length; i < l; i++) { | |
72 name = ns[i]; | |
73 if (data && i == (l - 1)) | |
74 object = object[name] = data; | |
75 else | |
76 object = object[name]; | |
77 } | |
78 return object == window ? null : object; | |
79 } | |
80 | |
81 function copyArray(arr) { | |
82 return Array.prototype.slice.call(arr, 0); | |
83 } | |
84 | |
85 function interceptCallback(message, callbackNamespace) { | |
86 var original = namespace(callbackNamespace); | |
87 namespace(callbackNamespace, function() { | |
88 recordedDataMap[message] = copyArray(arguments); | |
89 var result = original.apply(window, arguments); | |
90 namespace(callbackNamespace, original); | |
91 return result; | |
92 }); | |
93 } | |
94 | |
95 function dispatchCallbackForMessage(message) { | |
96 var callbackNamespace = callbackMap[message]; | |
97 var callback = namespace(callbackNamespace); | |
98 var data = dataMap[message]; | |
99 var filter = filterMap[message]; | |
100 if (filter) | |
101 data = filter(data); | |
102 callback.apply(window, data); | |
103 } | |
104 | |
105 function interceptLoadData() { | |
106 window.addEventListener('load', function() { | |
107 recordedDataMap['__loadTimeData__'] = loadTimeData.data_; | |
108 }); | |
109 } | |
110 | |
111 function mockGetThumbnailUrl(url) { | |
112 url = url.replace(/[:\/\?=]/g, '-'); | |
113 | |
114 var mockUrl; | |
115 var index = mockedThumbnailUrls.indexOf(url); | |
116 if (index != -1) | |
117 mockUrl = mockedThumbnailUrls[index]; | |
118 else | |
119 mockUrl = 'non-existent-file-name'; | |
120 | |
121 mockUrl = 'mock/images/' + mockUrl + '.jpg'; | |
122 return mockUrl; | |
123 } | |
124 | |
125 function mockLoadData() { | |
126 if (loadTimeData) | |
127 loadTimeData.data = dataMap['__loadTimeData__']; | |
128 } | |
129 | |
130 function getTime(time) { | |
131 var slownessFactor = debugArgs.slownessFactor || 1; | |
132 return Math.round(time * slownessFactor); | |
133 } | |
134 | |
135 //---------------------------------------------------------------------------- | |
136 // ChromeMock implementation | |
137 //---------------------------------------------------------------------------- | |
138 | |
139 var ChromeMock = { | |
140 get debugArgs() { | |
141 return debugArgs; | |
142 }, | |
143 | |
144 mock: function(newDataMap) { | |
145 if (newDataMap) { | |
146 dataMap = newDataMap; | |
147 if (!shouldRegisterData) | |
148 mockLoadData(); | |
149 } else { | |
150 return recordedDataMap; | |
151 } | |
152 }, | |
153 | |
154 send: function() { | |
155 if (!isInitialized) | |
156 initialize(); | |
157 | |
158 var message = arguments[0]; | |
159 var shouldCallChromeSend = false; | |
160 | |
161 if (callbackMap.hasOwnProperty(message)) { | |
162 var callbackNamespace = callbackMap[message]; | |
163 | |
164 if (shouldRegisterData) { | |
165 if (callbackNamespace !== NO_CALLBACK) | |
166 interceptCallback(message, callbackNamespace); | |
167 } else { | |
168 if (dataMap.hasOwnProperty(message)) { | |
169 var data = dataMap[message]; | |
170 var callback = namespace(callbackNamespace); | |
171 | |
172 if (filterMap.hasOwnProperty(message)) | |
173 data = filterMap[message](data); | |
174 | |
175 setTimeout(function() { | |
176 callback.apply(window, data); | |
177 }, 0); | |
178 } else { | |
179 if (callbackNamespace !== NO_CALLBACK) | |
180 console.warn('No mock registered for message "%s".', message); | |
181 else if (serverCallbackMap.hasOwnProperty(message)) | |
182 serverCallbackMap[message](arguments[1]); | |
183 } | |
184 } | |
185 } else { | |
186 shouldCallChromeSend = true; | |
187 console.warn('No callback data registered for message "%s".', message); | |
188 } | |
189 | |
190 shouldCallChromeSend = shouldCallChromeSend || shouldRegisterData; | |
191 if (shouldCallChromeSend) { | |
192 if (__chrome__ && __chrome__.send) | |
193 __chrome__.send(message); | |
194 } | |
195 }, | |
196 }; | |
197 | |
198 //---------------------------------------------------------------------------- | |
199 // C++ mock implementation | |
200 //---------------------------------------------------------------------------- | |
201 | |
202 var mostVisitedBlackList = {}; | |
203 | |
204 var filterMap = { | |
205 getMostVisited: function(data) { | |
206 var filtered = []; | |
207 var list = data[0]; | |
208 var hasBlacklistedUrls = false; | |
209 for (var i = 0, length = list.length; i < length; i++) { | |
210 if (mostVisitedBlackList.hasOwnProperty('' + i)) | |
211 hasBlacklistedUrls = true; | |
212 else | |
213 filtered.push(list[i]); | |
214 } | |
215 return [filtered, hasBlacklistedUrls]; | |
216 } | |
217 }; | |
218 | |
219 var serverCallbackMap = { | |
220 blacklistURLFromMostVisited: function(urls) { | |
221 var url = urls[0]; | |
222 var data = dataMap['getMostVisited'][0]; | |
223 for (var i = 0, length = data.length; i < length; i++) { | |
224 if (data[i].url == url) | |
225 mostVisitedBlackList['' + i] = 1; | |
226 } | |
227 dispatchCallbackForMessage('getMostVisited'); | |
228 }, | |
229 | |
230 removeURLsFromMostVisitedBlacklist: function(urls) { | |
231 var url = urls[0]; | |
232 var data = dataMap['getMostVisited'][0]; | |
233 for (var i = 0, length = data.length; i < length; i++) { | |
234 if (data[i].url == url) | |
235 delete mostVisitedBlackList['' + i]; | |
236 } | |
237 dispatchCallbackForMessage('getMostVisited'); | |
238 }, | |
239 | |
240 clearMostVisitedURLsBlacklist: function() { | |
241 mostVisitedBlackList = {}; | |
242 dispatchCallbackForMessage('getMostVisited'); | |
243 }, | |
244 | |
245 uninstallApp: function(id) { | |
246 var removedData; | |
247 var data = dataMap['getApps'][0].apps; | |
248 for (var i = 0, length = data.length; i < length; i++) { | |
249 if (data[i].id == id) { | |
250 removedData = data[i]; | |
251 data.splice(i, 1); | |
252 break; | |
253 } | |
254 } | |
255 assert(removedData); | |
256 dataMap['appRemoved'] = [removedData, true, true]; | |
257 dispatchCallbackForMessage('appRemoved'); | |
258 }, | |
259 }; | |
260 | |
261 //---------------------------------------------------------------------------- | |
262 // Debug | |
263 //---------------------------------------------------------------------------- | |
264 | |
265 var debugArgs = { | |
266 debug: false, | |
267 slownessFactor: null, | |
268 }; | |
269 | |
270 var debugStylesheet = null; | |
271 var selectorDurationMap = { | |
272 '.animate-grid-width': 200, | |
273 '.animate-grid-width .tile-cell': 200, | |
274 '.animate-tile-repositioning .tile': 200, | |
275 '.animate-tile-repositioning .tile:not(.target-tile)': 400, | |
276 '#bottom-panel': 200, | |
277 '.dot': 200, | |
278 '.tile-grid-content': 200, | |
279 '.tile-row': 200, | |
280 }; | |
281 | |
282 var selectorDurationImportantMap = { | |
283 }; | |
284 | |
285 var selectorDelayMap = { | |
286 '.animate-tile-repositioning.undo-removal .target-tile': 200, | |
287 }; | |
288 | |
289 function adjustAnimationSpeed() { | |
290 var animationRules = []; | |
291 for (var selector in selectorDurationMap) { | |
292 if (selectorDurationMap.hasOwnProperty(selector)) { | |
293 animationRules.push(selector + ' { -webkit-transition-duration: ' + | |
294 getTime(selectorDurationMap[selector]) + 'ms; }\n'); | |
295 } | |
296 } | |
297 | |
298 for (var selector in selectorDurationImportantMap) { | |
299 if (selectorDurationImportantMap.hasOwnProperty(selector)) { | |
300 animationRules.push(selector + ' { -webkit-transition-duration: ' + | |
301 getTime(selectorDurationImportantMap[selector]) + | |
302 'ms !important; }\n'); | |
303 } | |
304 } | |
305 | |
306 for (var selector in selectorDelayMap) { | |
307 if (selectorDelayMap.hasOwnProperty(selector)) { | |
308 animationRules.push(selector + ' { -webkit-transition-delay: ' + | |
309 getTime(selectorDelayMap[selector]) + 'ms; }\n'); | |
310 } | |
311 } | |
312 | |
313 var doc = document; | |
314 debugStylesheet = doc.getElementById('debugStylesheet'); | |
315 if (debugStylesheet) | |
316 debugStylesheet.parentElement.removeChild(debugStylesheet); | |
317 | |
318 debugStylesheet = doc.createElement('style'); | |
319 debugStylesheet.id = 'debugStylesheet'; | |
320 debugStylesheet.textContent = animationRules.join(''); | |
321 doc.querySelector('head').appendChild(debugStylesheet); | |
322 } | |
323 | |
324 function getArgs() { | |
325 var url = location.href; | |
326 var parts = url.split('?'); | |
327 var args = parts[1]; | |
328 if (args) { | |
329 var pairs = args.split('&'); | |
330 for (var i = 0, l = pairs.length; i < l; i++) { | |
331 var pair = pairs[i]; | |
332 var data = pair.split('='); | |
333 var key = data[0]; | |
334 var value = data[1]; | |
335 debugArgs[key] = typeof value == 'undefined' ? true : | |
336 parseFloat(value) ? parseFloat(value) : value; | |
337 } | |
338 } | |
339 } | |
340 | |
341 window.addEventListener('load', function() { | |
342 getArgs(); | |
343 | |
344 if (debugArgs.debug) | |
345 document.body.classList.add('debug'); | |
346 | |
347 if (debugArgs.background) | |
348 document.body.style.background = debugArgs.background; | |
349 | |
350 var slownessFactor = debugArgs.slownessFactor; | |
351 if (slownessFactor) | |
352 adjustAnimationSpeed(); | |
353 }); | |
354 | |
355 //---------------------------------------------------------------------------- | |
356 // ChromeMock initialization | |
357 //---------------------------------------------------------------------------- | |
358 | |
359 if (shouldRegisterData) | |
360 interceptLoadData(); | |
361 | |
362 window.chrome = ChromeMock; | |
363 })(); | |
OLD | NEW |