Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / chrome / test / data / indexeddb / endure / app.js
blobad611b5da46e1c89dcb88d433ff82283d0e5143c
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.
5 // This file simulates a typical foreground process of an offline-capable
6 // authoring application. When in an "offline" state, simulated user actions
7 // are recorded for later playback in an IDB data store. When in an "online"
8 // state, the recorded actions are drained from the store (as if being sent
9 // to the server).
11 var $ = function(s) {
12 return document.querySelector(s);
15 function status(message) {
16 var elem = $('#status');
17 while (elem.firstChild)
18 elem.removeChild(elem.firstChild);
19 elem.appendChild(document.createTextNode(message));
22 function log(message) {
23 status(message);
26 function error(message) {
27 status(message);
28 console.error(message);
31 function unexpectedErrorCallback(e) {
32 error("Unexpected error callback: (" + e.target.error.name + ") " +
33 e.target.error.message);
36 function unexpectedAbortCallback(e) {
37 error("Unexpected abort callback: (" + e.target.error.name + ") " +
38 e.target.error.message);
41 function unexpectedBlockedCallback(e) {
42 error("Unexpected blocked callback!");
45 var DBNAME = 'endurance-db';
46 var DBVERSION = 1;
47 var MAX_DOC_ID = 25;
49 var db;
51 function initdb() {
52 var request = indexedDB.deleteDatabase(DBNAME);
53 request.onerror = unexpectedErrorCallback;
54 request.onblocked = unexpectedBlockedCallback;
55 request.onsuccess = function () {
56 request = indexedDB.open(DBNAME, DBVERSION);
57 request.onerror = unexpectedErrorCallback;
58 request.onblocked = unexpectedBlockedCallback;
59 request.onupgradeneeded = function () {
60 db = request.result;
61 request.transaction.onabort = unexpectedAbortCallback;
63 var syncStore = db.createObjectStore(
64 'sync-chunks', {keyPath: 'sequence', autoIncrement: true});
65 syncStore.createIndex('doc-index', 'docid');
67 var docStore = db.createObjectStore(
68 'docs', {keyPath: 'docid'});
69 docStore.createIndex(
70 'owner-index', 'owner', {multiEntry: true});
72 var userEventStore = db.createObjectStore(
73 'user-events', {keyPath: 'sequence', autoIncrement: true});
74 userEventStore.createIndex('doc-index', 'docid');
76 request.onsuccess = function () {
77 log('initialized');
78 $('#offline').disabled = true;
79 $('#online').disabled = false;
84 var offline = true;
85 var worker = new Worker('app-worker.js?cachebust');
86 worker.onmessage = function (event) {
87 var data = event.data;
88 switch (data.type) {
89 case 'ABORT':
90 unexpectedAbortCallback({target: {error: data.error}});
91 break;
92 case 'ERROR':
93 unexpectedErrorCallback({target: {error: data.error}});
94 break;
95 case 'BLOCKED':
96 unexpectedBlockedCallback({target: {error: data.error}});
97 break;
98 case 'LOG':
99 log('WORKER: ' + data.message);
100 break;
101 case 'ERROR':
102 error('WORKER: ' + data.message);
103 break;
106 worker.onerror = function (event) {
107 error("Error in: " + event.filename + "(" + event.lineno + "): " +
108 event.message);
111 $('#offline').addEventListener('click', goOffline);
112 $('#online').addEventListener('click', goOnline);
114 var EVENT_INTERVAL = 100;
115 var eventIntervalId = 0;
117 function goOffline() {
118 if (offline)
119 return;
120 offline = true;
121 $('#offline').disabled = offline;
122 $('#online').disabled = !offline;
123 $('#state').innerHTML = 'offline';
124 log('offline');
126 worker.postMessage({type: 'offline'});
128 eventIntervalId = setInterval(recordEvent, EVENT_INTERVAL);
131 function goOnline() {
132 if (!offline)
133 return;
134 offline = false;
135 $('#offline').disabled = offline;
136 $('#online').disabled = !offline;
137 $('#state').innerHTML = 'online';
138 log('online');
140 worker.postMessage({type: 'online'});
142 setTimeout(playbackEvents, 100);
143 clearInterval(eventIntervalId);
144 eventIntervalId = 0;
147 function recordEvent() {
148 if (!db) {
149 error("Database not initialized");
150 return;
153 var transaction = db.transaction(['user-events'], 'readwrite');
154 var store = transaction.objectStore('user-events');
155 var record = {
156 // 'sequence' key will be generated
157 docid: Math.floor(Math.random() * MAX_DOC_ID),
158 timestamp: new Date(),
159 data: randomString(256)
162 log('putting user event');
163 var request = store.put(record);
164 request.onerror = unexpectedErrorCallback;
165 transaction.onabort = unexpectedAbortCallback;
166 transaction.oncomplete = function () {
167 log('put user event');
171 function sendEvent(record, callback) {
172 setTimeout(
173 function () {
174 if (offline)
175 callback(false);
176 else {
177 var serialization = JSON.stringify(record);
178 callback(true);
181 Math.random() * 200); // Simulate network jitter
184 var PLAYBACK_NONE = 0;
185 var PLAYBACK_SUCCESS = 1;
186 var PLAYBACK_FAILURE = 2;
188 function playbackEvent(callback) {
189 log('playbackEvent');
190 var result = false;
191 var transaction = db.transaction(['user-events'], 'readonly');
192 transaction.onabort = unexpectedAbortCallback;
193 var store = transaction.objectStore('user-events');
194 var cursorRequest = store.openCursor();
195 cursorRequest.onerror = unexpectedErrorCallback;
196 cursorRequest.onsuccess = function () {
197 var cursor = cursorRequest.result;
198 if (cursor) {
199 var record = cursor.value;
200 var key = cursor.key;
201 // NOTE: sendEvent is asynchronous so transaction should finish
202 sendEvent(
203 record,
204 function (success) {
205 if (success) {
206 // Use another transaction to delete event
207 var transaction = db.transaction(['user-events'], 'readwrite');
208 transaction.onabort = unexpectedAbortCallback;
209 var store = transaction.objectStore('user-events');
210 var deleteRequest = store.delete(key);
211 deleteRequest.onerror = unexpectedErrorCallback;
212 transaction.oncomplete = function () {
213 // successfully sent and deleted event
214 callback(PLAYBACK_SUCCESS);
216 } else {
217 // No progress made
218 callback(PLAYBACK_FAILURE);
221 } else {
222 callback(PLAYBACK_NONE);
227 var playback = false;
229 function playbackEvents() {
230 log('playbackEvents');
231 if (!db) {
232 error("Database not initialized");
233 return;
236 if (playback)
237 return;
239 playback = true;
240 log("Playing back events");
242 function nextEvent() {
243 playbackEvent(
244 function (result) {
245 switch (result) {
246 case PLAYBACK_NONE:
247 playback = false;
248 log("Done playing back events");
249 return;
250 case PLAYBACK_SUCCESS:
251 setTimeout(nextEvent, 0);
252 return;
253 case PLAYBACK_FAILURE:
254 playback = false;
255 log("Failure during playback (dropped offline?)");
256 return;
261 nextEvent();
264 function randomString(len) {
265 var s = '';
266 while (len--)
267 s += Math.floor((Math.random() * 36)).toString(36);
268 return s;
271 window.onload = function () {
272 log("initializing...");
273 initdb();