Skip to content

Commit

Permalink
fix(cookies): make document.cookie setter synchronous
Browse files Browse the repository at this point in the history
* fix(cookies): make document.cookie setter synchronous

* fix(cookies): remove unnecessary decoding of cookie before setting on native
  • Loading branch information
ItsChaceD committed Oct 18, 2022
1 parent c4e040a commit 2272abf
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 38 deletions.
24 changes: 14 additions & 10 deletions android/capacitor/src/main/assets/native-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,6 @@ const nativeBridge = (function (exports) {
}
return String(msg);
};
/**
* Safely web decode a string value (inspired by js-cookie)
* @param str The string value to decode
*/
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
const platform = getPlatformId(win);
if (platform == 'android' || platform == 'ios') {
// patch document.cookie on Android/iOS
Expand Down Expand Up @@ -305,7 +300,7 @@ const nativeBridge = (function (exports) {
// Use prompt to synchronously get cookies.
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
const payload = {
type: 'CapacitorCookies',
type: 'CapacitorCookies.get',
};
const res = prompt(JSON.stringify(payload));
return res;
Expand All @@ -322,10 +317,19 @@ const nativeBridge = (function (exports) {
if (null == cookieValue) {
continue;
}
cap.toNative('CapacitorCookies', 'setCookie', {
key: cookieKey,
value: decode(cookieValue),
});
if (platform === 'ios') {
// Use prompt to synchronously set cookies.
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
const payload = {
type: 'CapacitorCookies.set',
key: cookieKey,
value: cookieValue,
};
prompt(JSON.stringify(payload));
}
else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
win.CapacitorCookiesAndroidInterface.setCookie(cookieKey, cookieValue);
}
}
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package com.getcapacitor.plugin;

import android.app.Activity;
import android.content.SharedPreferences;
import android.util.Log;
import android.webkit.JavascriptInterface;
import androidx.annotation.Nullable;
import com.getcapacitor.CapConfig;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginConfig;
Expand Down Expand Up @@ -87,6 +82,15 @@ public String getCookies() {
return "";
}

@JavascriptInterface
public void setCookie(String key, String value) {
String url = getServerUrl(null);

if (!url.isEmpty()) {
cookieManager.setCookie(url, key, value);
}
}

@PluginMethod
public void setCookie(PluginCall call) {
String key = call.getString("key");
Expand Down
32 changes: 20 additions & 12 deletions core/native-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,6 @@ const initBridge = (w: any): void => {
return String(msg);
};

/**
* Safely web decode a string value (inspired by js-cookie)
* @param str The string value to decode
*/
const decode = (str: string): string =>
str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);

const platform = getPlatformId(win);

if (platform == 'android' || platform == 'ios') {
Expand Down Expand Up @@ -334,7 +327,7 @@ const initBridge = (w: any): void => {
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323

const payload = {
type: 'CapacitorCookies',
type: 'CapacitorCookies.get',
};

const res = prompt(JSON.stringify(payload));
Expand All @@ -355,10 +348,25 @@ const initBridge = (w: any): void => {
continue;
}

cap.toNative('CapacitorCookies', 'setCookie', {
key: cookieKey,
value: decode(cookieValue),
});
if (platform === 'ios') {
// Use prompt to synchronously set cookies.
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323

const payload = {
type: 'CapacitorCookies.set',
key: cookieKey,
value: cookieValue,
};

prompt(JSON.stringify(payload));
} else if (
typeof win.CapacitorCookiesAndroidInterface !== 'undefined'
) {
win.CapacitorCookiesAndroidInterface.setCookie(
cookieKey,
cookieValue,
);
}
}
},
});
Expand Down
8 changes: 8 additions & 0 deletions ios/Capacitor/Capacitor/Plugins/CapacitorCookieManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public class CapacitorCookieManager {
return value.removingPercentEncoding!
}

public func setCookie(_ key: String, _ value: String) {
let url = getServerUrl()!
let jar = HTTPCookieStorage.shared
let field = ["Set-Cookie": "\(key)=\(value)"]
let cookies = HTTPCookie.cookies(withResponseHeaderFields: field, for: url)
jar.setCookies(cookies, for: url, mainDocumentURL: url)
}

public func setCookie(_ url: URL, _ key: String, _ value: String) {
let jar = HTTPCookieStorage.shared
let field = ["Set-Cookie": "\(key)=\(value)"]
Expand Down
11 changes: 10 additions & 1 deletion ios/Capacitor/Capacitor/WebViewDelegationHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,19 @@ internal class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDel
if let payload = try JSONSerialization.jsonObject(with: dataFromString, options: .fragmentsAllowed) as? [String: AnyObject] {
let type = payload["type"] as? String

if type == "CapacitorCookies" {
if type == "CapacitorCookies.get" {
completionHandler(CapacitorCookieManager(bridge!.config).getCookies())
// Don't present prompt
return
} else if type == "CapacitorCookies.set" {
// swiftlint:disable force_cast
let key = payload["key"] as! String
let value = payload["value"] as! String
CapacitorCookieManager(bridge!.config).setCookie(key, value)
completionHandler("")
// swiftlint:enable force_cast
// Don't present prompt
return
} else if type == "CapacitorCookies.isEnabled" {
let pluginConfig = bridge!.config.getPluginConfig("CapacitorCookies")
completionHandler(String(pluginConfig.getBoolean("enabled", false)))
Expand Down
24 changes: 14 additions & 10 deletions ios/Capacitor/Capacitor/assets/native-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,6 @@ const nativeBridge = (function (exports) {
}
return String(msg);
};
/**
* Safely web decode a string value (inspired by js-cookie)
* @param str The string value to decode
*/
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
const platform = getPlatformId(win);
if (platform == 'android' || platform == 'ios') {
// patch document.cookie on Android/iOS
Expand Down Expand Up @@ -305,7 +300,7 @@ const nativeBridge = (function (exports) {
// Use prompt to synchronously get cookies.
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
const payload = {
type: 'CapacitorCookies',
type: 'CapacitorCookies.get',
};
const res = prompt(JSON.stringify(payload));
return res;
Expand All @@ -322,10 +317,19 @@ const nativeBridge = (function (exports) {
if (null == cookieValue) {
continue;
}
cap.toNative('CapacitorCookies', 'setCookie', {
key: cookieKey,
value: decode(cookieValue),
});
if (platform === 'ios') {
// Use prompt to synchronously set cookies.
// https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
const payload = {
type: 'CapacitorCookies.set',
key: cookieKey,
value: cookieValue,
};
prompt(JSON.stringify(payload));
}
else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
win.CapacitorCookiesAndroidInterface.setCookie(cookieKey, cookieValue);
}
}
},
});
Expand Down

0 comments on commit 2272abf

Please sign in to comment.