Skip to content

Commit ef27675

Browse files
committed
Initial commit
1 parent bb122e8 commit ef27675

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+117531
-0
lines changed

config.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version='1.0' encoding='utf-8'?>
2+
<widget id="com.ionicframework.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
3+
<name>HelloCordova</name>
4+
<description>
5+
An Ionic Framework and Cordova project.
6+
</description>
7+
<author email="you@example.com" href="http://example.com.com/">
8+
Your Name Here
9+
</author>
10+
<content src="index.html" />
11+
<access origin="*" />
12+
<preference name="webviewbounce" value="false" />
13+
<preference name="UIWebViewBounce" value="false" />
14+
<preference name="DisallowOverscroll" value="true" />
15+
16+
<!-- Ionic supports Android Jellybean and up -->
17+
<preference name="android-minSdkVersion" value="16" />
18+
19+
<!-- Don't store local data in an iCloud backup. Turn this to "cloud" to enable storage
20+
to be sent to iCloud. Note: enabling this could result in Apple rejecting your app.
21+
-->
22+
<preference name="BackupWebStorage" value="none" />
23+
24+
<feature name="StatusBar">
25+
<param name="ios-package" value="CDVStatusBar" onload="true" />
26+
</feature>
27+
</widget>

www/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
This is an addon starter template for the [Ionic Framework](http://ionicframework.com/).
2+
3+
## How to use this template
4+
5+
*This template does not work on its own*. It is missing the Ionic library, and AngularJS.
6+
7+
To use this, either create a new ionic project using the ionic node.js utility, or copy and paste this into an existing Cordova project and download a release of Ionic separately.
8+
9+
### With the Ionic tool:
10+
11+
Take the name after `ionic-starter-`, and that is the name of the template to be used when using the `ionic start` command below:
12+
13+
```bash
14+
$ sudo npm install -g ionic cordova
15+
$ ionic start myApp maps
16+
```
17+
18+
Then, to run it, cd into `myApp` and run:
19+
20+
```bash
21+
$ ionic platform add ios
22+
$ ionic build ios
23+
$ ionic emulate ios
24+
```
25+
26+
Substitute ios for android if not on a Mac, but if you can, the ios development toolchain is a lot easier to work with until you need to do anything custom to Android.

www/cordova-js-src/exec.js

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
/*
2+
*
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
*
20+
*/
21+
22+
/**
23+
* Creates a gap bridge iframe used to notify the native code about queued
24+
* commands.
25+
*/
26+
var cordova = require('cordova'),
27+
channel = require('cordova/channel'),
28+
utils = require('cordova/utils'),
29+
base64 = require('cordova/base64'),
30+
// XHR mode does not work on iOS 4.2.
31+
// XHR mode's main advantage is working around a bug in -webkit-scroll, which
32+
// doesn't exist only on iOS 5.x devices.
33+
// IFRAME_NAV is the fastest.
34+
// IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
35+
jsToNativeModes = {
36+
IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
37+
// XHR bridge appears to be flaky sometimes: CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134
38+
XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
39+
XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
40+
XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
41+
IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
42+
IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
43+
WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
44+
},
45+
bridgeMode,
46+
execIframe,
47+
execHashIframe,
48+
hashToggle = 1,
49+
execXhr,
50+
requestCount = 0,
51+
vcHeaderValue = null,
52+
commandQueue = [], // Contains pending JS->Native messages.
53+
isInContextOfEvalJs = 0,
54+
failSafeTimerId = 0;
55+
56+
function shouldBundleCommandJson() {
57+
if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
58+
return true;
59+
}
60+
if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
61+
var payloadLength = 0;
62+
for (var i = 0; i < commandQueue.length; ++i) {
63+
payloadLength += commandQueue[i].length;
64+
}
65+
// The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
66+
return payloadLength < 4500;
67+
}
68+
return false;
69+
}
70+
71+
function massageArgsJsToNative(args) {
72+
if (!args || utils.typeName(args) != 'Array') {
73+
return args;
74+
}
75+
var ret = [];
76+
args.forEach(function(arg, i) {
77+
if (utils.typeName(arg) == 'ArrayBuffer') {
78+
ret.push({
79+
'CDVType': 'ArrayBuffer',
80+
'data': base64.fromArrayBuffer(arg)
81+
});
82+
} else {
83+
ret.push(arg);
84+
}
85+
});
86+
return ret;
87+
}
88+
89+
function massageMessageNativeToJs(message) {
90+
if (message.CDVType == 'ArrayBuffer') {
91+
var stringToArrayBuffer = function(str) {
92+
var ret = new Uint8Array(str.length);
93+
for (var i = 0; i < str.length; i++) {
94+
ret[i] = str.charCodeAt(i);
95+
}
96+
return ret.buffer;
97+
};
98+
var base64ToArrayBuffer = function(b64) {
99+
return stringToArrayBuffer(atob(b64));
100+
};
101+
message = base64ToArrayBuffer(message.data);
102+
}
103+
return message;
104+
}
105+
106+
function convertMessageToArgsNativeToJs(message) {
107+
var args = [];
108+
if (!message || !message.hasOwnProperty('CDVType')) {
109+
args.push(message);
110+
} else if (message.CDVType == 'MultiPart') {
111+
message.messages.forEach(function(e) {
112+
args.push(massageMessageNativeToJs(e));
113+
});
114+
} else {
115+
args.push(massageMessageNativeToJs(message));
116+
}
117+
return args;
118+
}
119+
120+
function iOSExec() {
121+
if (bridgeMode === undefined) {
122+
bridgeMode = jsToNativeModes.IFRAME_NAV;
123+
}
124+
125+
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
126+
bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
127+
}
128+
129+
var successCallback, failCallback, service, action, actionArgs, splitCommand;
130+
var callbackId = null;
131+
if (typeof arguments[0] !== "string") {
132+
// FORMAT ONE
133+
successCallback = arguments[0];
134+
failCallback = arguments[1];
135+
service = arguments[2];
136+
action = arguments[3];
137+
actionArgs = arguments[4];
138+
139+
// Since we need to maintain backwards compatibility, we have to pass
140+
// an invalid callbackId even if no callback was provided since plugins
141+
// will be expecting it. The Cordova.exec() implementation allocates
142+
// an invalid callbackId and passes it even if no callbacks were given.
143+
callbackId = 'INVALID';
144+
} else {
145+
// FORMAT TWO, REMOVED
146+
try {
147+
splitCommand = arguments[0].split(".");
148+
action = splitCommand.pop();
149+
service = splitCommand.join(".");
150+
actionArgs = Array.prototype.splice.call(arguments, 1);
151+
152+
console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
153+
"cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
154+
);
155+
return;
156+
} catch (e) {}
157+
}
158+
159+
// If actionArgs is not provided, default to an empty array
160+
actionArgs = actionArgs || [];
161+
162+
// Register the callbacks and add the callbackId to the positional
163+
// arguments if given.
164+
if (successCallback || failCallback) {
165+
callbackId = service + cordova.callbackId++;
166+
cordova.callbacks[callbackId] =
167+
{success:successCallback, fail:failCallback};
168+
}
169+
170+
actionArgs = massageArgsJsToNative(actionArgs);
171+
172+
var command = [callbackId, service, action, actionArgs];
173+
174+
// Stringify and queue the command. We stringify to command now to
175+
// effectively clone the command arguments in case they are mutated before
176+
// the command is executed.
177+
commandQueue.push(JSON.stringify(command));
178+
179+
if (bridgeMode === jsToNativeModes.WK_WEBVIEW_BINDING) {
180+
window.webkit.messageHandlers.cordova.postMessage(command);
181+
} else {
182+
// If we're in the context of a stringByEvaluatingJavaScriptFromString call,
183+
// then the queue will be flushed when it returns; no need for a poke.
184+
// Also, if there is already a command in the queue, then we've already
185+
// poked the native side, so there is no reason to do so again.
186+
if (!isInContextOfEvalJs && commandQueue.length == 1) {
187+
pokeNative();
188+
}
189+
}
190+
}
191+
192+
function pokeNative() {
193+
switch (bridgeMode) {
194+
case jsToNativeModes.XHR_NO_PAYLOAD:
195+
case jsToNativeModes.XHR_WITH_PAYLOAD:
196+
case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
197+
pokeNativeViaXhr();
198+
break;
199+
default: // iframe-based.
200+
pokeNativeViaIframe();
201+
}
202+
}
203+
204+
function pokeNativeViaXhr() {
205+
// This prevents sending an XHR when there is already one being sent.
206+
// This should happen only in rare circumstances (refer to unit tests).
207+
if (execXhr && execXhr.readyState != 4) {
208+
execXhr = null;
209+
}
210+
// Re-using the XHR improves exec() performance by about 10%.
211+
execXhr = execXhr || new XMLHttpRequest();
212+
// Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
213+
// For some reason it still doesn't work though...
214+
// Add a timestamp to the query param to prevent caching.
215+
execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
216+
if (!vcHeaderValue) {
217+
vcHeaderValue = /.*\((.*)\)$/.exec(navigator.userAgent)[1];
218+
}
219+
execXhr.setRequestHeader('vc', vcHeaderValue);
220+
execXhr.setRequestHeader('rc', ++requestCount);
221+
if (shouldBundleCommandJson()) {
222+
execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
223+
}
224+
execXhr.send(null);
225+
}
226+
227+
function pokeNativeViaIframe() {
228+
// CB-5488 - Don't attempt to create iframe before document.body is available.
229+
if (!document.body) {
230+
setTimeout(pokeNativeViaIframe);
231+
return;
232+
}
233+
if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
234+
// TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
235+
if (!execHashIframe) {
236+
execHashIframe = document.createElement('iframe');
237+
execHashIframe.style.display = 'none';
238+
document.body.appendChild(execHashIframe);
239+
// Hash changes don't work on about:blank, so switch it to file:///.
240+
execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
241+
}
242+
// The delegate method is called only when the hash changes, so toggle it back and forth.
243+
hashToggle = hashToggle ^ 3;
244+
var hashValue = '%0' + hashToggle;
245+
if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
246+
hashValue += iOSExec.nativeFetchMessages();
247+
}
248+
execHashIframe.contentWindow.location.hash = hashValue;
249+
} else {
250+
// Check if they've removed it from the DOM, and put it back if so.
251+
if (execIframe && execIframe.contentWindow) {
252+
execIframe.contentWindow.location = 'gap://ready';
253+
} else {
254+
execIframe = document.createElement('iframe');
255+
execIframe.style.display = 'none';
256+
execIframe.src = 'gap://ready';
257+
document.body.appendChild(execIframe);
258+
}
259+
// Use a timer to protect against iframe being unloaded during the poke (CB-7735).
260+
// This makes the bridge ~ 7% slower, but works around the poke getting lost
261+
// when the iframe is removed from the DOM.
262+
// An onunload listener could be used in the case where the iframe has just been
263+
// created, but since unload events fire only once, it doesn't work in the normal
264+
// case of iframe reuse (where unload will have already fired due to the attempted
265+
// navigation of the page).
266+
failSafeTimerId = setTimeout(function() {
267+
if (commandQueue.length) {
268+
pokeNative();
269+
}
270+
}, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
271+
}
272+
}
273+
274+
iOSExec.jsToNativeModes = jsToNativeModes;
275+
276+
iOSExec.setJsToNativeBridgeMode = function(mode) {
277+
// Remove the iFrame since it may be no longer required, and its existence
278+
// can trigger browser bugs.
279+
// https://issues.apache.org/jira/browse/CB-593
280+
if (execIframe) {
281+
if (execIframe.parentNode) {
282+
execIframe.parentNode.removeChild(execIframe);
283+
}
284+
execIframe = null;
285+
}
286+
bridgeMode = mode;
287+
};
288+
289+
iOSExec.nativeFetchMessages = function() {
290+
// Stop listing for window detatch once native side confirms poke.
291+
if (failSafeTimerId) {
292+
clearTimeout(failSafeTimerId);
293+
failSafeTimerId = 0;
294+
}
295+
// Each entry in commandQueue is a JSON string already.
296+
if (!commandQueue.length) {
297+
return '';
298+
}
299+
var json = '[' + commandQueue.join(',') + ']';
300+
commandQueue.length = 0;
301+
return json;
302+
};
303+
304+
iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
305+
return iOSExec.nativeEvalAndFetch(function() {
306+
var success = status === 0 || status === 1;
307+
var args = convertMessageToArgsNativeToJs(message);
308+
cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
309+
});
310+
};
311+
312+
iOSExec.nativeEvalAndFetch = function(func) {
313+
// This shouldn't be nested, but better to be safe.
314+
isInContextOfEvalJs++;
315+
try {
316+
func();
317+
return iOSExec.nativeFetchMessages();
318+
} finally {
319+
isInContextOfEvalJs--;
320+
}
321+
};
322+
323+
module.exports = iOSExec;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy