Chromium Code Reviews| Index: chrome/test/data/extensions/api_test/notifications/galore/app/controller.js |
| diff --git a/chrome/test/data/extensions/api_test/notifications/galore/app/controller.js b/chrome/test/data/extensions/api_test/notifications/galore/app/controller.js |
| index 5f5aa1ad6f3f19f6a4124318cc0dc4f00440576e..cb594a2fe60ea798ad6f8402da900561782f9446 100644 |
| --- a/chrome/test/data/extensions/api_test/notifications/galore/app/controller.js |
| +++ b/chrome/test/data/extensions/api_test/notifications/galore/app/controller.js |
| @@ -2,242 +2,245 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -var Galore = Galore || {}; |
| - |
| -Galore.controller = { |
| - /** @constructor */ |
| - create: function() { |
| - var controller = Object.create(this); |
| - controller.api = chrome; |
| - controller.counter = 0; |
| - return controller; |
| - }, |
| - |
| - createWindow: function() { |
| - chrome.storage.sync.get('settings', this.onSettingsFetched_.bind(this)); |
| - }, |
| - |
| - /** @private */ |
| - onSettingsFetched_: function(items) { |
| - var request = new XMLHttpRequest(); |
| - var settings = items.settings || {}; |
| - var source = settings.data || '/data/' + this.getDataVersion_(); |
| - request.open('GET', source, true); |
| - request.responseType = 'text'; |
| - request.onload = this.onDataFetched_.bind(this, settings, request); |
| - request.send(); |
| - }, |
| - |
| - /** @private */ |
| - onDataFetched_: function(settings, request) { |
| - var count = 0; |
| - var data = JSON.parse(request.response); |
| +var NOT_RECORDING = "Stopped"; |
| +var RECORDING = "Recording"; |
| +var PAUSED = "Paused"; |
| +var PLAYING = "Playing"; |
| + |
| +var recordingState = NOT_RECORDING; |
| + |
| +// Timestamp when current segment started. |
| +var segmentStart; |
| +// Segment duration accumulated before pause button was hit. |
| +var pausedDuration; |
| +// The array of segments, with delay and action. |
| +var recordingList; |
| +// When this timer fires, the next segment from recordingList should be played. |
| +var playingTimer; |
| +var currentSegmentIndex; |
| + |
| +function setRecordingState(newState) { |
| + controller.view.setRecorderStatusText(newState); |
| + recordingState = newState; |
| +} |
| + |
| +function loadRecording() { |
| + chrome.storage.local.get("recording", function(items) { |
| + recordingList = JSON.parse(items["recording"] || "[]"); |
| + }) |
| +} |
| + |
| +function finalizeRecording() { |
| + chrome.storage.local.set({"recording": JSON.stringify(recordingList)}); |
| +} |
| + |
| +function setPreviousSegmentDuration() { |
| + var now = new Date().getTime(); |
| + var delay = now - segmentStart; |
| + segmentStart = now; |
| + recordingList[currentSegmentIndex++].delay = delay; |
| +} |
| + |
| +function recordCreate(id, options) { |
| + if (recordingState != RECORDING) |
| + return; |
| + setPreviousSegmentDuration(); |
| + recordingList.push({ type: "create", id: id, options: options }); |
| +} |
| + |
| +function recordDelete(id) { |
| + if (recordingState != RECORDING) |
| + return; |
| + setPreviousSegmentDuration(); |
| + recordingList.push({ type: "delete", id: id }); |
| +} |
| + |
| +function startPlaying() { |
| + if (recordingList.length < 2) |
| + return false; |
| + |
| + if (playingTimer) |
| + clearTimeout(playingTimer); |
| + |
| + currentSegmentIndex = 0; |
| + playingTimer = setTimeout(playNextSegment, |
| + recordingList[currentSegmentIndex].delay); |
| +} |
| + |
| +function playNextSegment() { |
| + currentSegmentIndex++; |
| + var segment = recordingList[currentSegmentIndex]; |
| + if (!segment) |
| + stopPlaying(); |
| + |
| + if (segment.type == "create") { |
| + chrome.notifications.create(segment.id, segment.options, function() {}); |
| + } else { // type == "delete" |
| + chrome.notifications.clear(segment.id, function() {}); |
| + } |
| + playingTimer = setTimeout(playNextSegment, |
| + recordingList[currentSegmentIndex].delay); |
| + segmentStart = new Date().getTime(); |
| +} |
| + |
| +function stopPlaying() { |
| + clearTimeout(playingTimer); |
| +} |
| + |
| +function pausePlaying() { |
| + clearTimeout(playingTimer); |
| + pausedDuration = |
| + recordingList[currentSegmentIndex].delay - (now - segmentStart); |
| +} |
| + |
| +function unpausePlaying() { |
| + playingTimer = setTimeout(playNextSegment, pausedDuration); |
| + segmentStart = new Date().getTime(); |
| +} |
| + |
| +function onRecord() { |
| + if (recordingState == NOT_RECORDING) { |
| + currentSegmentIndex = 0; |
| + segmentStart = new Date().getTime(); |
| + pausedDuration = 0; |
| + // This item is only needed to keep a duration of the delay between start |
| + // and first action. |
| + recordingList = [ { type:"start" } ]; |
| + } else if (recordingState == PAUSED) { |
| + segmentStart = new Date().getTime() - pausedDuration; |
| + pausedDuration = 0; |
| + } else { |
| + return; |
| + } |
| + setRecordingState(RECORDING); |
| +} |
| + |
| +function onPause() { |
| + if (recordingState == RECORDING) { |
| + pausedDuration = new Date().getTime() - segmentStart; |
| + segmentStart = 0; |
| + } else if (recordingState == PLAYING) { |
| + pausePlaying(); |
| + } else { |
| + return; |
| + } |
| + setRecordingState(PAUSED); |
| +} |
| + |
| +function onStop() { |
| + if (recordingState == RECORDING) { |
| + finalizeRecording(); |
| + } else if (recordingState == PAUSED) { |
| + segmentStart = new Date().getTime() - pausedDuration; |
| + finalizeRecording(); |
| + } else if (recordingState == PLAYING) { |
| + stopPlaying(); |
| + } else { |
| + return; |
| + } |
| + setRecordingState(NOT_RECORDING); |
| +} |
| + |
| +function onPlay() { |
| + if (recordingState == NOT_RECORDING && startPlaying()) { |
| + setRecordingState = PLAYING; |
| + } |
| +} |
| + |
| +function createWindow() { |
| + loadRecording(); |
| + chrome.storage.local.get('settings', onSettingsFetched); |
| +} |
| + |
| +function onSettingsFetched(items) { |
| + settings = items.settings || settings; |
| + var request = new XMLHttpRequest(); |
| + var source = '/data/data.json'; |
| + request.open('GET', source, true); |
| + request.responseType = 'text'; |
| + request.onload = onDataFetched; |
| + request.send(); |
| +} |
| + |
| +function onDataFetched() { |
| + var data = JSON.parse(this.response); |
| + createAppWindow(function() { |
| + // Create notification buttons. |
| data.forEach(function(section) { |
| + var type = section.notificationType; |
| (section.notificationOptions || []).forEach(function(options) { |
| - ++count; |
| - this.fetchImages_(options, function() { |
| - if (--count == 0) |
| - this.onImagesFetched_(settings, data); |
| - }.bind(this)); |
| - }, this); |
| - }, this); |
| - }, |
| - |
| - /** @private */ |
| - onImagesFetched_: function(settings, data) { |
| - this.settings = settings; |
| - this.view = Galore.view.create(this.settings, function() { |
| - // Create buttons. |
| - data.forEach(function(section) { |
| - var defaults = section.globals || data[0].globals; |
| - var type = section.notificationType; |
| - (section.notificationOptions || []).forEach(function(options) { |
| - var defaulted = this.getDefaultedOptions_(options, defaults); |
| - var create = this.createNotification_.bind(this, type, defaulted); |
| - this.view.addNotificationButton(section.sectionName, |
| - defaulted.title, |
| - defaulted.iconUrl, |
| - create); |
| - }, this); |
| - }, this); |
| - // Set the API entry point and use it to set event listeners. |
| - this.api = this.getApi_(data); |
| - if (this.api) |
| - this.addListeners_(this.api, data[0].events); |
| - // Display the completed and ready window. |
| - this.view.showWindow(); |
| - }.bind(this), this.onSettingsChange_.bind(this)); |
| - }, |
| - |
| - /** @private */ |
| - fetchImages_: function(options, onFetched) { |
| - var count = 0; |
| - var replacements = {}; |
| - this.mapStrings_(options, function(string) { |
| - if (string.indexOf("/images/") == 0 || string.search(/https?:\//) == 0) { |
| - ++count; |
| - this.fetchImage_(string, function(url) { |
| - replacements[string] = url; |
| - if (--count == 0) { |
| - this.mapStrings_(options, function(string) { |
| - return replacements[string] || string; |
| - }); |
| - onFetched.call(this, options); |
| - } |
| - }); |
| - } |
| - }); |
| - }, |
| - |
| - /** @private */ |
| - fetchImage_: function(url, onFetched) { |
| - var request = new XMLHttpRequest(); |
| - request.open('GET', url, true); |
| - request.responseType = 'blob'; |
| - request.onload = function() { |
| - var url = window.URL.createObjectURL(request.response); |
| - onFetched.call(this, url); |
| - }.bind(this); |
| - request.send(); |
| - }, |
| - |
| - /** @private */ |
| - onSettingsChange_: function(settings) { |
| - this.settings = settings; |
| - chrome.storage.sync.set({settings: this.settings}); |
| - }, |
| - |
| - /** @private */ |
| - createNotification_: function(type, options) { |
| - var id = this.getNextId_(); |
| - var priority = Number(this.settings.priority || 0); |
| - var expanded = this.getExpandedOptions_(options, id, type, priority); |
| - if (type == 'webkit') |
| - this.createWebKitNotification_(expanded); |
| - else |
| - this.createRichNotification_(expanded, id, type, priority); |
| - }, |
| - |
| - /** @private */ |
| - createWebKitNotification_: function(options) { |
| - var iconUrl = options.iconUrl; |
| - var title = options.title; |
| - var message = options.message; |
| - new Notification(title, { |
| - body: message, |
| - icon: iconUrl |
| - }); |
| - this.handleEvent_('create', '?', 'title: "' + title + '"'); |
| - }, |
| - |
| - /** @private */ |
| - createRichNotification_: function(options, id, type, priority) { |
| - this.api.create(id, options, function() { |
| - var argument1 = 'type: "' + type + '"'; |
| - var argument2 = 'priority: ' + priority; |
| - var argument3 = 'title: "' + options.title + '"'; |
| - this.handleEvent_('create', id, argument1, argument2, argument3); |
| - }.bind(this)); |
| - }, |
| - |
| - /** @private */ |
| - getNextId_: function() { |
| - this.counter += 1; |
| - return String(this.counter); |
| - }, |
| - |
| - /** @private */ |
| - getDefaultedOptions_: function(options, defaults) { |
| - var defaulted = this.deepCopy_(options); |
| - Object.keys(defaults || {}).forEach(function (key) { |
| - defaulted[key] = options[key] || defaults[key]; |
| + addNotificationButton(section.sectionName, |
| + options.title, |
| + options.iconUrl, |
| + function() { createNotification(type, options) }); |
| + }); |
| }); |
| - return defaulted; |
| - }, |
| - |
| - /** @private */ |
| - getExpandedOptions_: function(options, id, type, priority) { |
| - var expanded = this.deepCopy_(options); |
| - return this.mapStrings_(expanded, function(string) { |
| - return this.getExpandedOption_(string, id, type, priority); |
| - }, this); |
| - }, |
| - |
| - /** @private */ |
| - getExpandedOption_: function(option, id, type, priority) { |
| - if (option == '$!') { |
| - option = priority; // Avoids making priorities into strings. |
| - } else { |
| - option = option.replace(/\$#/g, id); |
| - option = option.replace(/\$\?/g, type); |
| - option = option.replace(/\$\!/g, priority); |
| - } |
| - return option; |
| - }, |
| - |
| - /** @private */ |
| - deepCopy_: function(value) { |
| - var copy = value; |
| - if (Array.isArray(value)) { |
| - copy = value.map(this.deepCopy_, this); |
| - } else if (value && typeof value === 'object') { |
| - copy = {} |
| - Object.keys(value).forEach(function (key) { |
| - copy[key] = this.deepCopy_(value[key]); |
| - }, this); |
| - } |
| - return copy; |
| - }, |
| - |
| - /** @private */ |
| - mapStrings_: function(value, map) { |
| - var mapped = value; |
| - if (typeof value === 'string') { |
| - mapped = map.call(this, value); |
| - mapped = (typeof mapped !== 'undefined') ? mapped : value; |
| - } else if (value && typeof value == 'object') { |
| - Object.keys(value).forEach(function (key) { |
| - mapped[key] = this.mapStrings_(value[key], map); |
| - }, this); |
| - } |
| - return mapped; |
| - }, |
| - |
| - /** @private */ |
| - addListeners_: function(api, events) { |
| - (events || []).forEach(function(event) { |
| - var listener = this.handleEvent_.bind(this, event); |
| - if (api[event]) |
| - api[event].addListener(listener); |
| - else |
| - console.log('Event ' + event + ' not defined.'); |
| - }, this); |
| - }, |
| - |
| - /** @private */ |
| - handleEvent_: function(event, id, var_args) { |
| - this.view.logEvent('Notification #' + id + ': ' + event + '(' + |
| - Array.prototype.slice.call(arguments, 2).join(', ') + |
| - ')'); |
| - }, |
| - |
| - /** @private */ |
| - getDataVersion_: function() { |
| - var version = navigator.appVersion.replace(/^.* Chrome\//, ''); |
| - return (version > '28.0.1500.70') ? '28.0.1500.70.json' : |
| - (version > '27.0.1433.1') ? '27.0.1433.1.json' : |
| - (version > '27.0.1432.2') ? '27.0.1432.2.json' : |
| - '27.0.0.0.json'; |
| - }, |
| - |
| - /** @private */ |
| - getApi_: function(data) { |
| - var path = data[0].api || 'notifications'; |
| - var api = chrome; |
| - path.split('.').forEach(function(key) { api = api && api[key]; }); |
| - if (!api) |
| - this.view.logError('No API found - chrome.' + path + ' is undefined'); |
| - return api; |
| - } |
| - |
| -}; |
| + addListeners(); |
| + showWindow(); |
| + }); |
| +} |
| + |
| +function onSettingsChange(settings) { |
| + chrome.storage.local.set({settings: settings}); |
| +} |
| + |
| +function createNotification(type, options) { |
| +var id = getNextId(); |
| +var priority = Number(settings.priority || 0); |
| +if (type == 'webkit') |
| + createWebKitNotification(options); |
| + else |
| + createRichNotification(id, type, priority, options); |
| +} |
| + |
| +function createWebKitNotification(options) { |
|
dewittj
2014/06/06 17:54:22
s/webkit/w3c/ or web
Dmitry Titov
2014/06/06 22:57:18
Done.
|
| + var iconUrl = options.iconUrl; |
| + var title = options.title; |
| + var message = options.message; |
| + new Notification(title, { |
| + body: message, |
| + icon: iconUrl |
|
dewittj
2014/06/06 17:54:22
add tag?
Dmitry Titov
2014/06/06 22:57:18
Done.
We currently don't seem to catch/log any ev
|
| + }); |
| + logCreate('created WebKit', '', 'title: "' + title + '"'); |
| +} |
| + |
| +function createRichNotification(id, type, priority, options) { |
| + options["type"] = type; |
| + options["priority"] = priority; |
| + chrome.notifications.create(id, options, function() { |
| + var argument1 = 'type: "' + type + '"'; |
| + var argument2 = 'priority: ' + priority; |
| + var argument3 = 'title: "' + options.title + '"'; |
| + logCreate('created Rich', id, argument1, argument2, argument3); |
| + }); |
| + recordCreate(id, options); |
| +} |
| + |
| +var counter = 0; |
| +function getNextId() { |
| + return String(counter++); |
| +} |
| + |
| +function addListeners() { |
| + chrome.notifications.onClosed.addListener(onClosed); |
| + chrome.notifications.onClicked.addListener(onClicked); |
| + chrome.notifications.onButtonClicked.addListener(onButtonClicked); |
| +} |
| + |
| +function logCreate(event, id, var_args) { |
| + logEvent('Notification #' + id + ': ' + event + '(' + |
| + Array.prototype.slice.call(arguments, 2).join(', ') + ')'); |
| +} |
| + |
| +function onClosed(id) { |
| + logEvent('Notification #' + id + ': onClosed'); |
| + recordDelete(id); |
| +} |
| + |
| +function onClicked(id) { |
| + logEvent('Notification #' + id + ': onClicked'); |
| +} |
| + |
| +function onButtonClicked(id, index) { |
| + logEvent('Notification #' + id + ': onButtonClicked, btn: ' + index); |
| +} |