@capacitor/android 4.2.1-nightly-20220920T151019.0 → 4.3.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 CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [4.3.0](https://github.com/ionic-team/capacitor/compare/4.2.0...4.3.0) (2022-09-21)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **android:** open external links in browser ([#5913](https://github.com/ionic-team/capacitor/issues/5913)) ([7553ede](https://github.com/ionic-team/capacitor/commit/7553ede93170971e21ab3dec1798443d084ead2a))
12
+ * **android:** set all cookies on proxied requests ([#5781](https://github.com/ionic-team/capacitor/issues/5781)) ([5ef6a38](https://github.com/ionic-team/capacitor/commit/5ef6a3889121dd39a9159ff80250df18854bc557))
13
+ * **android:** set WebViewClient on the WebView ([#5919](https://github.com/ionic-team/capacitor/issues/5919)) ([020ed8e](https://github.com/ionic-team/capacitor/commit/020ed8eaeb7864399d4b93f54ab7601c607d8e0d))
14
+ * **core:** Exception object was not set on Cap ([#5917](https://github.com/ionic-team/capacitor/issues/5917)) ([9ca27a4](https://github.com/ionic-team/capacitor/commit/9ca27a4f8441b368f8bf9d97dda57b1a55ac0e4e))
15
+
16
+
17
+ ### Features
18
+
19
+ * Capacitor Cookies & Capacitor Http core plugins ([d4047cf](https://github.com/ionic-team/capacitor/commit/d4047cfa947676777f400389a8d65defae140b45))
20
+
21
+
22
+
23
+
24
+
6
25
  # [4.2.0](https://github.com/ionic-team/capacitor/compare/4.1.0...4.2.0) (2022-09-08)
7
26
 
8
27
  **Note:** Version bump only for package @capacitor/android
@@ -2,7 +2,7 @@
2
2
  /*! Capacitor: https://capacitorjs.com/ - MIT License */
3
3
  /* Generated File. Do not edit. */
4
4
 
5
- var nativeBridge = (function (exports) {
5
+ const nativeBridge = (function (exports) {
6
6
  'use strict';
7
7
 
8
8
  var ExceptionCode;
@@ -268,6 +268,274 @@ var nativeBridge = (function (exports) {
268
268
  }
269
269
  return String(msg);
270
270
  };
271
+ /**
272
+ * Safely web decode a string value (inspired by js-cookie)
273
+ * @param str The string value to decode
274
+ */
275
+ const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
276
+ const platform = getPlatformId(win);
277
+ if (platform == 'android' || platform == 'ios') {
278
+ // patch document.cookie on Android/iOS
279
+ win.CapacitorCookiesDescriptor =
280
+ Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
281
+ Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
282
+ let doPatchCookies = false;
283
+ // check if capacitor cookies is disabled before patching
284
+ if (platform === 'ios') {
285
+ // Use prompt to synchronously get capacitor cookies config.
286
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
287
+ const payload = {
288
+ type: 'CapacitorCookies.isEnabled',
289
+ };
290
+ const isCookiesEnabled = prompt(JSON.stringify(payload));
291
+ if (isCookiesEnabled === 'true') {
292
+ doPatchCookies = true;
293
+ }
294
+ }
295
+ else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
296
+ const isCookiesEnabled = win.CapacitorCookiesAndroidInterface.isEnabled();
297
+ if (isCookiesEnabled === true) {
298
+ doPatchCookies = true;
299
+ }
300
+ }
301
+ if (doPatchCookies) {
302
+ Object.defineProperty(document, 'cookie', {
303
+ get: function () {
304
+ if (platform === 'ios') {
305
+ // Use prompt to synchronously get cookies.
306
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
307
+ const payload = {
308
+ type: 'CapacitorCookies',
309
+ };
310
+ const res = prompt(JSON.stringify(payload));
311
+ return res;
312
+ }
313
+ else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
314
+ return win.CapacitorCookiesAndroidInterface.getCookies();
315
+ }
316
+ },
317
+ set: function (val) {
318
+ const cookiePairs = val.split(';');
319
+ for (const cookiePair of cookiePairs) {
320
+ const cookieKey = cookiePair.split('=')[0];
321
+ const cookieValue = cookiePair.split('=')[1];
322
+ if (null == cookieValue) {
323
+ continue;
324
+ }
325
+ cap.toNative('CapacitorCookies', 'setCookie', {
326
+ key: cookieKey,
327
+ value: decode(cookieValue),
328
+ });
329
+ }
330
+ },
331
+ });
332
+ }
333
+ // patch fetch / XHR on Android/iOS
334
+ // store original fetch & XHR functions
335
+ win.CapacitorWebFetch = window.fetch;
336
+ win.CapacitorWebXMLHttpRequest = {
337
+ abort: window.XMLHttpRequest.prototype.abort,
338
+ open: window.XMLHttpRequest.prototype.open,
339
+ send: window.XMLHttpRequest.prototype.send,
340
+ setRequestHeader: window.XMLHttpRequest.prototype.setRequestHeader,
341
+ };
342
+ let doPatchHttp = false;
343
+ // check if capacitor http is disabled before patching
344
+ if (platform === 'ios') {
345
+ // Use prompt to synchronously get capacitor http config.
346
+ // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
347
+ const payload = {
348
+ type: 'CapacitorHttp',
349
+ };
350
+ const isHttpEnabled = prompt(JSON.stringify(payload));
351
+ if (isHttpEnabled === 'true') {
352
+ doPatchHttp = true;
353
+ }
354
+ }
355
+ else if (typeof win.CapacitorHttpAndroidInterface !== 'undefined') {
356
+ const isHttpEnabled = win.CapacitorHttpAndroidInterface.isEnabled();
357
+ if (isHttpEnabled === true) {
358
+ doPatchHttp = true;
359
+ }
360
+ }
361
+ if (doPatchHttp) {
362
+ // fetch patch
363
+ window.fetch = async (resource, options) => {
364
+ if (resource.toString().startsWith('data:') ||
365
+ resource.toString().startsWith('blob:')) {
366
+ return win.CapacitorWebFetch(resource, options);
367
+ }
368
+ try {
369
+ // intercept request & pass to the bridge
370
+ const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
371
+ url: resource,
372
+ method: (options === null || options === void 0 ? void 0 : options.method) ? options.method : undefined,
373
+ data: (options === null || options === void 0 ? void 0 : options.body) ? options.body : undefined,
374
+ headers: (options === null || options === void 0 ? void 0 : options.headers) ? options.headers : undefined,
375
+ });
376
+ const data = typeof nativeResponse.data === 'string'
377
+ ? nativeResponse.data
378
+ : JSON.stringify(nativeResponse.data);
379
+ // intercept & parse response before returning
380
+ const response = new Response(data, {
381
+ headers: nativeResponse.headers,
382
+ status: nativeResponse.status,
383
+ });
384
+ return response;
385
+ }
386
+ catch (error) {
387
+ return Promise.reject(error);
388
+ }
389
+ };
390
+ // XHR event listeners
391
+ const addEventListeners = function () {
392
+ this.addEventListener('abort', function () {
393
+ if (typeof this.onabort === 'function')
394
+ this.onabort();
395
+ });
396
+ this.addEventListener('error', function () {
397
+ if (typeof this.onerror === 'function')
398
+ this.onerror();
399
+ });
400
+ this.addEventListener('load', function () {
401
+ if (typeof this.onload === 'function')
402
+ this.onload();
403
+ });
404
+ this.addEventListener('loadend', function () {
405
+ if (typeof this.onloadend === 'function')
406
+ this.onloadend();
407
+ });
408
+ this.addEventListener('loadstart', function () {
409
+ if (typeof this.onloadstart === 'function')
410
+ this.onloadstart();
411
+ });
412
+ this.addEventListener('readystatechange', function () {
413
+ if (typeof this.onreadystatechange === 'function')
414
+ this.onreadystatechange();
415
+ });
416
+ this.addEventListener('timeout', function () {
417
+ if (typeof this.ontimeout === 'function')
418
+ this.ontimeout();
419
+ });
420
+ };
421
+ // XHR patch abort
422
+ window.XMLHttpRequest.prototype.abort = function () {
423
+ this.readyState = 0;
424
+ this.dispatchEvent(new Event('abort'));
425
+ this.dispatchEvent(new Event('loadend'));
426
+ };
427
+ // XHR patch open
428
+ window.XMLHttpRequest.prototype.open = function (method, url) {
429
+ Object.defineProperties(this, {
430
+ _headers: {
431
+ value: {},
432
+ writable: true,
433
+ },
434
+ readyState: {
435
+ get: function () {
436
+ var _a;
437
+ return (_a = this._readyState) !== null && _a !== void 0 ? _a : 0;
438
+ },
439
+ set: function (val) {
440
+ this._readyState = val;
441
+ this.dispatchEvent(new Event('readystatechange'));
442
+ },
443
+ },
444
+ response: {
445
+ value: '',
446
+ writable: true,
447
+ },
448
+ responseText: {
449
+ value: '',
450
+ writable: true,
451
+ },
452
+ responseURL: {
453
+ value: '',
454
+ writable: true,
455
+ },
456
+ status: {
457
+ value: 0,
458
+ writable: true,
459
+ },
460
+ });
461
+ addEventListeners.call(this);
462
+ this._method = method;
463
+ this._url = url;
464
+ this.readyState = 1;
465
+ };
466
+ // XHR patch set request header
467
+ window.XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
468
+ this._headers[header] = value;
469
+ };
470
+ // XHR patch send
471
+ window.XMLHttpRequest.prototype.send = function (body) {
472
+ try {
473
+ this.readyState = 2;
474
+ // intercept request & pass to the bridge
475
+ cap
476
+ .nativePromise('CapacitorHttp', 'request', {
477
+ url: this._url,
478
+ method: this._method,
479
+ data: body !== null ? body : undefined,
480
+ headers: this._headers,
481
+ })
482
+ .then((nativeResponse) => {
483
+ // intercept & parse response before returning
484
+ if (this.readyState == 2) {
485
+ this.dispatchEvent(new Event('loadstart'));
486
+ this._headers = nativeResponse.headers;
487
+ this.status = nativeResponse.status;
488
+ this.response = nativeResponse.data;
489
+ this.responseText =
490
+ typeof nativeResponse.data === 'string'
491
+ ? nativeResponse.data
492
+ : JSON.stringify(nativeResponse.data);
493
+ this.responseURL = nativeResponse.url;
494
+ this.readyState = 4;
495
+ this.dispatchEvent(new Event('load'));
496
+ this.dispatchEvent(new Event('loadend'));
497
+ }
498
+ })
499
+ .catch((error) => {
500
+ this.dispatchEvent(new Event('loadstart'));
501
+ this.status = error.status;
502
+ this._headers = error.headers;
503
+ this.response = error.data;
504
+ this.responseText = JSON.stringify(error.data);
505
+ this.responseURL = error.url;
506
+ this.readyState = 4;
507
+ this.dispatchEvent(new Event('error'));
508
+ this.dispatchEvent(new Event('loadend'));
509
+ });
510
+ }
511
+ catch (error) {
512
+ this.dispatchEvent(new Event('loadstart'));
513
+ this.status = 500;
514
+ this._headers = {};
515
+ this.response = error;
516
+ this.responseText = error.toString();
517
+ this.responseURL = this._url;
518
+ this.readyState = 4;
519
+ this.dispatchEvent(new Event('error'));
520
+ this.dispatchEvent(new Event('loadend'));
521
+ }
522
+ };
523
+ // XHR patch getAllResponseHeaders
524
+ window.XMLHttpRequest.prototype.getAllResponseHeaders = function () {
525
+ let returnString = '';
526
+ for (const key in this._headers) {
527
+ if (key != 'Set-Cookie') {
528
+ returnString += key + ': ' + this._headers[key] + '\r\n';
529
+ }
530
+ }
531
+ return returnString;
532
+ };
533
+ // XHR patch getResponseHeader
534
+ window.XMLHttpRequest.prototype.getResponseHeader = function (name) {
535
+ return this._headers[name];
536
+ };
537
+ }
538
+ }
271
539
  // patch window.console on iOS and store original console fns
272
540
  const isIos = getPlatformId(win) === 'ios';
273
541
  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,129 @@
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.PluginConfig;
13
+ import com.getcapacitor.PluginMethod;
14
+ import com.getcapacitor.annotation.CapacitorPlugin;
15
+ import java.net.CookieHandler;
16
+ import java.net.HttpCookie;
17
+ import java.net.URI;
18
+
19
+ @CapacitorPlugin
20
+ public class CapacitorCookies extends Plugin {
21
+
22
+ CapacitorCookieManager cookieManager;
23
+
24
+ @Override
25
+ public void load() {
26
+ this.bridge.getWebView().addJavascriptInterface(this, "CapacitorCookiesAndroidInterface");
27
+ this.cookieManager = new CapacitorCookieManager(null, java.net.CookiePolicy.ACCEPT_ALL);
28
+ CookieHandler.setDefault(cookieManager);
29
+ super.load();
30
+ }
31
+
32
+ @JavascriptInterface
33
+ public boolean isEnabled() {
34
+ PluginConfig pluginConfig = getBridge().getConfig().getPluginConfiguration("CapacitorCookies");
35
+ return pluginConfig.getBoolean("enabled", false);
36
+ }
37
+
38
+ /**
39
+ * Helper function for getting the serverUrl from the Capacitor Config. Returns an empty
40
+ * string if it is invalid and will auto-reject through {@code call}
41
+ * @param call the {@code PluginCall} context
42
+ * @return the string of the server specified in the Capacitor config
43
+ */
44
+ private String getServerUrl(@Nullable PluginCall call) {
45
+ String url = (call == null) ? this.bridge.getServerUrl() : call.getString("url", this.bridge.getServerUrl());
46
+
47
+ if (url == null || url.isEmpty()) {
48
+ url = this.bridge.getLocalUrl();
49
+ }
50
+
51
+ URI uri = getUri(url);
52
+ if (uri == null) {
53
+ if (call != null) {
54
+ call.reject("Invalid URL. Check that \"server\" is passed in correctly");
55
+ }
56
+
57
+ return "";
58
+ }
59
+
60
+ return url;
61
+ }
62
+
63
+ /**
64
+ * Try to parse a url string and if it can't be parsed, return null
65
+ * @param url the url string to try to parse
66
+ * @return a parsed URI
67
+ */
68
+ private URI getUri(String url) {
69
+ try {
70
+ return new URI(url);
71
+ } catch (Exception ex) {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ @JavascriptInterface
77
+ public String getCookies() {
78
+ try {
79
+ String url = getServerUrl(null);
80
+ if (!url.isEmpty()) {
81
+ return cookieManager.getCookieString(url);
82
+ }
83
+ } catch (Exception e) {
84
+ e.printStackTrace();
85
+ }
86
+
87
+ return "";
88
+ }
89
+
90
+ @PluginMethod
91
+ public void setCookie(PluginCall call) {
92
+ String key = call.getString("key");
93
+ String value = call.getString("value");
94
+ String url = getServerUrl(call);
95
+
96
+ if (!url.isEmpty()) {
97
+ cookieManager.setCookie(url, key, value);
98
+ call.resolve();
99
+ }
100
+ }
101
+
102
+ @PluginMethod
103
+ public void deleteCookie(PluginCall call) {
104
+ String key = call.getString("key");
105
+ String url = getServerUrl(call);
106
+ if (!url.isEmpty()) {
107
+ cookieManager.setCookie(url, key + "=; Expires=Wed, 31 Dec 2000 23:59:59 GMT");
108
+ call.resolve();
109
+ }
110
+ }
111
+
112
+ @PluginMethod
113
+ public void clearCookies(PluginCall call) {
114
+ String url = getServerUrl(call);
115
+ if (!url.isEmpty()) {
116
+ HttpCookie[] cookies = cookieManager.getCookies(url);
117
+ for (HttpCookie cookie : cookies) {
118
+ cookieManager.setCookie(url, cookie.getName() + "=; Expires=Wed, 31 Dec 2000 23:59:59 GMT");
119
+ }
120
+ call.resolve();
121
+ }
122
+ }
123
+
124
+ @PluginMethod
125
+ public void clearAllCookies(PluginCall call) {
126
+ cookieManager.removeAllCookies();
127
+ call.resolve();
128
+ }
129
+ }