Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / data / extensions / hangout_services_test.js
blob8a167a4f02737caf183533226954d5cf1a219c61
1 // Copyright 2013 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 // JavaScript for invoking methods on APIs used by Hangouts via the
6 // Hangout Services extension, and a JavaScript-based end-to-end test
7 // of the extension.
9 // ID of the Hangout Services component extension.
10 var EXTENSION_ID = "nkeimhogjdpnpccoofpliimaahmaaome";
12 // Sends a message to the Hangout Services extension, expecting
13 // success, and unwraps the value returned.
14 function sendMessage(message, callback) {
15   function unwrapValue(result) {
16     if (callback)
17       callback(result.value);
18   }
19   window.top.chrome.runtime.sendMessage(EXTENSION_ID, message, unwrapValue);
22 // If connected, this port will receive events from the extension.
23 var callbackPort;
25 // Connects callbackPort to the extension, with a connectInfo.name that
26 // indicates we want to receive the onSinksChanged event, and sets its
27 // onMessage to |callback|.
28 function listenForSinksChangedEvent(callback) {
29   callbackPort = window.top.chrome.runtime.connect(
30       EXTENSION_ID, {'name': 'onSinksChangedListener'});
31   callbackPort.onMessage.addListener(callback);
35 // Helpers to invoke functions on the extension.
38 // Will call |callback({'cancelId': ..., 'streamId': ...})| on completion.
39 function chooseDesktopMedia(callback) {
40   sendMessage({'method': 'chooseDesktopMedia'}, callback);
43 // Will call |callback()| when API method has been called (it will
44 // complete later).
45 function cancelChooseDesktopMedia(cancelId, callback) {
46   sendMessage({'method': 'cancelChooseDesktopMedia', 'cancelId': cancelId},
47               callback);
50 // Will call |callback(cpuInfo)| on completion.
51 function cpuGetInfo(callback) {
52   sendMessage({'method': 'cpu.getInfo'}, callback);
55 // Will call |callback()| on completion.
56 function loggingSetMetadata(metaData, callback) {
57   sendMessage({'method': 'logging.setMetadata', 'metaData': metaData},
58               callback);
61 // Will call |callback()| on completion.
62 function loggingStart(callback) {
63   sendMessage({'method': 'logging.start'}, callback);
66 // Will call |callback()| when API method has been called (it will
67 // complete later).
68 function loggingUploadOnRenderClose() {
69   sendMessage({'method': 'logging.uploadOnRenderClose'});
72 // Will call |callback()| when API method has been called (it will
73 // complete later).
74 function loggingNoUploadOnRenderClose() {
75   sendMessage({'method': 'logging.noUploadOnRenderClose'});
78 // Will call |callback()| on completion.
79 function loggingStop(callback) {
80   sendMessage({'method': 'logging.stop'}, callback);
83 // Will call |callback()| on completion.
84 function loggingStore(logId, callback) {
85   sendMessage({'method': 'logging.store', 'logId': logId}, callback);
88 // Will call |callback()| on completion.
89 function loggingUploadStored(logId, callback) {
90   sendMessage({'method': 'logging.uploadStored', 'logId': logId}, callback);
93 // Will call |callback(uploadResult)| on completion.
94 function loggingUpload(callback) {
95   sendMessage({'method': 'logging.upload'}, callback);
98 // Will call |callback(uploadResult)| on completion.
99 function loggingStopAndUpload(callback) {
100   sendMessage({'method': 'logging.stopAndUpload'}, callback);
103 // Will call |callback()| on completion.
104 function loggingDiscard(callback) {
105   sendMessage({'method': 'logging.discard'}, callback);
108 // Will call |callback(sinkList)| on completion.
109 function getSinks(callback) {
110   sendMessage({'method': 'getSinks'}, callback);
113 // Will call |callback(activeSink)| on completion.
114 function getActiveSink(callback) {
115   sendMessage({'method': 'getActiveSink'}, callback);
118 // Will call |callback()| on completion.
119 function setActiveSink(sinkId, callback) {
120   sendMessage({'method': 'setActiveSink', 'sinkId': sinkId}, callback);
123 // Will call |callback(sinkId)| on completion.
124 function getAssociatedSink(sourceId, callback) {
125   sendMessage({'method': 'getAssociatedSink', 'sourceId': sourceId},
126               callback);
129 // Will call |callback()| on completion. If the extension you send to
130 // is not loaded, the extension system will still call |callback()|
131 // but will set lastError.
132 function isExtensionEnabled(callback) {
133   sendMessage({'method': 'isExtensionEnabled'}, callback);
137 // Automated tests.
140 // Very micro test framework. Add all tests to |TESTS|. Each test must
141 // call the passed-in callback eventually with a string indicating
142 // results. Empty results indicate success.
143 var TESTS = [
144   testCpuGetInfo,
145   testLogging,
146   testLoggingSetMetaDataAfterStart,
147   testDisabledLogging,
148   testDisabledLoggingButUpload,
149   testDisabledLoggingWithStopAndUpload,
150   testEnabledLoggingButDiscard,
151   testGetSinks,
152   testGetActiveSink,
153   testSetActiveSink,
154   testGetAssociatedSink,
155   testIsExtensionEnabled,
156   testSendingToInvalidExtension,
157   testStoreLog,
159   // Uncomment to manually test timeout logic.
160   //testTimeout,
163 var TEST_TIMEOUT_MS = 3000;
165 function runAllTests(callback) {
166   var results = '';
168   // Run one test at a time, running the next only on completion.
169   // This makes it easier to deal with timing out tests that do not
170   // complete successfully.
171   //
172   // It also seems necessary (instead of starting all the tests in
173   // parallel) as the webrtcLoggingPrivate API does not seem to like
174   // certain sequences of interleaved requests (it may DCHECK in
175   // WebRtcLoggingHandlerHost::NotifyLoggingStarted() when firing the
176   // start callback.
177   //
178   // TODO(grunell): Fix webrtcLoggingPrivate to be stateless.
180   // Index of the test currently executing.
181   var testIndex = 0;
183   function startTest(test) {
184     console.log('Starting ' + test.name);
186     // Start the test function...
187     test(function(currentResults) {
188         nextTest(test.name, currentResults, false);
189       });
191     // ...and also start a timeout.
192     function onTimeout() {
193       nextTest(test.name, '', true);
194     }
195     setTimeout(onTimeout, TEST_TIMEOUT_MS);
196   }
198   function nextTest(testName, currentResults, timedOut) {
199     // The check for testIndex is necessary for timeouts arriving
200     // after testIndex is already past the end of the TESTS array.
201     if (testIndex >= TESTS.length ||
202         testName != TESTS[testIndex].name) {
203       // Either a timeout of a function that already completed, or a
204       // function completing after a timeout. Either way we ignore.
205       console.log('Ignoring results for ' + testName +
206                   ' (timedout: ' + timedOut + ')');
207       return;
208     }
210     if (timedOut) {
211       console.log('Timed out: ' + testName);
212       results = results + 'Timed out: ' + testName + '\n';
213     } else {
214       console.log('Got results for ' + testName + ': ' + currentResults);
215       if (currentResults != '') {
216         results = results + 'Failure in ' + testName + ':\n';
217         results = results + currentResults;
218       }
219     }
221     ++testIndex;
222     if (testIndex == TESTS.length) {
223       callback(results);
224     } else {
225       startTest(TESTS[testIndex]);
226     }
227   }
229   startTest(TESTS[testIndex]);
232 function testCpuGetInfo(callback) {
233   cpuGetInfo(function(info) {
234       if (info.numOfProcessors != 0 &&
235           info.archName != '' &&
236           info.modelName != '') {
237         callback('');
238       } else {
239         callback('Missing information in CpuInfo');
240       }
241     });
244 // Tests setting metadata, turning on upload, starting and then
245 // stopping the log.
246 function testLogging(callback) {
247   loggingSetMetadata([{'bingo': 'bongo', 'smurf': 'geburf'}], function() {
248       loggingStart(function() {
249           loggingUploadOnRenderClose();
250           loggingStop(function() {
251               callback('');
252             });
253         });
254     });
257 // Tests starting the log, setting metadata, turning on upload, and then
258 // stopping the log.
259 function testLoggingSetMetaDataAfterStart(callback) {
260   loggingStart(function() {
261       loggingSetMetadata([{'bingo': 'bongo', 'smurf': 'geburf'}], function() {
262           loggingUploadOnRenderClose();
263           loggingStop(function() {
264               callback('');
265             });
266         });
267     });
270 // Starts and stops logging while auto-upload is disabled.
271 function testDisabledLogging(callback) {
272   loggingNoUploadOnRenderClose();
273   loggingStart(function() {
274       loggingStop(function() {
275           callback('');
276         });
277     });
280 // Starts and stops logging while auto-upload is disabled, but
281 // requests logs upload after stopping logging.
282 function testDisabledLoggingButUpload(callback) {
283   loggingNoUploadOnRenderClose();
284   loggingStart(function() {
285       loggingStop(function() {
286           loggingUpload(function(loggingResult) {
287               if (loggingResult != '') {
288                 callback('');
289               } else {
290                 callback('Got empty upload result.');
291               }
292             });
293         });
294     });
297 // Starts logging while auto-upload is disabled. Uses the
298 // stopAndUpload function to stop, then upload, the results.
299 function testDisabledLoggingWithStopAndUpload(callback) {
300   loggingNoUploadOnRenderClose();
301   loggingStart(function() {
302       loggingStopAndUpload(function(loggingResult) {
303           if (loggingResult != '') {
304             callback('');
305           } else {
306             callback('Got empty upload result.');
307           }
308       });
309   });
312 // Starts and stops logging while auto-upload is enabled, but
313 // requests logs be discarded after stopping logging.
314 function testEnabledLoggingButDiscard(callback) {
315   loggingUploadOnRenderClose();
316   loggingStart(function() {
317       loggingStop(function() {
318           loggingDiscard(function() {
319               callback('');
320             });
321         });
322     });
325 function testGetSinks(callback) {
326   getSinks(function(sinks) {
327       // Some bots may have no audio sinks installed, in which case we
328       // will get an empty list here.
329       callback('');
330     });
333 function testGetActiveSink(callback) {
334   getActiveSink(function(sinkId) {
335       if (sinkId == '') {
336         callback('Got empty sink ID.');
337       } else {
338         callback('');
339       }
340     });
343 function testSetActiveSink(callback) {
344   getSinks(function(sinks) {
345       for (var i = 0; i < sinks.length; ++i) {
346         setActiveSink(sinks[i].sinkId);
347       }
348       callback('');
349     });
352 function testGetAssociatedSink(callback) {
353   getAssociatedSink('noSuchSourceId', function(sinkId) {
354       if (sinkId != '') {
355         callback('Got non-empty sink ID for nonexistent source ID.');
356       } else {
357         callback('');
358       }
359     });
362 function testIsExtensionEnabled(callback) {
363   isExtensionEnabled(function() {
364       callback('');
365     });
368 function testSendingToInvalidExtension(callback) {
369   // This test verifies that client code can always determine whether
370   // or not the component extension is available without resorting to
371   // timeouts, by sending it the 'isExtensionEnabled' message. If the
372   // extension is there, it will respond (see testIsExtensionEnabled)
373   // and if it's not, the extension framework will send a callback and
374   // set lastError.
375   var NON_EXISTENT_EXTENSION_ID = "aaaaaaagjdpnpccoofpliimaaeeeeeee";
376   window.top.chrome.runtime.sendMessage(
377       NON_EXISTENT_EXTENSION_ID, {'method': 'isExtensionEnabled'},
378       function() {
379           if (window.top.chrome.runtime.lastError.message.indexOf(
380                   'Could not establish connection') == -1) {
381             callback('lastError is not set correctly.');
382           } else {
383             callback('');
384           }
385         });
388 function testStoreLog(callback) {
389   var logId = "mylog_id";
390   // Start by logging something.
391   loggingSetMetadata([{'bingos': 'bongos', 'smurfs': 'geburfs'}], function() {
392       loggingStart(function() {
393           loggingStop(function() {
394               loggingStore(logId, function() {
395                   loggingUploadStored(logId, function(loggingResult) {
396                     if (loggingResult != '') {
397                       callback('');
398                     } else {
399                       callback('Got empty upload result.');
400                     }
401                   });
402               });
403             });
404         });
405     });
408 function testTimeout(callback) {
409   // Never call the callback. Used for manually testing that the
410   // timeout logic of the test framework is correct.