UNPKG

5.4 kBJavaScriptView Raw
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 the exec bridge used to notify the native code of
24 * commands.
25 */
26var cordova = require('cordova');
27var utils = require('cordova/utils');
28var base64 = require('cordova/base64');
29
30function massageArgsJsToNative (args) {
31 if (!args || utils.typeName(args) !== 'Array') {
32 return args;
33 }
34 var ret = [];
35 args.forEach(function (arg, i) {
36 if (utils.typeName(arg) === 'ArrayBuffer') {
37 ret.push({
38 CDVType: 'ArrayBuffer',
39 data: base64.fromArrayBuffer(arg)
40 });
41 } else {
42 ret.push(arg);
43 }
44 });
45 return ret;
46}
47
48function massageMessageNativeToJs (message) {
49 if (message.CDVType === 'ArrayBuffer') {
50 var stringToArrayBuffer = function (str) {
51 var ret = new Uint8Array(str.length);
52 for (var i = 0; i < str.length; i++) {
53 ret[i] = str.charCodeAt(i);
54 }
55 return ret.buffer;
56 };
57 var base64ToArrayBuffer = function (b64) {
58 return stringToArrayBuffer(atob(b64)); // eslint-disable-line no-undef
59 };
60 message = base64ToArrayBuffer(message.data);
61 }
62 return message;
63}
64
65function convertMessageToArgsNativeToJs (message) {
66 var args = [];
67 if (!message || !Object.prototype.hasOwnProperty.call(message, 'CDVType')) {
68 args.push(message);
69 } else if (message.CDVType === 'MultiPart') {
70 message.messages.forEach(function (e) {
71 args.push(massageMessageNativeToJs(e));
72 });
73 } else {
74 args.push(massageMessageNativeToJs(message));
75 }
76 return args;
77}
78
79var iOSExec = function () {
80 var successCallback, failCallback, service, action, actionArgs;
81 var callbackId = null;
82 if (typeof arguments[0] !== 'string') {
83 // FORMAT ONE
84 successCallback = arguments[0];
85 failCallback = arguments[1];
86 service = arguments[2];
87 action = arguments[3];
88 actionArgs = arguments[4];
89
90 // Since we need to maintain backwards compatibility, we have to pass
91 // an invalid callbackId even if no callback was provided since plugins
92 // will be expecting it. The Cordova.exec() implementation allocates
93 // an invalid callbackId and passes it even if no callbacks were given.
94 callbackId = 'INVALID';
95 } else {
96 throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' + // eslint-disable-line
97 'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);');
98 }
99
100 // If actionArgs is not provided, default to an empty array
101 actionArgs = actionArgs || [];
102
103 // Register the callbacks and add the callbackId to the positional
104 // arguments if given.
105 if (successCallback || failCallback) {
106 callbackId = service + cordova.callbackId++;
107 cordova.callbacks[callbackId] =
108 { success: successCallback, fail: failCallback };
109 }
110
111 actionArgs = massageArgsJsToNative(actionArgs);
112
113 // CB-10133 DataClone DOM Exception 25 guard (fast function remover)
114 var command = [callbackId, service, action, JSON.parse(JSON.stringify(actionArgs))];
115 window.webkit.messageHandlers.cordova.postMessage(command);
116};
117
118iOSExec.nativeCallback = function (callbackId, status, message, keepCallback, debug) {
119 var success = status === 0 || status === 1;
120 var args = convertMessageToArgsNativeToJs(message);
121 Promise.resolve().then(function () {
122 cordova.callbackFromNative(callbackId, success, status, args, keepCallback); // eslint-disable-line
123 });
124};
125
126// for backwards compatibility
127iOSExec.nativeEvalAndFetch = function (func) {
128 try {
129 func();
130 } catch (e) {
131 console.log(e);
132 }
133};
134
135// Proxy the exec for bridge changes. See CB-10106
136
137function cordovaExec () {
138 var cexec = require('cordova/exec');
139 var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
140 return (cexec_valid && execProxy !== cexec) ? cexec : iOSExec;
141}
142
143function execProxy () {
144 cordovaExec().apply(null, arguments);
145}
146
147execProxy.nativeFetchMessages = function () {
148 return cordovaExec().nativeFetchMessages.apply(null, arguments);
149};
150
151execProxy.nativeEvalAndFetch = function () {
152 return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
153};
154
155execProxy.nativeCallback = function () {
156 return cordovaExec().nativeCallback.apply(null, arguments);
157};
158
159module.exports = execProxy;