@capacitor/android 4.1.0 → 4.1.1-dev-7e3589f9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +633 -0
- package/LICENSE +17 -19
- package/capacitor/src/main/assets/native-bridge.js +203 -0
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +2 -0
- package/capacitor/src/main/java/com/getcapacitor/JSValue.java +65 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookieManager.java +172 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookies.java +122 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +75 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/CapacitorHttpUrlConnection.java +381 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java +409 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/ICapacitorHttpUrlConnection.java +15 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/MimeType.java +17 -0
- package/package.json +3 -2
|
@@ -241,6 +241,209 @@ const nativeBridge = (function (exports) {
|
|
|
241
241
|
}
|
|
242
242
|
return String(msg);
|
|
243
243
|
};
|
|
244
|
+
/**
|
|
245
|
+
* Safely web decode a string value (inspired by js-cookie)
|
|
246
|
+
* @param str The string value to decode
|
|
247
|
+
*/
|
|
248
|
+
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
|
|
249
|
+
const platform = getPlatformId(win);
|
|
250
|
+
if (platform == 'android' || platform == 'ios') {
|
|
251
|
+
// patch document.cookie on Android/iOS
|
|
252
|
+
win.CapacitorCookiesDescriptor =
|
|
253
|
+
Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
|
|
254
|
+
Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
|
|
255
|
+
Object.defineProperty(document, 'cookie', {
|
|
256
|
+
get: function () {
|
|
257
|
+
if (platform === 'ios') {
|
|
258
|
+
// Use prompt to synchronously get cookies.
|
|
259
|
+
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
|
|
260
|
+
const payload = {
|
|
261
|
+
type: 'CapacitorCookies',
|
|
262
|
+
};
|
|
263
|
+
const res = prompt(JSON.stringify(payload));
|
|
264
|
+
return res;
|
|
265
|
+
}
|
|
266
|
+
else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
|
|
267
|
+
return win.CapacitorCookiesAndroidInterface.getCookies();
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
set: function (val) {
|
|
271
|
+
const cookiePairs = val.split(';');
|
|
272
|
+
for (const cookiePair of cookiePairs) {
|
|
273
|
+
const cookieKey = cookiePair.split('=')[0];
|
|
274
|
+
const cookieValue = cookiePair.split('=')[1];
|
|
275
|
+
if (null == cookieValue) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
cap.toNative('CapacitorCookies', 'setCookie', {
|
|
279
|
+
key: cookieKey,
|
|
280
|
+
value: decode(cookieValue),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
// patch fetch / XHR on Android/iOS
|
|
286
|
+
// store original fetch & XHR functions
|
|
287
|
+
win.CapacitorWebFetch = window.fetch;
|
|
288
|
+
win.CapacitorWebXMLHttpRequest = {
|
|
289
|
+
abort: window.XMLHttpRequest.prototype.abort,
|
|
290
|
+
open: window.XMLHttpRequest.prototype.open,
|
|
291
|
+
send: window.XMLHttpRequest.prototype.send,
|
|
292
|
+
setRequestHeader: window.XMLHttpRequest.prototype.setRequestHeader,
|
|
293
|
+
};
|
|
294
|
+
// fetch patch
|
|
295
|
+
window.fetch = async (resource, options) => {
|
|
296
|
+
if (resource.toString().startsWith('data:')) {
|
|
297
|
+
return win.CapacitorWebFetch(resource, options);
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
// intercept request & pass to the bridge
|
|
301
|
+
const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
|
|
302
|
+
url: resource,
|
|
303
|
+
method: (options === null || options === void 0 ? void 0 : options.method) ? options.method : undefined,
|
|
304
|
+
data: (options === null || options === void 0 ? void 0 : options.body) ? options.body : undefined,
|
|
305
|
+
headers: (options === null || options === void 0 ? void 0 : options.headers) ? options.headers : undefined,
|
|
306
|
+
});
|
|
307
|
+
// intercept & parse response before returning
|
|
308
|
+
const response = new Response(JSON.stringify(nativeResponse.data), {
|
|
309
|
+
headers: nativeResponse.headers,
|
|
310
|
+
status: nativeResponse.status,
|
|
311
|
+
});
|
|
312
|
+
return response;
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
return Promise.reject(error);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
// XHR event listeners
|
|
319
|
+
const addEventListeners = function () {
|
|
320
|
+
this.addEventListener('abort', function () {
|
|
321
|
+
if (typeof this.onabort === 'function')
|
|
322
|
+
this.onabort();
|
|
323
|
+
});
|
|
324
|
+
this.addEventListener('error', function () {
|
|
325
|
+
if (typeof this.onerror === 'function')
|
|
326
|
+
this.onerror();
|
|
327
|
+
});
|
|
328
|
+
this.addEventListener('load', function () {
|
|
329
|
+
if (typeof this.onload === 'function')
|
|
330
|
+
this.onload();
|
|
331
|
+
});
|
|
332
|
+
this.addEventListener('loadend', function () {
|
|
333
|
+
if (typeof this.onloadend === 'function')
|
|
334
|
+
this.onloadend();
|
|
335
|
+
});
|
|
336
|
+
this.addEventListener('loadstart', function () {
|
|
337
|
+
if (typeof this.onloadstart === 'function')
|
|
338
|
+
this.onloadstart();
|
|
339
|
+
});
|
|
340
|
+
this.addEventListener('readystatechange', function () {
|
|
341
|
+
if (typeof this.onreadystatechange === 'function')
|
|
342
|
+
this.onreadystatechange();
|
|
343
|
+
});
|
|
344
|
+
this.addEventListener('timeout', function () {
|
|
345
|
+
if (typeof this.ontimeout === 'function')
|
|
346
|
+
this.ontimeout();
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
// XHR patch abort
|
|
350
|
+
window.XMLHttpRequest.prototype.abort = function () {
|
|
351
|
+
Object.defineProperties(this, {
|
|
352
|
+
_headers: {
|
|
353
|
+
value: {},
|
|
354
|
+
writable: true,
|
|
355
|
+
},
|
|
356
|
+
readyState: {
|
|
357
|
+
get: function () {
|
|
358
|
+
var _a;
|
|
359
|
+
return (_a = this._readyState) !== null && _a !== void 0 ? _a : 0;
|
|
360
|
+
},
|
|
361
|
+
set: function (val) {
|
|
362
|
+
this._readyState = val;
|
|
363
|
+
this.dispatchEvent(new Event('readystatechange'));
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
response: {
|
|
367
|
+
value: '',
|
|
368
|
+
writable: true,
|
|
369
|
+
},
|
|
370
|
+
responseText: {
|
|
371
|
+
value: '',
|
|
372
|
+
writable: true,
|
|
373
|
+
},
|
|
374
|
+
responseURL: {
|
|
375
|
+
value: '',
|
|
376
|
+
writable: true,
|
|
377
|
+
},
|
|
378
|
+
status: {
|
|
379
|
+
value: 0,
|
|
380
|
+
writable: true,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
this.readyState = 0;
|
|
384
|
+
this.dispatchEvent(new Event('abort'));
|
|
385
|
+
this.dispatchEvent(new Event('loadend'));
|
|
386
|
+
};
|
|
387
|
+
// XHR patch open
|
|
388
|
+
window.XMLHttpRequest.prototype.open = function (method, url) {
|
|
389
|
+
this.abort();
|
|
390
|
+
addEventListeners.call(this);
|
|
391
|
+
this._method = method;
|
|
392
|
+
this._url = url;
|
|
393
|
+
this.readyState = 1;
|
|
394
|
+
};
|
|
395
|
+
// XHR patch set request header
|
|
396
|
+
window.XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
|
|
397
|
+
this._headers[header] = value;
|
|
398
|
+
};
|
|
399
|
+
// XHR patch send
|
|
400
|
+
window.XMLHttpRequest.prototype.send = function (body) {
|
|
401
|
+
try {
|
|
402
|
+
this.readyState = 2;
|
|
403
|
+
// intercept request & pass to the bridge
|
|
404
|
+
cap
|
|
405
|
+
.nativePromise('CapacitorHttp', 'request', {
|
|
406
|
+
url: this._url,
|
|
407
|
+
method: this._method,
|
|
408
|
+
data: body !== null ? body : undefined,
|
|
409
|
+
headers: this._headers,
|
|
410
|
+
})
|
|
411
|
+
.then((nativeResponse) => {
|
|
412
|
+
// intercept & parse response before returning
|
|
413
|
+
if (this.readyState == 2) {
|
|
414
|
+
this.dispatchEvent(new Event('loadstart'));
|
|
415
|
+
this.status = nativeResponse.status;
|
|
416
|
+
this.response = nativeResponse.data;
|
|
417
|
+
this.responseText = JSON.stringify(nativeResponse.data);
|
|
418
|
+
this.responseURL = nativeResponse.url;
|
|
419
|
+
this.readyState = 4;
|
|
420
|
+
this.dispatchEvent(new Event('load'));
|
|
421
|
+
this.dispatchEvent(new Event('loadend'));
|
|
422
|
+
}
|
|
423
|
+
})
|
|
424
|
+
.catch((error) => {
|
|
425
|
+
this.dispatchEvent(new Event('loadstart'));
|
|
426
|
+
this.status = error.status;
|
|
427
|
+
this.response = error.data;
|
|
428
|
+
this.responseText = JSON.stringify(error.data);
|
|
429
|
+
this.responseURL = error.url;
|
|
430
|
+
this.readyState = 4;
|
|
431
|
+
this.dispatchEvent(new Event('error'));
|
|
432
|
+
this.dispatchEvent(new Event('loadend'));
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
this.dispatchEvent(new Event('loadstart'));
|
|
437
|
+
this.status = 500;
|
|
438
|
+
this.response = error;
|
|
439
|
+
this.responseText = error.toString();
|
|
440
|
+
this.responseURL = this._url;
|
|
441
|
+
this.readyState = 4;
|
|
442
|
+
this.dispatchEvent(new Event('error'));
|
|
443
|
+
this.dispatchEvent(new Event('loadend'));
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
244
447
|
// patch window.console on iOS and store original console fns
|
|
245
448
|
const isIos = getPlatformId(win) === 'ios';
|
|
246
449
|
if (win.console && isIos) {
|
|
@@ -556,7 +556,9 @@ public class Bridge {
|
|
|
556
556
|
* Register our core Plugin APIs
|
|
557
557
|
*/
|
|
558
558
|
private void registerAllPlugins() {
|
|
559
|
+
this.registerPlugin(com.getcapacitor.plugin.CapacitorCookies.class);
|
|
559
560
|
this.registerPlugin(com.getcapacitor.plugin.WebView.class);
|
|
561
|
+
this.registerPlugin(com.getcapacitor.plugin.CapacitorHttp.class);
|
|
560
562
|
|
|
561
563
|
for (Class<? extends Plugin> pluginClass : this.initialPlugins) {
|
|
562
564
|
this.registerPlugin(pluginClass);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package com.getcapacitor;
|
|
2
|
+
|
|
3
|
+
import org.json.JSONException;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents a single user-data value of any type on the capacitor PluginCall object.
|
|
7
|
+
*/
|
|
8
|
+
public class JSValue {
|
|
9
|
+
|
|
10
|
+
private final Object value;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param call The capacitor plugin call, used for accessing the value safely.
|
|
14
|
+
* @param name The name of the property to access.
|
|
15
|
+
*/
|
|
16
|
+
public JSValue(PluginCall call, String name) {
|
|
17
|
+
this.value = this.toValue(call, name);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns the coerced but uncasted underlying value.
|
|
22
|
+
*/
|
|
23
|
+
public Object getValue() {
|
|
24
|
+
return this.value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Override
|
|
28
|
+
public String toString() {
|
|
29
|
+
return this.getValue().toString();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns the underlying value as a JSObject, or throwing if it cannot.
|
|
34
|
+
*
|
|
35
|
+
* @throws JSONException If the underlying value is not a JSObject.
|
|
36
|
+
*/
|
|
37
|
+
public JSObject toJSObject() throws JSONException {
|
|
38
|
+
if (this.value instanceof JSObject) return (JSObject) this.value;
|
|
39
|
+
throw new JSONException("JSValue could not be coerced to JSObject.");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns the underlying value as a JSArray, or throwing if it cannot.
|
|
44
|
+
*
|
|
45
|
+
* @throws JSONException If the underlying value is not a JSArray.
|
|
46
|
+
*/
|
|
47
|
+
public JSArray toJSArray() throws JSONException {
|
|
48
|
+
if (this.value instanceof JSArray) return (JSArray) this.value;
|
|
49
|
+
throw new JSONException("JSValue could not be coerced to JSArray.");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns the underlying value this object represents, coercing it into a capacitor-friendly object if supported.
|
|
54
|
+
*/
|
|
55
|
+
private Object toValue(PluginCall call, String name) {
|
|
56
|
+
Object value = null;
|
|
57
|
+
value = call.getArray(name, null);
|
|
58
|
+
if (value != null) return value;
|
|
59
|
+
value = call.getObject(name, null);
|
|
60
|
+
if (value != null) return value;
|
|
61
|
+
value = call.getString(name, null);
|
|
62
|
+
if (value != null) return value;
|
|
63
|
+
return call.getData().opt(name);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
package com.getcapacitor.plugin;
|
|
2
|
+
|
|
3
|
+
import java.net.CookieManager;
|
|
4
|
+
import java.net.CookiePolicy;
|
|
5
|
+
import java.net.CookieStore;
|
|
6
|
+
import java.net.HttpCookie;
|
|
7
|
+
import java.net.URI;
|
|
8
|
+
import java.util.ArrayList;
|
|
9
|
+
import java.util.Collections;
|
|
10
|
+
import java.util.HashMap;
|
|
11
|
+
import java.util.List;
|
|
12
|
+
import java.util.Map;
|
|
13
|
+
import java.util.Objects;
|
|
14
|
+
|
|
15
|
+
public class CapacitorCookieManager extends CookieManager {
|
|
16
|
+
|
|
17
|
+
private final android.webkit.CookieManager webkitCookieManager;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create a new cookie manager with the default cookie store and policy
|
|
21
|
+
*/
|
|
22
|
+
public CapacitorCookieManager() {
|
|
23
|
+
this(null, null);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create a new cookie manager with specified cookie store and cookie policy.
|
|
28
|
+
* @param store a {@code CookieStore} to be used by CookieManager. if {@code null}, cookie
|
|
29
|
+
* manager will use a default one, which is an in-memory CookieStore implementation.
|
|
30
|
+
* @param policy a {@code CookiePolicy} instance to be used by cookie manager as policy
|
|
31
|
+
* callback. if {@code null}, ACCEPT_ORIGINAL_SERVER will be used.
|
|
32
|
+
*/
|
|
33
|
+
public CapacitorCookieManager(CookieStore store, CookiePolicy policy) {
|
|
34
|
+
super(store, policy);
|
|
35
|
+
webkitCookieManager = android.webkit.CookieManager.getInstance();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Gets the cookies for the given URL.
|
|
40
|
+
* @param url the URL for which the cookies are requested
|
|
41
|
+
* @return value the cookies as a string, using the format of the 'Cookie' HTTP request header
|
|
42
|
+
*/
|
|
43
|
+
public String getCookieString(String url) {
|
|
44
|
+
return webkitCookieManager.getCookie(url);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Gets a cookie value for the given URL and key.
|
|
49
|
+
* @param url the URL for which the cookies are requested
|
|
50
|
+
* @param key the key of the cookie to search for
|
|
51
|
+
* @return the {@code HttpCookie} value of the cookie at the key,
|
|
52
|
+
* otherwise it will return a new empty {@code HttpCookie}
|
|
53
|
+
*/
|
|
54
|
+
public HttpCookie getCookie(String url, String key) {
|
|
55
|
+
HttpCookie[] cookies = getCookies(url);
|
|
56
|
+
for (HttpCookie cookie : cookies) {
|
|
57
|
+
if (cookie.getName().equals(key)) {
|
|
58
|
+
return cookie;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Gets an array of {@code HttpCookie} given a URL.
|
|
67
|
+
* @param url the URL for which the cookies are requested
|
|
68
|
+
* @return an {@code HttpCookie} array of non-expired cookies
|
|
69
|
+
*/
|
|
70
|
+
public HttpCookie[] getCookies(String url) {
|
|
71
|
+
try {
|
|
72
|
+
ArrayList<HttpCookie> cookieList = new ArrayList<>();
|
|
73
|
+
String cookieString = getCookieString(url);
|
|
74
|
+
if (cookieString != null) {
|
|
75
|
+
String[] singleCookie = cookieString.split(";");
|
|
76
|
+
for (String c : singleCookie) {
|
|
77
|
+
HttpCookie parsed = HttpCookie.parse(c).get(0);
|
|
78
|
+
parsed.setValue(parsed.getValue());
|
|
79
|
+
cookieList.add(parsed);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
HttpCookie[] cookies = new HttpCookie[cookieList.size()];
|
|
83
|
+
return cookieList.toArray(cookies);
|
|
84
|
+
} catch (Exception ex) {
|
|
85
|
+
return new HttpCookie[0];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Sets a cookie for the given URL. Any existing cookie with the same host, path and name will
|
|
91
|
+
* be replaced with the new cookie. The cookie being set will be ignored if it is expired.
|
|
92
|
+
* @param url the URL for which the cookie is to be set
|
|
93
|
+
* @param value the cookie as a string, using the format of the 'Set-Cookie' HTTP response header
|
|
94
|
+
*/
|
|
95
|
+
public void setCookie(String url, String value) {
|
|
96
|
+
webkitCookieManager.setCookie(url, value);
|
|
97
|
+
flush();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Sets a cookie for the given URL. Any existing cookie with the same host, path and name will
|
|
102
|
+
* be replaced with the new cookie. The cookie being set will be ignored if it is expired.
|
|
103
|
+
* @param url the URL for which the cookie is to be set
|
|
104
|
+
* @param key the {@code HttpCookie} name to use for lookup
|
|
105
|
+
* @param value the value of the {@code HttpCookie} given a key
|
|
106
|
+
*/
|
|
107
|
+
public void setCookie(String url, String key, String value) {
|
|
108
|
+
String cookieValue = key + "=" + value;
|
|
109
|
+
setCookie(url, cookieValue);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Removes all cookies. This method is asynchronous.
|
|
114
|
+
*/
|
|
115
|
+
public void removeAllCookies() {
|
|
116
|
+
webkitCookieManager.removeAllCookies(null);
|
|
117
|
+
flush();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Ensures all cookies currently accessible through the getCookie API are written to persistent
|
|
122
|
+
* storage. This call will block the caller until it is done and may perform I/O.
|
|
123
|
+
*/
|
|
124
|
+
public void flush() {
|
|
125
|
+
webkitCookieManager.flush();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@Override
|
|
129
|
+
public void put(URI uri, Map<String, List<String>> responseHeaders) {
|
|
130
|
+
// make sure our args are valid
|
|
131
|
+
if ((uri == null) || (responseHeaders == null)) return;
|
|
132
|
+
|
|
133
|
+
// save our url once
|
|
134
|
+
String url = uri.toString();
|
|
135
|
+
|
|
136
|
+
// go over the headers
|
|
137
|
+
for (String headerKey : responseHeaders.keySet()) {
|
|
138
|
+
// ignore headers which aren't cookie related
|
|
139
|
+
if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;
|
|
140
|
+
|
|
141
|
+
// process each of the headers
|
|
142
|
+
for (String headerValue : Objects.requireNonNull(responseHeaders.get(headerKey))) {
|
|
143
|
+
setCookie(url, headerValue);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@Override
|
|
149
|
+
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) {
|
|
150
|
+
// make sure our args are valid
|
|
151
|
+
if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");
|
|
152
|
+
|
|
153
|
+
// save our url once
|
|
154
|
+
String url = uri.toString();
|
|
155
|
+
|
|
156
|
+
// prepare our response
|
|
157
|
+
Map<String, List<String>> res = new HashMap<>();
|
|
158
|
+
|
|
159
|
+
// get the cookie
|
|
160
|
+
String cookie = getCookieString(url);
|
|
161
|
+
|
|
162
|
+
// return it
|
|
163
|
+
if (cookie != null) res.put("Cookie", Collections.singletonList(cookie));
|
|
164
|
+
return res;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@Override
|
|
168
|
+
public CookieStore getCookieStore() {
|
|
169
|
+
// we don't want anyone to work with this cookie store directly
|
|
170
|
+
throw new UnsupportedOperationException();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
package com.getcapacitor.plugin;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.content.SharedPreferences;
|
|
5
|
+
import android.util.Log;
|
|
6
|
+
import android.webkit.JavascriptInterface;
|
|
7
|
+
import androidx.annotation.Nullable;
|
|
8
|
+
import com.getcapacitor.CapConfig;
|
|
9
|
+
import com.getcapacitor.JSObject;
|
|
10
|
+
import com.getcapacitor.Plugin;
|
|
11
|
+
import com.getcapacitor.PluginCall;
|
|
12
|
+
import com.getcapacitor.PluginMethod;
|
|
13
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
14
|
+
import java.net.CookieHandler;
|
|
15
|
+
import java.net.HttpCookie;
|
|
16
|
+
import java.net.URI;
|
|
17
|
+
|
|
18
|
+
@CapacitorPlugin
|
|
19
|
+
public class CapacitorCookies extends Plugin {
|
|
20
|
+
|
|
21
|
+
CapacitorCookieManager cookieManager;
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public void load() {
|
|
25
|
+
this.bridge.getWebView().addJavascriptInterface(this, "CapacitorCookiesAndroidInterface");
|
|
26
|
+
this.cookieManager = new CapacitorCookieManager(null, java.net.CookiePolicy.ACCEPT_ALL);
|
|
27
|
+
CookieHandler.setDefault(cookieManager);
|
|
28
|
+
super.load();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Helper function for getting the serverUrl from the Capacitor Config. Returns an empty
|
|
33
|
+
* string if it is invalid and will auto-reject through {@code call}
|
|
34
|
+
* @param call the {@code PluginCall} context
|
|
35
|
+
* @return the string of the server specified in the Capacitor config
|
|
36
|
+
*/
|
|
37
|
+
private String getServerUrl(@Nullable PluginCall call) {
|
|
38
|
+
String url = (call == null) ? this.bridge.getServerUrl() : call.getString("url", this.bridge.getServerUrl());
|
|
39
|
+
|
|
40
|
+
if (url == null || url.isEmpty()) {
|
|
41
|
+
url = this.bridge.getLocalUrl();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
URI uri = getUri(url);
|
|
45
|
+
if (uri == null) {
|
|
46
|
+
if (call != null) {
|
|
47
|
+
call.reject("Invalid URL. Check that \"server\" is passed in correctly");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return url;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Try to parse a url string and if it can't be parsed, return null
|
|
58
|
+
* @param url the url string to try to parse
|
|
59
|
+
* @return a parsed URI
|
|
60
|
+
*/
|
|
61
|
+
private URI getUri(String url) {
|
|
62
|
+
try {
|
|
63
|
+
return new URI(url);
|
|
64
|
+
} catch (Exception ex) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@JavascriptInterface
|
|
70
|
+
public String getCookies() {
|
|
71
|
+
try {
|
|
72
|
+
String url = getServerUrl(null);
|
|
73
|
+
if (!url.isEmpty()) {
|
|
74
|
+
return cookieManager.getCookieString(url);
|
|
75
|
+
}
|
|
76
|
+
} catch (Exception e) {
|
|
77
|
+
e.printStackTrace();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@PluginMethod
|
|
84
|
+
public void setCookie(PluginCall call) {
|
|
85
|
+
String key = call.getString("key");
|
|
86
|
+
String value = call.getString("value");
|
|
87
|
+
String url = getServerUrl(call);
|
|
88
|
+
|
|
89
|
+
if (!url.isEmpty()) {
|
|
90
|
+
cookieManager.setCookie(url, key, value);
|
|
91
|
+
call.resolve();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@PluginMethod
|
|
96
|
+
public void deleteCookie(PluginCall call) {
|
|
97
|
+
String key = call.getString("key");
|
|
98
|
+
String url = getServerUrl(call);
|
|
99
|
+
if (!url.isEmpty()) {
|
|
100
|
+
cookieManager.setCookie(url, key + "=; Expires=Wed, 31 Dec 2000 23:59:59 GMT");
|
|
101
|
+
call.resolve();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@PluginMethod
|
|
106
|
+
public void clearCookies(PluginCall call) {
|
|
107
|
+
String url = getServerUrl(call);
|
|
108
|
+
if (!url.isEmpty()) {
|
|
109
|
+
HttpCookie[] cookies = cookieManager.getCookies(url);
|
|
110
|
+
for (HttpCookie cookie : cookies) {
|
|
111
|
+
cookieManager.setCookie(url, cookie.getName() + "=; Expires=Wed, 31 Dec 2000 23:59:59 GMT");
|
|
112
|
+
}
|
|
113
|
+
call.resolve();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@PluginMethod
|
|
118
|
+
public void clearAllCookies(PluginCall call) {
|
|
119
|
+
cookieManager.removeAllCookies();
|
|
120
|
+
call.resolve();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package com.getcapacitor.plugin;
|
|
2
|
+
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import android.webkit.JavascriptInterface;
|
|
5
|
+
import com.getcapacitor.CapConfig;
|
|
6
|
+
import com.getcapacitor.JSObject;
|
|
7
|
+
import com.getcapacitor.Plugin;
|
|
8
|
+
import com.getcapacitor.PluginCall;
|
|
9
|
+
import com.getcapacitor.PluginConfig;
|
|
10
|
+
import com.getcapacitor.PluginMethod;
|
|
11
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
12
|
+
import com.getcapacitor.annotation.Permission;
|
|
13
|
+
import com.getcapacitor.plugin.util.HttpRequestHandler;
|
|
14
|
+
|
|
15
|
+
@CapacitorPlugin(
|
|
16
|
+
permissions = {
|
|
17
|
+
@Permission(strings = { Manifest.permission.WRITE_EXTERNAL_STORAGE }, alias = "HttpWrite"),
|
|
18
|
+
@Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE }, alias = "HttpRead")
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
public class CapacitorHttp extends Plugin {
|
|
22
|
+
|
|
23
|
+
private void http(final PluginCall call, final String httpMethod) {
|
|
24
|
+
Runnable asyncHttpCall = new Runnable() {
|
|
25
|
+
@Override
|
|
26
|
+
public void run() {
|
|
27
|
+
try {
|
|
28
|
+
JSObject response = HttpRequestHandler.request(call, httpMethod);
|
|
29
|
+
call.resolve(response);
|
|
30
|
+
} catch (Exception e) {
|
|
31
|
+
System.out.println(e.toString());
|
|
32
|
+
call.reject(e.getClass().getSimpleName(), e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
Thread httpThread = new Thread(asyncHttpCall);
|
|
37
|
+
httpThread.start();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@JavascriptInterface
|
|
41
|
+
public boolean isDisabled() {
|
|
42
|
+
PluginConfig pluginConfig = getBridge().getConfig().getPluginConfiguration("CapacitorHttp");
|
|
43
|
+
return pluginConfig.getBoolean("disabled", false);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@PluginMethod
|
|
47
|
+
public void request(final PluginCall call) {
|
|
48
|
+
this.http(call, null);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@PluginMethod
|
|
52
|
+
public void get(final PluginCall call) {
|
|
53
|
+
this.http(call, "GET");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@PluginMethod
|
|
57
|
+
public void post(final PluginCall call) {
|
|
58
|
+
this.http(call, "POST");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@PluginMethod
|
|
62
|
+
public void put(final PluginCall call) {
|
|
63
|
+
this.http(call, "PUT");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@PluginMethod
|
|
67
|
+
public void patch(final PluginCall call) {
|
|
68
|
+
this.http(call, "PATCH");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@PluginMethod
|
|
72
|
+
public void delete(final PluginCall call) {
|
|
73
|
+
this.http(call, "DELETE");
|
|
74
|
+
}
|
|
75
|
+
}
|