Skip to content

Commit

Permalink
Manage CookieStore directly
Browse files Browse the repository at this point in the history
Fullfill the design of #115
  • Loading branch information
JingMatrix committed Sep 20, 2023
1 parent b32f814 commit 385ef69
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 52 deletions.
44 changes: 27 additions & 17 deletions app/src/main/assets/GM.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const GM_cookie = new (class {
return;
}
if (cookies == this.store && url.origin != location.origin) return;
const capitalize = (s) => s && s[0].toUpperCase() + s.slice(1);
return cookies
.filter((item) => {
if (!("name" in item && "value" in item)) return false;
Expand All @@ -138,14 +139,32 @@ const GM_cookie = new (class {
if ("domain" in item) {
let domain = item.domain;
if (domain.startsWith(".")) domain = domain.slice(1);
if (!url.hostname.endsWith(item.domain)) return false;
if (!url.hostname.endsWith(domain)) return false;
}
const expires = item.expirationDate || item.expires;
if (expires > 0) return expires * 1000 > new Date().getTime();
return true;
})
.map((item) => item.name + "=" + item.value)
.join("; ");
.map((item) => {
let header = [item.name + "=" + item.value];
header.push(`Domain=${item.domain}`);
if (Number.isFinite(item.expires) && item.expires != -1) {
const date = new Date();
date.setTime(item.expires * 1000);
header.push(`expires=${date.toUTCString()}`);
}
const props = ["path", "sameSite", "httpOnly", "secure"];
for (const prop of props) {
if (!(prop in item)) continue;
const val = item[prop];
if (typeof val == "string" && val.length != 0) {
header.push(capitalize(prop) + `=${capitalize(val)}`);
} else if (val === true) {
header.push(capitalize(prop));
}
}
return header.join("; ");
});
}
async list(details = { url: window.origin }, callback) {
let cookies, error;
Expand Down Expand Up @@ -647,7 +666,6 @@ function GM_xmlhttpRequest(details) {

const origin = new URL(details.url).origin;
if (
!("permission" in navigator) &&
location.origin == origin &&
GM_info.script.grants.includes("GM_cookie") &&
!("cookie" in details) &&
Expand All @@ -658,7 +676,10 @@ function GM_xmlhttpRequest(details) {
}
request.cookie = GM_cookie.export(details.url);
}

if (typeof request.cookie == "string") {
request.cookie = request.cookie.split("; ");
}
if (!Array.isArray(request.cookie)) delete request.cookie;
ChromeXt.dispatch("xmlhttpRequest", {
id: GM_info.script.id,
request,
Expand Down Expand Up @@ -763,7 +784,7 @@ class ResponseSink {
const key = parts.shift().toLowerCase();
var value = parts.join("=");
if (key === "expires") {
cookie.expires = new Date(value).getTime() / 1000;
cookie.expires = Date.parse(value).getTime() / 1000;
} else if (key === "max-age") {
cookie.maxAge = Number(value);
cookie.expires = cookie.maxAge + new Date().getTime() / 1000;
Expand Down Expand Up @@ -809,17 +830,6 @@ class ResponseSink {
this.xhr.error = new Error("Redirection not allowed");
this.xhr.abort();
}
if (
"permission" in navigator &&
GM_info.script.includes("GM_cookie") &&
new URL(this.xhr.finalUrl).origin == location.origin
) {
const cookies = ResponseSink.parseCookie(
this.xhr.headers.getSetCookie(),
this.xhr.finalUrl
);
GM_cookie.set(cookies, undefined, true);
}
this.xhr.total = this.xhr.headers.get("Content-Length");
if (this.xhr.total !== null) {
this.xhr.lengthComputable = true;
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/matrix/chromext/Chrome.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.os.Build
import android.os.Handler
import java.io.File
import java.lang.ref.WeakReference
import java.net.CookieManager
import java.util.concurrent.Executors
import org.json.JSONObject
import org.matrix.chromext.devtools.DevSessions
Expand Down Expand Up @@ -39,6 +40,7 @@ object Chrome {
"ChromeXt", "UserScript Notifications", NotificationManager.IMPORTANCE_DEFAULT)
.apply { description = "Notifications created by GM_notification API" }
} else null
val cookieStore = CookieManager().getCookieStore()

fun init(ctx: Context, packageName: String? = null) {
val initialized = mContext != null
Expand Down
3 changes: 0 additions & 3 deletions app/src/main/java/org/matrix/chromext/hook/UserScript.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package org.matrix.chromext.hook

import android.content.Context
import android.net.http.HttpResponseCache
import java.net.CookieHandler
import java.net.CookieManager
import org.matrix.chromext.Chrome
import org.matrix.chromext.Listener
import org.matrix.chromext.proxy.UserScriptProxy
Expand All @@ -19,7 +17,6 @@ object UserScriptHook : BaseHook() {
override fun init() {

val proxy = UserScriptProxy
CookieHandler.setDefault(CookieManager())

// proxy.tabModelJniBridge.declaredConstructors[0].hookAfter {
// Chrome.addTabModel(it.thisObject)
Expand Down
61 changes: 29 additions & 32 deletions app/src/main/java/org/matrix/chromext/utils/XMLHttpRequest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,46 @@ package org.matrix.chromext.utils

import android.util.Base64
import java.io.IOException
import java.net.CookieHandler
import java.net.CookieManager
import java.net.CookiePolicy
import java.net.HttpCookie
import java.net.HttpURLConnection
import java.net.SocketTimeoutException
import java.net.URL
import org.json.JSONArray
import org.json.JSONObject
import org.matrix.chromext.Chrome
import org.matrix.chromext.Listener
import org.matrix.chromext.hook.UserScriptHook
import org.matrix.chromext.hook.WebViewHook
import org.matrix.chromext.script.Local

class XMLHttpRequest(id: String, request: JSONObject, uuid: Double, currentTab: Any?) {
val response = JSONObject(mapOf("id" to id, "uuid" to uuid))
val request = request
val currentTab = currentTab
val request = request
val response = JSONObject(mapOf("id" to id, "uuid" to uuid))

var connection: HttpURLConnection? = null
var cookies: List<HttpCookie>

val url = URL(request.optString("url"))
val method = request.optString("method")
val headers = request.optJSONObject("headers")
val followRedirects = request.optString("redirect") != "error"
val binary = request.optBoolean("binary")
val anonymous = request.optBoolean("anonymous")
val binary = request.optBoolean("binary")
val buffersize = request.optInt("buffersize", 8)
val cookie = request.optJSONArray("cookie")
val followRedirects = request.optString("redirect") != "error"
val headers = request.optJSONObject("headers")
val method = request.optString("method")
val nocache = request.optBoolean("nocache")
val timeout = request.optInt("timeout")
val buffersize = request.optInt("buffersize", 8)
val responseType = request.optString("responseType")
val url = URL(request.optString("url"))
val uri = url.toURI()

init {
if (UserScriptHook.isInit) {
val manager = CookieHandler.getDefault() as CookieManager
if (anonymous || request.has("cookie")) {
if (anonymous) manager.setCookiePolicy(CookiePolicy.ACCEPT_NONE)
val uri = url.toURI()
val cookieStore = manager.getCookieStore()
cookieStore.get(uri).forEach { cookieStore.remove(uri, it) }
} else {
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL)
if (cookie != null && !anonymous) {
for (i in 0 until cookie.length()) {
runCatching {
HttpCookie.parse(cookie!!.getString(i)).forEach { Chrome.cookieStore.add(uri, it) }
}
}
}
cookies = Chrome.cookieStore.get(uri)
}

fun abort() {
Expand All @@ -59,12 +56,9 @@ class XMLHttpRequest(id: String, request: JSONObject, uuid: Double, currentTab:
setInstanceFollowRedirects(followRedirects)
setUseCaches(!nocache)
setConnectTimeout(timeout)
if (request.has("cookie") && !anonymous)
setRequestProperty("Cookie", request.optString("cookie"))
if (WebViewHook.isInit && !anonymous) {
val manger = android.webkit.CookieManager.getInstance()
addRequestProperty("Cookie", manger.getCookie(url.toString()))
}

if (!anonymous && cookies.size > 0)
setRequestProperty("Cookie", cookies.map { it.toString() }.joinToString("; "))

if (request.has("user")) {
val user = request.optString("user")
Expand Down Expand Up @@ -93,12 +87,15 @@ class XMLHttpRequest(id: String, request: JSONObject, uuid: Double, currentTab:
headers.containsKey("Content-Encoding") ||
(headers.get("Content-Type")?.optString(0, "")?.contains("charset") == true)
data.put("binary", binary)
if (WebViewHook.isInit && !anonymous) {
val manager = android.webkit.CookieManager.getInstance()

if (!anonymous) {
headerFields
.filter { it.key != null && it.key.startsWith("Set-Cookie") }
.forEach { it.value.forEach { manager.setCookie(url.toString(), it) } }
manager.flush()
.forEach {
it.value.forEach {
HttpCookie.parse(it).forEach { Chrome.cookieStore.add(uri, it) }
}
}
}

val buffer = ByteArray(buffersize * DEFAULT_BUFFER_SIZE)
Expand Down

0 comments on commit 385ef69

Please sign in to comment.