commonroutesServer/www/platforms/android/assets/www/cordova.js
www/platforms/android/assets/www/cordova.jsRaw
1// Platform: android
2// d403ce434788ffe1937711d6ebcbcc837fcbcb14
3/*
4 Licensed to the Apache Software Foundation (ASF) under one
5 or more contributor license agreements. See the NOTICE file
6 distributed with this work for additional information
7 regarding copyright ownership. The ASF licenses this file
8 to you under the Apache License, Version 2.0 (the
9 "License"); you may not use this file except in compliance
10 with the License. You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing,
15 software distributed under the License is distributed on an
16 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 KIND, either express or implied. See the License for the
18 specific language governing permissions and limitations
19 under the License.
20*/
21;(function() {
22var PLATFORM_VERSION_BUILD_LABEL = '5.2.2';
23// file: src/scripts/require.js
24
25/*jshint -W079 */
26/*jshint -W020 */
27
28var require,
29 define;
30
31(function () {
32 var modules = {},
33 // Stack of moduleIds currently being built.
34 requireStack = [],
35 // Map of module ID -> index into requireStack of modules currently being built.
36 inProgressModules = {},
37 SEPARATOR = ".";
38
39
40
41 function build(module) {
42 var factory = module.factory,
43 localRequire = function (id) {
44 var resultantId = id;
45 //Its a relative path, so lop off the last portion and add the id (minus "./")
46 if (id.charAt(0) === ".") {
47 resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
48 }
49 return require(resultantId);
50 };
51 module.exports = {};
52 delete module.factory;
53 factory(localRequire, module.exports, module);
54 return module.exports;
55 }
56
57 require = function (id) {
58 if (!modules[id]) {
59 throw "module " + id + " not found";
60 } else if (id in inProgressModules) {
61 var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
62 throw "Cycle in require graph: " + cycle;
63 }
64 if (modules[id].factory) {
65 try {
66 inProgressModules[id] = requireStack.length;
67 requireStack.push(id);
68 return build(modules[id]);
69 } finally {
70 delete inProgressModules[id];
71 requireStack.pop();
72 }
73 }
74 return modules[id].exports;
75 };
76
77 define = function (id, factory) {
78 if (modules[id]) {
79 throw "module " + id + " already defined";
80 }
81
82 modules[id] = {
83 id: id,
84 factory: factory
85 };
86 };
87
88 define.remove = function (id) {
89 delete modules[id];
90 };
91
92 define.moduleMap = modules;
93})();
94
95//Export for use in node
96if (typeof module === "object" && typeof require === "function") {
97 module.exports.require = require;
98 module.exports.define = define;
99}
100
101// file: src/cordova.js
102define("cordova", function(require, exports, module) {
103
104// Workaround for Windows 10 in hosted environment case
105// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
106if (window.cordova && !(window.cordova instanceof HTMLElement)) {
107 throw new Error("cordova already defined");
108}
109
110
111var channel = require('cordova/channel');
112var platform = require('cordova/platform');
113
114
115/**
116 * Intercept calls to addEventListener + removeEventListener and handle deviceready,
117 * resume, and pause events.
118 */
119var m_document_addEventListener = document.addEventListener;
120var m_document_removeEventListener = document.removeEventListener;
121var m_window_addEventListener = window.addEventListener;
122var m_window_removeEventListener = window.removeEventListener;
123
124/**
125 * Houses custom event handlers to intercept on document + window event listeners.
126 */
127var documentEventHandlers = {},
128 windowEventHandlers = {};
129
130document.addEventListener = function(evt, handler, capture) {
131 var e = evt.toLowerCase();
132 if (typeof documentEventHandlers[e] != 'undefined') {
133 documentEventHandlers[e].subscribe(handler);
134 } else {
135 m_document_addEventListener.call(document, evt, handler, capture);
136 }
137};
138
139window.addEventListener = function(evt, handler, capture) {
140 var e = evt.toLowerCase();
141 if (typeof windowEventHandlers[e] != 'undefined') {
142 windowEventHandlers[e].subscribe(handler);
143 } else {
144 m_window_addEventListener.call(window, evt, handler, capture);
145 }
146};
147
148document.removeEventListener = function(evt, handler, capture) {
149 var e = evt.toLowerCase();
150 // If unsubscribing from an event that is handled by a plugin
151 if (typeof documentEventHandlers[e] != "undefined") {
152 documentEventHandlers[e].unsubscribe(handler);
153 } else {
154 m_document_removeEventListener.call(document, evt, handler, capture);
155 }
156};
157
158window.removeEventListener = function(evt, handler, capture) {
159 var e = evt.toLowerCase();
160 // If unsubscribing from an event that is handled by a plugin
161 if (typeof windowEventHandlers[e] != "undefined") {
162 windowEventHandlers[e].unsubscribe(handler);
163 } else {
164 m_window_removeEventListener.call(window, evt, handler, capture);
165 }
166};
167
168function createEvent(type, data) {
169 var event = document.createEvent('Events');
170 event.initEvent(type, false, false);
171 if (data) {
172 for (var i in data) {
173 if (data.hasOwnProperty(i)) {
174 event[i] = data[i];
175 }
176 }
177 }
178 return event;
179}
180
181
182var cordova = {
183 define:define,
184 require:require,
185 version:PLATFORM_VERSION_BUILD_LABEL,
186 platformVersion:PLATFORM_VERSION_BUILD_LABEL,
187 platformId:platform.id,
188 /**
189 * Methods to add/remove your own addEventListener hijacking on document + window.
190 */
191 addWindowEventHandler:function(event) {
192 return (windowEventHandlers[event] = channel.create(event));
193 },
194 addStickyDocumentEventHandler:function(event) {
195 return (documentEventHandlers[event] = channel.createSticky(event));
196 },
197 addDocumentEventHandler:function(event) {
198 return (documentEventHandlers[event] = channel.create(event));
199 },
200 removeWindowEventHandler:function(event) {
201 delete windowEventHandlers[event];
202 },
203 removeDocumentEventHandler:function(event) {
204 delete documentEventHandlers[event];
205 },
206 /**
207 * Retrieve original event handlers that were replaced by Cordova
208 *
209 * @return object
210 */
211 getOriginalHandlers: function() {
212 return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
213 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
214 },
215 /**
216 * Method to fire event from native code
217 * bNoDetach is required for events which cause an exception which needs to be caught in native code
218 */
219 fireDocumentEvent: function(type, data, bNoDetach) {
220 var evt = createEvent(type, data);
221 if (typeof documentEventHandlers[type] != 'undefined') {
222 if( bNoDetach ) {
223 documentEventHandlers[type].fire(evt);
224 }
225 else {
226 setTimeout(function() {
227 // Fire deviceready on listeners that were registered before cordova.js was loaded.
228 if (type == 'deviceready') {
229 document.dispatchEvent(evt);
230 }
231 documentEventHandlers[type].fire(evt);
232 }, 0);
233 }
234 } else {
235 document.dispatchEvent(evt);
236 }
237 },
238 fireWindowEvent: function(type, data) {
239 var evt = createEvent(type,data);
240 if (typeof windowEventHandlers[type] != 'undefined') {
241 setTimeout(function() {
242 windowEventHandlers[type].fire(evt);
243 }, 0);
244 } else {
245 window.dispatchEvent(evt);
246 }
247 },
248
249 /**
250 * Plugin callback mechanism.
251 */
252 // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
253 // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
254 callbackId: Math.floor(Math.random() * 2000000000),
255 callbacks: {},
256 callbackStatus: {
257 NO_RESULT: 0,
258 OK: 1,
259 CLASS_NOT_FOUND_EXCEPTION: 2,
260 ILLEGAL_ACCESS_EXCEPTION: 3,
261 INSTANTIATION_EXCEPTION: 4,
262 MALFORMED_URL_EXCEPTION: 5,
263 IO_EXCEPTION: 6,
264 INVALID_ACTION: 7,
265 JSON_EXCEPTION: 8,
266 ERROR: 9
267 },
268
269 /**
270 * Called by native code when returning successful result from an action.
271 */
272 callbackSuccess: function(callbackId, args) {
273 cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
274 },
275
276 /**
277 * Called by native code when returning error result from an action.
278 */
279 callbackError: function(callbackId, args) {
280 // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
281 // Derive success from status.
282 cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
283 },
284
285 /**
286 * Called by native code when returning the result from an action.
287 */
288 callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
289 try {
290 var callback = cordova.callbacks[callbackId];
291 if (callback) {
292 if (isSuccess && status == cordova.callbackStatus.OK) {
293 callback.success && callback.success.apply(null, args);
294 } else if (!isSuccess) {
295 callback.fail && callback.fail.apply(null, args);
296 }
297 /*
298 else
299 Note, this case is intentionally not caught.
300 this can happen if isSuccess is true, but callbackStatus is NO_RESULT
301 which is used to remove a callback from the list without calling the callbacks
302 typically keepCallback is false in this case
303 */
304 // Clear callback if not expecting any more results
305 if (!keepCallback) {
306 delete cordova.callbacks[callbackId];
307 }
308 }
309 }
310 catch (err) {
311 var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
312 console && console.log && console.log(msg);
313 cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
314 throw err;
315 }
316 },
317 addConstructor: function(func) {
318 channel.onCordovaReady.subscribe(function() {
319 try {
320 func();
321 } catch(e) {
322 console.log("Failed to run constructor: " + e);
323 }
324 });
325 }
326};
327
328
329module.exports = cordova;
330
331});
332
333// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
334define("cordova/android/nativeapiprovider", function(require, exports, module) {
335
336/**
337 * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
338 */
339
340var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
341var currentApi = nativeApi;
342
343module.exports = {
344 get: function() { return currentApi; },
345 setPreferPrompt: function(value) {
346 currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
347 },
348 // Used only by tests.
349 set: function(value) {
350 currentApi = value;
351 }
352};
353
354});
355
356// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
357define("cordova/android/promptbasednativeapi", function(require, exports, module) {
358
359/**
360 * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
361 * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
362 */
363
364module.exports = {
365 exec: function(bridgeSecret, service, action, callbackId, argsJson) {
366 return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
367 },
368 setNativeToJsBridgeMode: function(bridgeSecret, value) {
369 prompt(value, 'gap_bridge_mode:' + bridgeSecret);
370 },
371 retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
372 return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
373 }
374};
375
376});
377
378// file: src/common/argscheck.js
379define("cordova/argscheck", function(require, exports, module) {
380
381var utils = require('cordova/utils');
382
383var moduleExports = module.exports;
384
385var typeMap = {
386 'A': 'Array',
387 'D': 'Date',
388 'N': 'Number',
389 'S': 'String',
390 'F': 'Function',
391 'O': 'Object'
392};
393
394function extractParamName(callee, argIndex) {
395 return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
396}
397
398function checkArgs(spec, functionName, args, opt_callee) {
399 if (!moduleExports.enableChecks) {
400 return;
401 }
402 var errMsg = null;
403 var typeName;
404 for (var i = 0; i < spec.length; ++i) {
405 var c = spec.charAt(i),
406 cUpper = c.toUpperCase(),
407 arg = args[i];
408 // Asterix means allow anything.
409 if (c == '*') {
410 continue;
411 }
412 typeName = utils.typeName(arg);
413 if ((arg === null || arg === undefined) && c == cUpper) {
414 continue;
415 }
416 if (typeName != typeMap[cUpper]) {
417 errMsg = 'Expected ' + typeMap[cUpper];
418 break;
419 }
420 }
421 if (errMsg) {
422 errMsg += ', but got ' + typeName + '.';
423 errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
424 // Don't log when running unit tests.
425 if (typeof jasmine == 'undefined') {
426 console.error(errMsg);
427 }
428 throw TypeError(errMsg);
429 }
430}
431
432function getValue(value, defaultValue) {
433 return value === undefined ? defaultValue : value;
434}
435
436moduleExports.checkArgs = checkArgs;
437moduleExports.getValue = getValue;
438moduleExports.enableChecks = true;
439
440
441});
442
443// file: src/common/base64.js
444define("cordova/base64", function(require, exports, module) {
445
446var base64 = exports;
447
448base64.fromArrayBuffer = function(arrayBuffer) {
449 var array = new Uint8Array(arrayBuffer);
450 return uint8ToBase64(array);
451};
452
453base64.toArrayBuffer = function(str) {
454 var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
455 var arrayBuffer = new ArrayBuffer(decodedStr.length);
456 var array = new Uint8Array(arrayBuffer);
457 for (var i=0, len=decodedStr.length; i < len; i++) {
458 array[i] = decodedStr.charCodeAt(i);
459 }
460 return arrayBuffer;
461};
462
463//------------------------------------------------------------------------------
464
465/* This code is based on the performance tests at http://jsperf.com/b64tests
466 * This 12-bit-at-a-time algorithm was the best performing version on all
467 * platforms tested.
468 */
469
470var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
471var b64_12bit;
472
473var b64_12bitTable = function() {
474 b64_12bit = [];
475 for (var i=0; i<64; i++) {
476 for (var j=0; j<64; j++) {
477 b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j];
478 }
479 }
480 b64_12bitTable = function() { return b64_12bit; };
481 return b64_12bit;
482};
483
484function uint8ToBase64(rawData) {
485 var numBytes = rawData.byteLength;
486 var output="";
487 var segment;
488 var table = b64_12bitTable();
489 for (var i=0;i<numBytes-2;i+=3) {
490 segment = (rawData[i] << 16) + (rawData[i+1] << 8) + rawData[i+2];
491 output += table[segment >> 12];
492 output += table[segment & 0xfff];
493 }
494 if (numBytes - i == 2) {
495 segment = (rawData[i] << 16) + (rawData[i+1] << 8);
496 output += table[segment >> 12];
497 output += b64_6bit[(segment & 0xfff) >> 6];
498 output += '=';
499 } else if (numBytes - i == 1) {
500 segment = (rawData[i] << 16);
501 output += table[segment >> 12];
502 output += '==';
503 }
504 return output;
505}
506
507});
508
509// file: src/common/builder.js
510define("cordova/builder", function(require, exports, module) {
511
512var utils = require('cordova/utils');
513
514function each(objects, func, context) {
515 for (var prop in objects) {
516 if (objects.hasOwnProperty(prop)) {
517 func.apply(context, [objects[prop], prop]);
518 }
519 }
520}
521
522function clobber(obj, key, value) {
523 exports.replaceHookForTesting(obj, key);
524 var needsProperty = false;
525 try {
526 obj[key] = value;
527 } catch (e) {
528 needsProperty = true;
529 }
530 // Getters can only be overridden by getters.
531 if (needsProperty || obj[key] !== value) {
532 utils.defineGetter(obj, key, function() {
533 return value;
534 });
535 }
536}
537
538function assignOrWrapInDeprecateGetter(obj, key, value, message) {
539 if (message) {
540 utils.defineGetter(obj, key, function() {
541 console.log(message);
542 delete obj[key];
543 clobber(obj, key, value);
544 return value;
545 });
546 } else {
547 clobber(obj, key, value);
548 }
549}
550
551function include(parent, objects, clobber, merge) {
552 each(objects, function (obj, key) {
553 try {
554 var result = obj.path ? require(obj.path) : {};
555
556 if (clobber) {
557 // Clobber if it doesn't exist.
558 if (typeof parent[key] === 'undefined') {
559 assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
560 } else if (typeof obj.path !== 'undefined') {
561 // If merging, merge properties onto parent, otherwise, clobber.
562 if (merge) {
563 recursiveMerge(parent[key], result);
564 } else {
565 assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
566 }
567 }
568 result = parent[key];
569 } else {
570 // Overwrite if not currently defined.
571 if (typeof parent[key] == 'undefined') {
572 assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
573 } else {
574 // Set result to what already exists, so we can build children into it if they exist.
575 result = parent[key];
576 }
577 }
578
579 if (obj.children) {
580 include(result, obj.children, clobber, merge);
581 }
582 } catch(e) {
583 utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
584 }
585 });
586}
587
588/**
589 * Merge properties from one object onto another recursively. Properties from
590 * the src object will overwrite existing target property.
591 *
592 * @param target Object to merge properties into.
593 * @param src Object to merge properties from.
594 */
595function recursiveMerge(target, src) {
596 for (var prop in src) {
597 if (src.hasOwnProperty(prop)) {
598 if (target.prototype && target.prototype.constructor === target) {
599 // If the target object is a constructor override off prototype.
600 clobber(target.prototype, prop, src[prop]);
601 } else {
602 if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
603 recursiveMerge(target[prop], src[prop]);
604 } else {
605 clobber(target, prop, src[prop]);
606 }
607 }
608 }
609 }
610}
611
612exports.buildIntoButDoNotClobber = function(objects, target) {
613 include(target, objects, false, false);
614};
615exports.buildIntoAndClobber = function(objects, target) {
616 include(target, objects, true, false);
617};
618exports.buildIntoAndMerge = function(objects, target) {
619 include(target, objects, true, true);
620};
621exports.recursiveMerge = recursiveMerge;
622exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
623exports.replaceHookForTesting = function() {};
624
625});
626
627// file: src/common/channel.js
628define("cordova/channel", function(require, exports, module) {
629
630var utils = require('cordova/utils'),
631 nextGuid = 1;
632
633/**
634 * Custom pub-sub "channel" that can have functions subscribed to it
635 * This object is used to define and control firing of events for
636 * cordova initialization, as well as for custom events thereafter.
637 *
638 * The order of events during page load and Cordova startup is as follows:
639 *
640 * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
641 * onNativeReady* Internal event that indicates the Cordova native side is ready.
642 * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
643 * onDeviceReady* User event fired to indicate that Cordova is ready
644 * onResume User event fired to indicate a start/resume lifecycle event
645 * onPause User event fired to indicate a pause lifecycle event
646 *
647 * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
648 * All listeners that subscribe after the event is fired will be executed right away.
649 *
650 * The only Cordova events that user code should register for are:
651 * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
652 * pause App has moved to background
653 * resume App has returned to foreground
654 *
655 * Listeners can be registered as:
656 * document.addEventListener("deviceready", myDeviceReadyListener, false);
657 * document.addEventListener("resume", myResumeListener, false);
658 * document.addEventListener("pause", myPauseListener, false);
659 *
660 * The DOM lifecycle events should be used for saving and restoring state
661 * window.onload
662 * window.onunload
663 *
664 */
665
666/**
667 * Channel
668 * @constructor
669 * @param type String the channel name
670 */
671var Channel = function(type, sticky) {
672 this.type = type;
673 // Map of guid -> function.
674 this.handlers = {};
675 // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
676 this.state = sticky ? 1 : 0;
677 // Used in sticky mode to remember args passed to fire().
678 this.fireArgs = null;
679 // Used by onHasSubscribersChange to know if there are any listeners.
680 this.numHandlers = 0;
681 // Function that is called when the first listener is subscribed, or when
682 // the last listener is unsubscribed.
683 this.onHasSubscribersChange = null;
684},
685 channel = {
686 /**
687 * Calls the provided function only after all of the channels specified
688 * have been fired. All channels must be sticky channels.
689 */
690 join: function(h, c) {
691 var len = c.length,
692 i = len,
693 f = function() {
694 if (!(--i)) h();
695 };
696 for (var j=0; j<len; j++) {
697 if (c[j].state === 0) {
698 throw Error('Can only use join with sticky channels.');
699 }
700 c[j].subscribe(f);
701 }
702 if (!len) h();
703 },
704 create: function(type) {
705 return channel[type] = new Channel(type, false);
706 },
707 createSticky: function(type) {
708 return channel[type] = new Channel(type, true);
709 },
710
711 /**
712 * cordova Channels that must fire before "deviceready" is fired.
713 */
714 deviceReadyChannelsArray: [],
715 deviceReadyChannelsMap: {},
716
717 /**
718 * Indicate that a feature needs to be initialized before it is ready to be used.
719 * This holds up Cordova's "deviceready" event until the feature has been initialized
720 * and Cordova.initComplete(feature) is called.
721 *
722 * @param feature {String} The unique feature name
723 */
724 waitForInitialization: function(feature) {
725 if (feature) {
726 var c = channel[feature] || this.createSticky(feature);
727 this.deviceReadyChannelsMap[feature] = c;
728 this.deviceReadyChannelsArray.push(c);
729 }
730 },
731
732 /**
733 * Indicate that initialization code has completed and the feature is ready to be used.
734 *
735 * @param feature {String} The unique feature name
736 */
737 initializationComplete: function(feature) {
738 var c = this.deviceReadyChannelsMap[feature];
739 if (c) {
740 c.fire();
741 }
742 }
743 };
744
745function forceFunction(f) {
746 if (typeof f != 'function') throw "Function required as first argument!";
747}
748
749/**
750 * Subscribes the given function to the channel. Any time that
751 * Channel.fire is called so too will the function.
752 * Optionally specify an execution context for the function
753 * and a guid that can be used to stop subscribing to the channel.
754 * Returns the guid.
755 */
756Channel.prototype.subscribe = function(f, c) {
757 // need a function to call
758 forceFunction(f);
759 if (this.state == 2) {
760 f.apply(c || this, this.fireArgs);
761 return;
762 }
763
764 var func = f,
765 guid = f.observer_guid;
766 if (typeof c == "object") { func = utils.close(c, f); }
767
768 if (!guid) {
769 // first time any channel has seen this subscriber
770 guid = '' + nextGuid++;
771 }
772 func.observer_guid = guid;
773 f.observer_guid = guid;
774
775 // Don't add the same handler more than once.
776 if (!this.handlers[guid]) {
777 this.handlers[guid] = func;
778 this.numHandlers++;
779 if (this.numHandlers == 1) {
780 this.onHasSubscribersChange && this.onHasSubscribersChange();
781 }
782 }
783};
784
785/**
786 * Unsubscribes the function with the given guid from the channel.
787 */
788Channel.prototype.unsubscribe = function(f) {
789 // need a function to unsubscribe
790 forceFunction(f);
791
792 var guid = f.observer_guid,
793 handler = this.handlers[guid];
794 if (handler) {
795 delete this.handlers[guid];
796 this.numHandlers--;
797 if (this.numHandlers === 0) {
798 this.onHasSubscribersChange && this.onHasSubscribersChange();
799 }
800 }
801};
802
803/**
804 * Calls all functions subscribed to this channel.
805 */
806Channel.prototype.fire = function(e) {
807 var fail = false,
808 fireArgs = Array.prototype.slice.call(arguments);
809 // Apply stickiness.
810 if (this.state == 1) {
811 this.state = 2;
812 this.fireArgs = fireArgs;
813 }
814 if (this.numHandlers) {
815 // Copy the values first so that it is safe to modify it from within
816 // callbacks.
817 var toCall = [];
818 for (var item in this.handlers) {
819 toCall.push(this.handlers[item]);
820 }
821 for (var i = 0; i < toCall.length; ++i) {
822 toCall[i].apply(this, fireArgs);
823 }
824 if (this.state == 2 && this.numHandlers) {
825 this.numHandlers = 0;
826 this.handlers = {};
827 this.onHasSubscribersChange && this.onHasSubscribersChange();
828 }
829 }
830};
831
832
833// defining them here so they are ready super fast!
834// DOM event that is received when the web page is loaded and parsed.
835channel.createSticky('onDOMContentLoaded');
836
837// Event to indicate the Cordova native side is ready.
838channel.createSticky('onNativeReady');
839
840// Event to indicate that all Cordova JavaScript objects have been created
841// and it's time to run plugin constructors.
842channel.createSticky('onCordovaReady');
843
844// Event to indicate that all automatically loaded JS plugins are loaded and ready.
845// FIXME remove this
846channel.createSticky('onPluginsReady');
847
848// Event to indicate that Cordova is ready
849channel.createSticky('onDeviceReady');
850
851// Event to indicate a resume lifecycle event
852channel.create('onResume');
853
854// Event to indicate a pause lifecycle event
855channel.create('onPause');
856
857// Channels that must fire before "deviceready" is fired.
858channel.waitForInitialization('onCordovaReady');
859channel.waitForInitialization('onDOMContentLoaded');
860
861module.exports = channel;
862
863});
864
865// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/exec.js
866define("cordova/exec", function(require, exports, module) {
867
868/**
869 * Execute a cordova command. It is up to the native side whether this action
870 * is synchronous or asynchronous. The native side can return:
871 * Synchronous: PluginResult object as a JSON string
872 * Asynchronous: Empty string ""
873 * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
874 * depending upon the result of the action.
875 *
876 * @param {Function} success The success callback
877 * @param {Function} fail The fail callback
878 * @param {String} service The name of the service to use
879 * @param {String} action Action to be run in cordova
880 * @param {String[]} [args] Zero or more arguments to pass to the method
881 */
882var cordova = require('cordova'),
883 nativeApiProvider = require('cordova/android/nativeapiprovider'),
884 utils = require('cordova/utils'),
885 base64 = require('cordova/base64'),
886 channel = require('cordova/channel'),
887 jsToNativeModes = {
888 PROMPT: 0,
889 JS_OBJECT: 1
890 },
891 nativeToJsModes = {
892 // Polls for messages using the JS->Native bridge.
893 POLLING: 0,
894 // For LOAD_URL to be viable, it would need to have a work-around for
895 // the bug where the soft-keyboard gets dismissed when a message is sent.
896 LOAD_URL: 1,
897 // For the ONLINE_EVENT to be viable, it would need to intercept all event
898 // listeners (both through addEventListener and window.ononline) as well
899 // as set the navigator property itself.
900 ONLINE_EVENT: 2
901 },
902 jsToNativeBridgeMode, // Set lazily.
903 nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT,
904 pollEnabled = false,
905 bridgeSecret = -1;
906
907var messagesFromNative = [];
908var isProcessing = false;
909var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
910var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
911
912function androidExec(success, fail, service, action, args) {
913 if (bridgeSecret < 0) {
914 // If we ever catch this firing, we'll need to queue up exec()s
915 // and fire them once we get a secret. For now, I don't think
916 // it's possible for exec() to be called since plugins are parsed but
917 // not run until until after onNativeReady.
918 throw new Error('exec() called without bridgeSecret');
919 }
920 // Set default bridge modes if they have not already been set.
921 // By default, we use the failsafe, since addJavascriptInterface breaks too often
922 if (jsToNativeBridgeMode === undefined) {
923 androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
924 }
925
926 // Process any ArrayBuffers in the args into a string.
927 for (var i = 0; i < args.length; i++) {
928 if (utils.typeName(args[i]) == 'ArrayBuffer') {
929 args[i] = base64.fromArrayBuffer(args[i]);
930 }
931 }
932
933 var callbackId = service + cordova.callbackId++,
934 argsJson = JSON.stringify(args);
935
936 if (success || fail) {
937 cordova.callbacks[callbackId] = {success:success, fail:fail};
938 }
939
940 var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
941 // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
942 // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
943 if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
944 androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
945 androidExec(success, fail, service, action, args);
946 androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
947 } else if (msgs) {
948 messagesFromNative.push(msgs);
949 // Always process async to avoid exceptions messing up stack.
950 nextTick(processMessages);
951 }
952}
953
954androidExec.init = function() {
955 bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
956 channel.onNativeReady.fire();
957};
958
959function pollOnceFromOnlineEvent() {
960 pollOnce(true);
961}
962
963function pollOnce(opt_fromOnlineEvent) {
964 if (bridgeSecret < 0) {
965 // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
966 // We know there's nothing to retrieve, so no need to poll.
967 return;
968 }
969 var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
970 if (msgs) {
971 messagesFromNative.push(msgs);
972 // Process sync since we know we're already top-of-stack.
973 processMessages();
974 }
975}
976
977function pollingTimerFunc() {
978 if (pollEnabled) {
979 pollOnce();
980 setTimeout(pollingTimerFunc, 50);
981 }
982}
983
984function hookOnlineApis() {
985 function proxyEvent(e) {
986 cordova.fireWindowEvent(e.type);
987 }
988 // The network module takes care of firing online and offline events.
989 // It currently fires them only on document though, so we bridge them
990 // to window here (while first listening for exec()-releated online/offline
991 // events).
992 window.addEventListener('online', pollOnceFromOnlineEvent, false);
993 window.addEventListener('offline', pollOnceFromOnlineEvent, false);
994 cordova.addWindowEventHandler('online');
995 cordova.addWindowEventHandler('offline');
996 document.addEventListener('online', proxyEvent, false);
997 document.addEventListener('offline', proxyEvent, false);
998}
999
1000hookOnlineApis();
1001
1002androidExec.jsToNativeModes = jsToNativeModes;
1003androidExec.nativeToJsModes = nativeToJsModes;
1004
1005androidExec.setJsToNativeBridgeMode = function(mode) {
1006 if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
1007 mode = jsToNativeModes.PROMPT;
1008 }
1009 nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
1010 jsToNativeBridgeMode = mode;
1011};
1012
1013androidExec.setNativeToJsBridgeMode = function(mode) {
1014 if (mode == nativeToJsBridgeMode) {
1015 return;
1016 }
1017 if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
1018 pollEnabled = false;
1019 }
1020
1021 nativeToJsBridgeMode = mode;
1022 // Tell the native side to switch modes.
1023 // Otherwise, it will be set by androidExec.init()
1024 if (bridgeSecret >= 0) {
1025 nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
1026 }
1027
1028 if (mode == nativeToJsModes.POLLING) {
1029 pollEnabled = true;
1030 setTimeout(pollingTimerFunc, 1);
1031 }
1032};
1033
1034function buildPayload(payload, message) {
1035 var payloadKind = message.charAt(0);
1036 if (payloadKind == 's') {
1037 payload.push(message.slice(1));
1038 } else if (payloadKind == 't') {
1039 payload.push(true);
1040 } else if (payloadKind == 'f') {
1041 payload.push(false);
1042 } else if (payloadKind == 'N') {
1043 payload.push(null);
1044 } else if (payloadKind == 'n') {
1045 payload.push(+message.slice(1));
1046 } else if (payloadKind == 'A') {
1047 var data = message.slice(1);
1048 payload.push(base64.toArrayBuffer(data));
1049 } else if (payloadKind == 'S') {
1050 payload.push(window.atob(message.slice(1)));
1051 } else if (payloadKind == 'M') {
1052 var multipartMessages = message.slice(1);
1053 while (multipartMessages !== "") {
1054 var spaceIdx = multipartMessages.indexOf(' ');
1055 var msgLen = +multipartMessages.slice(0, spaceIdx);
1056 var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
1057 multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
1058 buildPayload(payload, multipartMessage);
1059 }
1060 } else {
1061 payload.push(JSON.parse(message));
1062 }
1063}
1064
1065// Processes a single message, as encoded by NativeToJsMessageQueue.java.
1066function processMessage(message) {
1067 var firstChar = message.charAt(0);
1068 if (firstChar == 'J') {
1069 // This is deprecated on the .java side. It doesn't work with CSP enabled.
1070 eval(message.slice(1));
1071 } else if (firstChar == 'S' || firstChar == 'F') {
1072 var success = firstChar == 'S';
1073 var keepCallback = message.charAt(1) == '1';
1074 var spaceIdx = message.indexOf(' ', 2);
1075 var status = +message.slice(2, spaceIdx);
1076 var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
1077 var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
1078 var payloadMessage = message.slice(nextSpaceIdx + 1);
1079 var payload = [];
1080 buildPayload(payload, payloadMessage);
1081 cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
1082 } else {
1083 console.log("processMessage failed: invalid message: " + JSON.stringify(message));
1084 }
1085}
1086
1087function processMessages() {
1088 // Check for the reentrant case.
1089 if (isProcessing) {
1090 return;
1091 }
1092 if (messagesFromNative.length === 0) {
1093 return;
1094 }
1095 isProcessing = true;
1096 try {
1097 var msg = popMessageFromQueue();
1098 // The Java side can send a * message to indicate that it
1099 // still has messages waiting to be retrieved.
1100 if (msg == '*' && messagesFromNative.length === 0) {
1101 nextTick(pollOnce);
1102 return;
1103 }
1104 processMessage(msg);
1105 } finally {
1106 isProcessing = false;
1107 if (messagesFromNative.length > 0) {
1108 nextTick(processMessages);
1109 }
1110 }
1111}
1112
1113function popMessageFromQueue() {
1114 var messageBatch = messagesFromNative.shift();
1115 if (messageBatch == '*') {
1116 return '*';
1117 }
1118
1119 var spaceIdx = messageBatch.indexOf(' ');
1120 var msgLen = +messageBatch.slice(0, spaceIdx);
1121 var message = messageBatch.substr(spaceIdx + 1, msgLen);
1122 messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
1123 if (messageBatch) {
1124 messagesFromNative.unshift(messageBatch);
1125 }
1126 return message;
1127}
1128
1129module.exports = androidExec;
1130
1131});
1132
1133// file: src/common/exec/proxy.js
1134define("cordova/exec/proxy", function(require, exports, module) {
1135
1136
1137// internal map of proxy function
1138var CommandProxyMap = {};
1139
1140module.exports = {
1141
1142 // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
1143 add:function(id,proxyObj) {
1144 console.log("adding proxy for " + id);
1145 CommandProxyMap[id] = proxyObj;
1146 return proxyObj;
1147 },
1148
1149 // cordova.commandProxy.remove("Accelerometer");
1150 remove:function(id) {
1151 var proxy = CommandProxyMap[id];
1152 delete CommandProxyMap[id];
1153 CommandProxyMap[id] = null;
1154 return proxy;
1155 },
1156
1157 get:function(service,action) {
1158 return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
1159 }
1160};
1161});
1162
1163// file: src/common/init.js
1164define("cordova/init", function(require, exports, module) {
1165
1166var channel = require('cordova/channel');
1167var cordova = require('cordova');
1168var modulemapper = require('cordova/modulemapper');
1169var platform = require('cordova/platform');
1170var pluginloader = require('cordova/pluginloader');
1171var utils = require('cordova/utils');
1172
1173var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
1174
1175function logUnfiredChannels(arr) {
1176 for (var i = 0; i < arr.length; ++i) {
1177 if (arr[i].state != 2) {
1178 console.log('Channel not fired: ' + arr[i].type);
1179 }
1180 }
1181}
1182
1183window.setTimeout(function() {
1184 if (channel.onDeviceReady.state != 2) {
1185 console.log('deviceready has not fired after 5 seconds.');
1186 logUnfiredChannels(platformInitChannelsArray);
1187 logUnfiredChannels(channel.deviceReadyChannelsArray);
1188 }
1189}, 5000);
1190
1191// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
1192// We replace it so that properties that can't be clobbered can instead be overridden.
1193function replaceNavigator(origNavigator) {
1194 var CordovaNavigator = function() {};
1195 CordovaNavigator.prototype = origNavigator;
1196 var newNavigator = new CordovaNavigator();
1197 // This work-around really only applies to new APIs that are newer than Function.bind.
1198 // Without it, APIs such as getGamepads() break.
1199 if (CordovaNavigator.bind) {
1200 for (var key in origNavigator) {
1201 if (typeof origNavigator[key] == 'function') {
1202 newNavigator[key] = origNavigator[key].bind(origNavigator);
1203 }
1204 else {
1205 (function(k) {
1206 utils.defineGetterSetter(newNavigator,key,function() {
1207 return origNavigator[k];
1208 });
1209 })(key);
1210 }
1211 }
1212 }
1213 return newNavigator;
1214}
1215
1216if (window.navigator) {
1217 window.navigator = replaceNavigator(window.navigator);
1218}
1219
1220if (!window.console) {
1221 window.console = {
1222 log: function(){}
1223 };
1224}
1225if (!window.console.warn) {
1226 window.console.warn = function(msg) {
1227 this.log("warn: " + msg);
1228 };
1229}
1230
1231// Register pause, resume and deviceready channels as events on document.
1232channel.onPause = cordova.addDocumentEventHandler('pause');
1233channel.onResume = cordova.addDocumentEventHandler('resume');
1234channel.onActivated = cordova.addDocumentEventHandler('activated');
1235channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
1236
1237// Listen for DOMContentLoaded and notify our channel subscribers.
1238if (document.readyState == 'complete' || document.readyState == 'interactive') {
1239 channel.onDOMContentLoaded.fire();
1240} else {
1241 document.addEventListener('DOMContentLoaded', function() {
1242 channel.onDOMContentLoaded.fire();
1243 }, false);
1244}
1245
1246// _nativeReady is global variable that the native side can set
1247// to signify that the native code is ready. It is a global since
1248// it may be called before any cordova JS is ready.
1249if (window._nativeReady) {
1250 channel.onNativeReady.fire();
1251}
1252
1253modulemapper.clobbers('cordova', 'cordova');
1254modulemapper.clobbers('cordova/exec', 'cordova.exec');
1255modulemapper.clobbers('cordova/exec', 'Cordova.exec');
1256
1257// Call the platform-specific initialization.
1258platform.bootstrap && platform.bootstrap();
1259
1260// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
1261// The delay allows the attached modules to be defined before the plugin loader looks for them.
1262setTimeout(function() {
1263 pluginloader.load(function() {
1264 channel.onPluginsReady.fire();
1265 });
1266}, 0);
1267
1268/**
1269 * Create all cordova objects once native side is ready.
1270 */
1271channel.join(function() {
1272 modulemapper.mapModules(window);
1273
1274 platform.initialize && platform.initialize();
1275
1276 // Fire event to notify that all objects are created
1277 channel.onCordovaReady.fire();
1278
1279 // Fire onDeviceReady event once page has fully loaded, all
1280 // constructors have run and cordova info has been received from native
1281 // side.
1282 channel.join(function() {
1283 require('cordova').fireDocumentEvent('deviceready');
1284 }, channel.deviceReadyChannelsArray);
1285
1286}, platformInitChannelsArray);
1287
1288
1289});
1290
1291// file: src/common/init_b.js
1292define("cordova/init_b", function(require, exports, module) {
1293
1294var channel = require('cordova/channel');
1295var cordova = require('cordova');
1296var modulemapper = require('cordova/modulemapper');
1297var platform = require('cordova/platform');
1298var pluginloader = require('cordova/pluginloader');
1299var utils = require('cordova/utils');
1300
1301var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
1302
1303// setting exec
1304cordova.exec = require('cordova/exec');
1305
1306function logUnfiredChannels(arr) {
1307 for (var i = 0; i < arr.length; ++i) {
1308 if (arr[i].state != 2) {
1309 console.log('Channel not fired: ' + arr[i].type);
1310 }
1311 }
1312}
1313
1314window.setTimeout(function() {
1315 if (channel.onDeviceReady.state != 2) {
1316 console.log('deviceready has not fired after 5 seconds.');
1317 logUnfiredChannels(platformInitChannelsArray);
1318 logUnfiredChannels(channel.deviceReadyChannelsArray);
1319 }
1320}, 5000);
1321
1322// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
1323// We replace it so that properties that can't be clobbered can instead be overridden.
1324function replaceNavigator(origNavigator) {
1325 var CordovaNavigator = function() {};
1326 CordovaNavigator.prototype = origNavigator;
1327 var newNavigator = new CordovaNavigator();
1328 // This work-around really only applies to new APIs that are newer than Function.bind.
1329 // Without it, APIs such as getGamepads() break.
1330 if (CordovaNavigator.bind) {
1331 for (var key in origNavigator) {
1332 if (typeof origNavigator[key] == 'function') {
1333 newNavigator[key] = origNavigator[key].bind(origNavigator);
1334 }
1335 else {
1336 (function(k) {
1337 utils.defineGetterSetter(newNavigator,key,function() {
1338 return origNavigator[k];
1339 });
1340 })(key);
1341 }
1342 }
1343 }
1344 return newNavigator;
1345}
1346if (window.navigator) {
1347 window.navigator = replaceNavigator(window.navigator);
1348}
1349
1350if (!window.console) {
1351 window.console = {
1352 log: function(){}
1353 };
1354}
1355if (!window.console.warn) {
1356 window.console.warn = function(msg) {
1357 this.log("warn: " + msg);
1358 };
1359}
1360
1361// Register pause, resume and deviceready channels as events on document.
1362channel.onPause = cordova.addDocumentEventHandler('pause');
1363channel.onResume = cordova.addDocumentEventHandler('resume');
1364channel.onActivated = cordova.addDocumentEventHandler('activated');
1365channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
1366
1367// Listen for DOMContentLoaded and notify our channel subscribers.
1368if (document.readyState == 'complete' || document.readyState == 'interactive') {
1369 channel.onDOMContentLoaded.fire();
1370} else {
1371 document.addEventListener('DOMContentLoaded', function() {
1372 channel.onDOMContentLoaded.fire();
1373 }, false);
1374}
1375
1376// _nativeReady is global variable that the native side can set
1377// to signify that the native code is ready. It is a global since
1378// it may be called before any cordova JS is ready.
1379if (window._nativeReady) {
1380 channel.onNativeReady.fire();
1381}
1382
1383// Call the platform-specific initialization.
1384platform.bootstrap && platform.bootstrap();
1385
1386// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
1387// The delay allows the attached modules to be defined before the plugin loader looks for them.
1388setTimeout(function() {
1389 pluginloader.load(function() {
1390 channel.onPluginsReady.fire();
1391 });
1392}, 0);
1393
1394/**
1395 * Create all cordova objects once native side is ready.
1396 */
1397channel.join(function() {
1398 modulemapper.mapModules(window);
1399
1400 platform.initialize && platform.initialize();
1401
1402 // Fire event to notify that all objects are created
1403 channel.onCordovaReady.fire();
1404
1405 // Fire onDeviceReady event once page has fully loaded, all
1406 // constructors have run and cordova info has been received from native
1407 // side.
1408 channel.join(function() {
1409 require('cordova').fireDocumentEvent('deviceready');
1410 }, channel.deviceReadyChannelsArray);
1411
1412}, platformInitChannelsArray);
1413
1414});
1415
1416// file: src/common/modulemapper.js
1417define("cordova/modulemapper", function(require, exports, module) {
1418
1419var builder = require('cordova/builder'),
1420 moduleMap = define.moduleMap,
1421 symbolList,
1422 deprecationMap;
1423
1424exports.reset = function() {
1425 symbolList = [];
1426 deprecationMap = {};
1427};
1428
1429function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
1430 if (!(moduleName in moduleMap)) {
1431 throw new Error('Module ' + moduleName + ' does not exist.');
1432 }
1433 symbolList.push(strategy, moduleName, symbolPath);
1434 if (opt_deprecationMessage) {
1435 deprecationMap[symbolPath] = opt_deprecationMessage;
1436 }
1437}
1438
1439// Note: Android 2.3 does have Function.bind().
1440exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
1441 addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
1442};
1443
1444exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
1445 addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
1446};
1447
1448exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
1449 addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
1450};
1451
1452exports.runs = function(moduleName) {
1453 addEntry('r', moduleName, null);
1454};
1455
1456function prepareNamespace(symbolPath, context) {
1457 if (!symbolPath) {
1458 return context;
1459 }
1460 var parts = symbolPath.split('.');
1461 var cur = context;
1462 for (var i = 0, part; part = parts[i]; ++i) {
1463 cur = cur[part] = cur[part] || {};
1464 }
1465 return cur;
1466}
1467
1468exports.mapModules = function(context) {
1469 var origSymbols = {};
1470 context.CDV_origSymbols = origSymbols;
1471 for (var i = 0, len = symbolList.length; i < len; i += 3) {
1472 var strategy = symbolList[i];
1473 var moduleName = symbolList[i + 1];
1474 var module = require(moduleName);
1475 // <runs/>
1476 if (strategy == 'r') {
1477 continue;
1478 }
1479 var symbolPath = symbolList[i + 2];
1480 var lastDot = symbolPath.lastIndexOf('.');
1481 var namespace = symbolPath.substr(0, lastDot);
1482 var lastName = symbolPath.substr(lastDot + 1);
1483
1484 var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
1485 var parentObj = prepareNamespace(namespace, context);
1486 var target = parentObj[lastName];
1487
1488 if (strategy == 'm' && target) {
1489 builder.recursiveMerge(target, module);
1490 } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
1491 if (!(symbolPath in origSymbols)) {
1492 origSymbols[symbolPath] = target;
1493 }
1494 builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
1495 }
1496 }
1497};
1498
1499exports.getOriginalSymbol = function(context, symbolPath) {
1500 var origSymbols = context.CDV_origSymbols;
1501 if (origSymbols && (symbolPath in origSymbols)) {
1502 return origSymbols[symbolPath];
1503 }
1504 var parts = symbolPath.split('.');
1505 var obj = context;
1506 for (var i = 0; i < parts.length; ++i) {
1507 obj = obj && obj[parts[i]];
1508 }
1509 return obj;
1510};
1511
1512exports.reset();
1513
1514
1515});
1516
1517// file: src/common/modulemapper_b.js
1518define("cordova/modulemapper_b", function(require, exports, module) {
1519
1520var builder = require('cordova/builder'),
1521 symbolList = [],
1522 deprecationMap;
1523
1524exports.reset = function() {
1525 symbolList = [];
1526 deprecationMap = {};
1527};
1528
1529function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
1530 symbolList.push(strategy, moduleName, symbolPath);
1531 if (opt_deprecationMessage) {
1532 deprecationMap[symbolPath] = opt_deprecationMessage;
1533 }
1534}
1535
1536// Note: Android 2.3 does have Function.bind().
1537exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
1538 addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
1539};
1540
1541exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
1542 addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
1543};
1544
1545exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
1546 addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
1547};
1548
1549exports.runs = function(moduleName) {
1550 addEntry('r', moduleName, null);
1551};
1552
1553function prepareNamespace(symbolPath, context) {
1554 if (!symbolPath) {
1555 return context;
1556 }
1557 var parts = symbolPath.split('.');
1558 var cur = context;
1559 for (var i = 0, part; part = parts[i]; ++i) {
1560 cur = cur[part] = cur[part] || {};
1561 }
1562 return cur;
1563}
1564
1565exports.mapModules = function(context) {
1566 var origSymbols = {};
1567 context.CDV_origSymbols = origSymbols;
1568 for (var i = 0, len = symbolList.length; i < len; i += 3) {
1569 var strategy = symbolList[i];
1570 var moduleName = symbolList[i + 1];
1571 var module = require(moduleName);
1572 // <runs/>
1573 if (strategy == 'r') {
1574 continue;
1575 }
1576 var symbolPath = symbolList[i + 2];
1577 var lastDot = symbolPath.lastIndexOf('.');
1578 var namespace = symbolPath.substr(0, lastDot);
1579 var lastName = symbolPath.substr(lastDot + 1);
1580
1581 var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
1582 var parentObj = prepareNamespace(namespace, context);
1583 var target = parentObj[lastName];
1584
1585 if (strategy == 'm' && target) {
1586 builder.recursiveMerge(target, module);
1587 } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
1588 if (!(symbolPath in origSymbols)) {
1589 origSymbols[symbolPath] = target;
1590 }
1591 builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
1592 }
1593 }
1594};
1595
1596exports.getOriginalSymbol = function(context, symbolPath) {
1597 var origSymbols = context.CDV_origSymbols;
1598 if (origSymbols && (symbolPath in origSymbols)) {
1599 return origSymbols[symbolPath];
1600 }
1601 var parts = symbolPath.split('.');
1602 var obj = context;
1603 for (var i = 0; i < parts.length; ++i) {
1604 obj = obj && obj[parts[i]];
1605 }
1606 return obj;
1607};
1608
1609exports.reset();
1610
1611
1612});
1613
1614// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/platform.js
1615define("cordova/platform", function(require, exports, module) {
1616
1617// The last resume event that was received that had the result of a plugin call.
1618var lastResumeEvent = null;
1619
1620module.exports = {
1621 id: 'android',
1622 bootstrap: function() {
1623 var channel = require('cordova/channel'),
1624 cordova = require('cordova'),
1625 exec = require('cordova/exec'),
1626 modulemapper = require('cordova/modulemapper');
1627
1628 // Get the shared secret needed to use the bridge.
1629 exec.init();
1630
1631 // TODO: Extract this as a proper plugin.
1632 modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
1633
1634 var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
1635
1636 // Inject a listener for the backbutton on the document.
1637 var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
1638 backButtonChannel.onHasSubscribersChange = function() {
1639 // If we just attached the first handler or detached the last handler,
1640 // let native know we need to override the back button.
1641 exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
1642 };
1643
1644 // Add hardware MENU and SEARCH button handlers
1645 cordova.addDocumentEventHandler('menubutton');
1646 cordova.addDocumentEventHandler('searchbutton');
1647
1648 function bindButtonChannel(buttonName) {
1649 // generic button bind used for volumeup/volumedown buttons
1650 var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
1651 volumeButtonChannel.onHasSubscribersChange = function() {
1652 exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
1653 };
1654 }
1655 // Inject a listener for the volume buttons on the document.
1656 bindButtonChannel('volumeup');
1657 bindButtonChannel('volumedown');
1658
1659 // The resume event is not "sticky", but it is possible that the event
1660 // will contain the result of a plugin call. We need to ensure that the
1661 // plugin result is delivered even after the event is fired (CB-10498)
1662 var cordovaAddEventListener = document.addEventListener;
1663
1664 document.addEventListener = function(evt, handler, capture) {
1665 cordovaAddEventListener(evt, handler, capture);
1666
1667 if (evt === 'resume' && lastResumeEvent) {
1668 handler(lastResumeEvent);
1669 }
1670 };
1671
1672 // Let native code know we are all done on the JS side.
1673 // Native code will then un-hide the WebView.
1674 channel.onCordovaReady.subscribe(function() {
1675 exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
1676 exec(null, null, APP_PLUGIN_NAME, "show", []);
1677 });
1678 }
1679};
1680
1681function onMessageFromNative(msg) {
1682 var cordova = require('cordova');
1683 var action = msg.action;
1684
1685 switch (action)
1686 {
1687 // Button events
1688 case 'backbutton':
1689 case 'menubutton':
1690 case 'searchbutton':
1691 // App life cycle events
1692 case 'pause':
1693 // Volume events
1694 case 'volumedownbutton':
1695 case 'volumeupbutton':
1696 cordova.fireDocumentEvent(action);
1697 break;
1698 case 'resume':
1699 if(arguments.length > 1 && msg.pendingResult) {
1700 if(arguments.length === 2) {
1701 msg.pendingResult.result = arguments[1];
1702 } else {
1703 // The plugin returned a multipart message
1704 var res = [];
1705 for(var i = 1; i < arguments.length; i++) {
1706 res.push(arguments[i]);
1707 }
1708 msg.pendingResult.result = res;
1709 }
1710
1711 // Save the plugin result so that it can be delivered to the js
1712 // even if they miss the initial firing of the event
1713 lastResumeEvent = msg;
1714 }
1715 cordova.fireDocumentEvent(action, msg);
1716 break;
1717 default:
1718 throw new Error('Unknown event action ' + action);
1719 }
1720}
1721
1722});
1723
1724// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/plugin/android/app.js
1725define("cordova/plugin/android/app", function(require, exports, module) {
1726
1727var exec = require('cordova/exec');
1728var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
1729
1730module.exports = {
1731 /**
1732 * Clear the resource cache.
1733 */
1734 clearCache:function() {
1735 exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
1736 },
1737
1738 /**
1739 * Load the url into the webview or into new browser instance.
1740 *
1741 * @param url The URL to load
1742 * @param props Properties that can be passed in to the activity:
1743 * wait: int => wait msec before loading URL
1744 * loadingDialog: "Title,Message" => display a native loading dialog
1745 * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
1746 * clearHistory: boolean => clear webview history (default=false)
1747 * openExternal: boolean => open in a new browser (default=false)
1748 *
1749 * Example:
1750 * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
1751 */
1752 loadUrl:function(url, props) {
1753 exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
1754 },
1755
1756 /**
1757 * Cancel loadUrl that is waiting to be loaded.
1758 */
1759 cancelLoadUrl:function() {
1760 exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
1761 },
1762
1763 /**
1764 * Clear web history in this web view.
1765 * Instead of BACK button loading the previous web page, it will exit the app.
1766 */
1767 clearHistory:function() {
1768 exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
1769 },
1770
1771 /**
1772 * Go to previous page displayed.
1773 * This is the same as pressing the backbutton on Android device.
1774 */
1775 backHistory:function() {
1776 exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
1777 },
1778
1779 /**
1780 * Override the default behavior of the Android back button.
1781 * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
1782 *
1783 * Note: The user should not have to call this method. Instead, when the user
1784 * registers for the "backbutton" event, this is automatically done.
1785 *
1786 * @param override T=override, F=cancel override
1787 */
1788 overrideBackbutton:function(override) {
1789 exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
1790 },
1791
1792 /**
1793 * Override the default behavior of the Android volume button.
1794 * If overridden, when the volume button is pressed, the "volume[up|down]button"
1795 * JavaScript event will be fired.
1796 *
1797 * Note: The user should not have to call this method. Instead, when the user
1798 * registers for the "volume[up|down]button" event, this is automatically done.
1799 *
1800 * @param button volumeup, volumedown
1801 * @param override T=override, F=cancel override
1802 */
1803 overrideButton:function(button, override) {
1804 exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
1805 },
1806
1807 /**
1808 * Exit and terminate the application.
1809 */
1810 exitApp:function() {
1811 return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
1812 }
1813};
1814
1815});
1816
1817// file: src/common/pluginloader.js
1818define("cordova/pluginloader", function(require, exports, module) {
1819
1820var modulemapper = require('cordova/modulemapper');
1821var urlutil = require('cordova/urlutil');
1822
1823// Helper function to inject a <script> tag.
1824// Exported for testing.
1825exports.injectScript = function(url, onload, onerror) {
1826 var script = document.createElement("script");
1827 // onload fires even when script fails loads with an error.
1828 script.onload = onload;
1829 // onerror fires for malformed URLs.
1830 script.onerror = onerror;
1831 script.src = url;
1832 document.head.appendChild(script);
1833};
1834
1835function injectIfNecessary(id, url, onload, onerror) {
1836 onerror = onerror || onload;
1837 if (id in define.moduleMap) {
1838 onload();
1839 } else {
1840 exports.injectScript(url, function() {
1841 if (id in define.moduleMap) {
1842 onload();
1843 } else {
1844 onerror();
1845 }
1846 }, onerror);
1847 }
1848}
1849
1850function onScriptLoadingComplete(moduleList, finishPluginLoading) {
1851 // Loop through all the plugins and then through their clobbers and merges.
1852 for (var i = 0, module; module = moduleList[i]; i++) {
1853 if (module.clobbers && module.clobbers.length) {
1854 for (var j = 0; j < module.clobbers.length; j++) {
1855 modulemapper.clobbers(module.id, module.clobbers[j]);
1856 }
1857 }
1858
1859 if (module.merges && module.merges.length) {
1860 for (var k = 0; k < module.merges.length; k++) {
1861 modulemapper.merges(module.id, module.merges[k]);
1862 }
1863 }
1864
1865 // Finally, if runs is truthy we want to simply require() the module.
1866 if (module.runs) {
1867 modulemapper.runs(module.id);
1868 }
1869 }
1870
1871 finishPluginLoading();
1872}
1873
1874// Handler for the cordova_plugins.js content.
1875// See plugman's plugin_loader.js for the details of this object.
1876// This function is only called if the really is a plugins array that isn't empty.
1877// Otherwise the onerror response handler will just call finishPluginLoading().
1878function handlePluginsObject(path, moduleList, finishPluginLoading) {
1879 // Now inject the scripts.
1880 var scriptCounter = moduleList.length;
1881
1882 if (!scriptCounter) {
1883 finishPluginLoading();
1884 return;
1885 }
1886 function scriptLoadedCallback() {
1887 if (!--scriptCounter) {
1888 onScriptLoadingComplete(moduleList, finishPluginLoading);
1889 }
1890 }
1891
1892 for (var i = 0; i < moduleList.length; i++) {
1893 injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
1894 }
1895}
1896
1897function findCordovaPath() {
1898 var path = null;
1899 var scripts = document.getElementsByTagName('script');
1900 var term = '/cordova.js';
1901 for (var n = scripts.length-1; n>-1; n--) {
1902 var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
1903 if (src.indexOf(term) == (src.length - term.length)) {
1904 path = src.substring(0, src.length - term.length) + '/';
1905 break;
1906 }
1907 }
1908 return path;
1909}
1910
1911// Tries to load all plugins' js-modules.
1912// This is an async process, but onDeviceReady is blocked on onPluginsReady.
1913// onPluginsReady is fired when there are no plugins to load, or they are all done.
1914exports.load = function(callback) {
1915 var pathPrefix = findCordovaPath();
1916 if (pathPrefix === null) {
1917 console.log('Could not find cordova.js script tag. Plugin loading may fail.');
1918 pathPrefix = '';
1919 }
1920 injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
1921 var moduleList = require("cordova/plugin_list");
1922 handlePluginsObject(pathPrefix, moduleList, callback);
1923 }, callback);
1924};
1925
1926
1927});
1928
1929// file: src/common/pluginloader_b.js
1930define("cordova/pluginloader_b", function(require, exports, module) {
1931
1932var modulemapper = require('cordova/modulemapper');
1933
1934// Handler for the cordova_plugins.js content.
1935// See plugman's plugin_loader.js for the details of this object.
1936function handlePluginsObject(moduleList) {
1937 // if moduleList is not defined or empty, we've nothing to do
1938 if (!moduleList || !moduleList.length) {
1939 return;
1940 }
1941
1942 // Loop through all the modules and then through their clobbers and merges.
1943 for (var i = 0, module; module = moduleList[i]; i++) {
1944 if (module.clobbers && module.clobbers.length) {
1945 for (var j = 0; j < module.clobbers.length; j++) {
1946 modulemapper.clobbers(module.id, module.clobbers[j]);
1947 }
1948 }
1949
1950 if (module.merges && module.merges.length) {
1951 for (var k = 0; k < module.merges.length; k++) {
1952 modulemapper.merges(module.id, module.merges[k]);
1953 }
1954 }
1955
1956 // Finally, if runs is truthy we want to simply require() the module.
1957 if (module.runs) {
1958 modulemapper.runs(module.id);
1959 }
1960 }
1961}
1962
1963// Loads all plugins' js-modules. Plugin loading is syncronous in browserified bundle
1964// but the method accepts callback to be compatible with non-browserify flow.
1965// onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
1966// no plugins to load, or they are all done.
1967exports.load = function(callback) {
1968 var moduleList = require("cordova/plugin_list");
1969 handlePluginsObject(moduleList);
1970
1971 callback();
1972};
1973
1974
1975});
1976
1977// file: src/common/urlutil.js
1978define("cordova/urlutil", function(require, exports, module) {
1979
1980
1981/**
1982 * For already absolute URLs, returns what is passed in.
1983 * For relative URLs, converts them to absolute ones.
1984 */
1985exports.makeAbsolute = function makeAbsolute(url) {
1986 var anchorEl = document.createElement('a');
1987 anchorEl.href = url;
1988 return anchorEl.href;
1989};
1990
1991
1992});
1993
1994// file: src/common/utils.js
1995define("cordova/utils", function(require, exports, module) {
1996
1997var utils = exports;
1998
1999/**
2000 * Defines a property getter / setter for obj[key].
2001 */
2002utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
2003 if (Object.defineProperty) {
2004 var desc = {
2005 get: getFunc,
2006 configurable: true
2007 };
2008 if (opt_setFunc) {
2009 desc.set = opt_setFunc;
2010 }
2011 Object.defineProperty(obj, key, desc);
2012 } else {
2013 obj.__defineGetter__(key, getFunc);
2014 if (opt_setFunc) {
2015 obj.__defineSetter__(key, opt_setFunc);
2016 }
2017 }
2018};
2019
2020/**
2021 * Defines a property getter for obj[key].
2022 */
2023utils.defineGetter = utils.defineGetterSetter;
2024
2025utils.arrayIndexOf = function(a, item) {
2026 if (a.indexOf) {
2027 return a.indexOf(item);
2028 }
2029 var len = a.length;
2030 for (var i = 0; i < len; ++i) {
2031 if (a[i] == item) {
2032 return i;
2033 }
2034 }
2035 return -1;
2036};
2037
2038/**
2039 * Returns whether the item was found in the array.
2040 */
2041utils.arrayRemove = function(a, item) {
2042 var index = utils.arrayIndexOf(a, item);
2043 if (index != -1) {
2044 a.splice(index, 1);
2045 }
2046 return index != -1;
2047};
2048
2049utils.typeName = function(val) {
2050 return Object.prototype.toString.call(val).slice(8, -1);
2051};
2052
2053/**
2054 * Returns an indication of whether the argument is an array or not
2055 */
2056utils.isArray = Array.isArray ||
2057 function(a) {return utils.typeName(a) == 'Array';};
2058
2059/**
2060 * Returns an indication of whether the argument is a Date or not
2061 */
2062utils.isDate = function(d) {
2063 return (d instanceof Date);
2064};
2065
2066/**
2067 * Does a deep clone of the object.
2068 */
2069utils.clone = function(obj) {
2070 if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
2071 return obj;
2072 }
2073
2074 var retVal, i;
2075
2076 if(utils.isArray(obj)){
2077 retVal = [];
2078 for(i = 0; i < obj.length; ++i){
2079 retVal.push(utils.clone(obj[i]));
2080 }
2081 return retVal;
2082 }
2083
2084 retVal = {};
2085 for(i in obj){
2086 if((!(i in retVal) || retVal[i] != obj[i]) && typeof obj[i] != 'undefined') {
2087 retVal[i] = utils.clone(obj[i]);
2088 }
2089 }
2090 return retVal;
2091};
2092
2093/**
2094 * Returns a wrapped version of the function
2095 */
2096utils.close = function(context, func, params) {
2097 return function() {
2098 var args = params || arguments;
2099 return func.apply(context, args);
2100 };
2101};
2102
2103//------------------------------------------------------------------------------
2104function UUIDcreatePart(length) {
2105 var uuidpart = "";
2106 for (var i=0; i<length; i++) {
2107 var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
2108 if (uuidchar.length == 1) {
2109 uuidchar = "0" + uuidchar;
2110 }
2111 uuidpart += uuidchar;
2112 }
2113 return uuidpart;
2114}
2115
2116/**
2117 * Create a UUID
2118 */
2119utils.createUUID = function() {
2120 return UUIDcreatePart(4) + '-' +
2121 UUIDcreatePart(2) + '-' +
2122 UUIDcreatePart(2) + '-' +
2123 UUIDcreatePart(2) + '-' +
2124 UUIDcreatePart(6);
2125};
2126
2127
2128/**
2129 * Extends a child object from a parent object using classical inheritance
2130 * pattern.
2131 */
2132utils.extend = (function() {
2133 // proxy used to establish prototype chain
2134 var F = function() {};
2135 // extend Child from Parent
2136 return function(Child, Parent) {
2137
2138 F.prototype = Parent.prototype;
2139 Child.prototype = new F();
2140 Child.__super__ = Parent.prototype;
2141 Child.prototype.constructor = Child;
2142 };
2143}());
2144
2145/**
2146 * Alerts a message in any available way: alert or console.log.
2147 */
2148utils.alert = function(msg) {
2149 if (window.alert) {
2150 window.alert(msg);
2151 } else if (console && console.log) {
2152 console.log(msg);
2153 }
2154};
2155
2156
2157
2158
2159
2160});
2161
2162window.cordova = require('cordova');
2163// file: src/scripts/bootstrap.js
2164
2165require('cordova/init');
2166
2167})();