123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * @author didierfred@gmail.com
- * @version 0.4
- */
- //C:\Program Files\Google\Chrome\Application\chrome.exe --auto-open-devtools-for-tabs --load-extension=D:\mayun\LR04.02_RVCTerminalPlus_uos\addin\res\VTMModifyHeaders "file:///D:/redirect.html?url=http://oa.cmbchina.com"
- //"C:\Program Files\Google\Chrome\Application\chrome.exe" --auto-open-devtools-for-tabs --load-extension=D:\mayun\LR04.02_RVCTerminalPlus_uos\addin\res\VTMModifyHeaders "file:///D:/mayun/LR04.02_RVCTerminalPlus_uos/addin/res/ManagerDesktop/redirect.html?redirect_open=http://oa.cmbchina.com&redirect_type=ad"
- "use strict";
- // 创建自定义事件发射器
- const eventBus = new EventTarget();
- // 定义事件名
- const WS_CALLBACK_COMPLETE = 'wsCallbackComplete';
- let config;
- let started = 'on';
- let debug_mode = true;
- const isChrome = true;
- let config_read_type = 'websocket';//local,file,websocket,http
- const wsUrl = 'ws://127.0.0.1:9002?name=vtm_modify_header';
- const wsLoggerUrl = 'ws://127.0.0.1:9002?name=header_';
- let socket = null;
- let isExtensionReady = false;
- let isSuc = false;
- let dstWs_logger = wsLoggerUrl;
- let currentUrl = "";
- let urlParam = "";
- let data = "";
- function delay(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
- class WebSocketLogger {
- constructor(options) {
- // 默认配置
- const defaults = {
- url: wsLoggerUrl,
- reconnectInterval: 5000,
- maxReconnectAttempts: 3,
- logging: true
- };
- this.config = { ...defaults, ...options };
- this.ws = null;
- this.reconnectAttempts = 0;
- this.isConnected = false;
- this.messageQueue = [];
- }
- // 初始化WebSocket连接
- connect() {
- this.ws = new WebSocket(this.config.url);
- this.ws.onopen = () => {
- this.isConnected = true;
- this.reconnectAttempts = 0;
- console.log('WebSocket connected');
- this._flushMessageQueue(); // 发送积压的消息
- };
- this.ws.onclose = () => {
- this.isConnected = false;
- console.log('WebSocket disconnected');
- this._attemptReconnect();
- };
- this.ws.onerror = (error) => {
- console.error('WebSocket error:', error);
- };
- }
- // 尝试重新连接
- _attemptReconnect() {
- if (this.reconnectAttempts < this.config.maxReconnectAttempts) {
- this.reconnectAttempts++;
- console.log(`Reconnecting attempt ${this.reconnectAttempts}...`);
- setTimeout(() => this.connect(), this.config.reconnectInterval);
- } else {
- console.error('Max reconnection attempts reached');
- }
- }
- // 发送日志消息
- log(payload) {
- const defaultPayload = {
- messageType: 3080198,
- EntityName: 'header_log',
- ResultMsg: '',
- LogType: 'VTMSys',
- CostTime: 0,
- ResultCode: 'SUC0000',
- LogCode: '',
- API: 'header_log',
- SourceType: '',
- BussID: '',
- TipMsg: ''
- };
- const message = { ...defaultPayload, ...payload };
- if (this.isConnected) {
- this._sendMessage(message);
- } else {
- this.messageQueue.push(message); // 先存入队列
- if (this.messageQueue.length === 1) {
- this.connect(); // 首次断连时尝试重连
- }
- }
- }
- // 实际发送消息
- _sendMessage(message) {
- try {
- this.ws.send(JSON.stringify(message));
- if (this.config.logging) {
- console.log('Log sent:', message);
- }
- } catch (error) {
- console.error('Failed to send log:', error);
- this.messageQueue.push(message); // 失败后重新入队
- }
- }
- // 发送队列中的积压消息
- _flushMessageQueue() {
- while (this.messageQueue.length > 0 && this.isConnected) {
- const message = this.messageQueue.shift();
- this._sendMessage(message);
- }
- }
- // 关闭连接
- close() {
- if (this.ws) {
- this.ws.close();
- this.isConnected = false;
- }
- }
- }
- loadConfigurationFromLocalStorage();
- chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
- if (tabs.length > 0 && tabs[0].url) {
- console.log("Current URL2:", tabs[0].url);
- } else {
- console.error("No active tab found or URL is unavailable.");
- }
- });
- function connectWebSocket(callback_function) {
- let socket = null; // 初始化 socket 变量
- let timeoutId = setTimeout(() => {
- socket.close();
- callback_function(null); // 超时回调 null
- }, 3000); // 5秒 = 5000 毫秒
- let connectionOpened = false; // 标记连接是否已经打开
- try {
- socket = new WebSocket(wsUrl);
- } catch (error) {
- console.log('WebSocket connection creation error: ' + error);
- callback_function(null); // 连接创建失败,回调 null
- return;
- }
- socket.onmessage = function (event) {
- console.log('Received message:' + event.data);
- clearTimeout(timeoutId); // 清除定时器
- if (socket && socket.readyState === WebSocket.OPEN) { // 检查连接状态
- socket.close();
- }
- callback_function(event.data);
- return;
- };
- socket.onopen = function () {
- console.log('WebSocket connection established');
- connectionOpened = true; // 设置连接已打开标志
- // 发送配置请求
- let requestData = '{"messageType":131073}';
- console.log('Send message:' + requestData);
- socket.send(requestData);
- };
- socket.onerror = function (error) {
- console.log('WebSocket connection error:' + error);
- clearTimeout(timeoutId); // 清除定时器
- if (socket && socket.readyState === WebSocket.OPEN) { // 检查连接状态
- socket.close();
- }
- callback_function(null); // 错误回调 null
- };
- socket.onclose = function (event) {
- console.log('WebSocket connection closed:' + event.reason);
- clearTimeout(timeoutId); // 清除定时器
- connectionOpened = false; // 重置连接已打开标志
- if (event.reason !== 'Connection timed out') { // 如果不是超时关闭
- callback_function(null); // 连接意外关闭,回调 null
- }
- };
- }
- function extractUrlFromFileProtocol(fileUrl) {
- try {
- const urlObj = new URL(fileUrl);
- const params = new URLSearchParams(urlObj.search);
- const targetUrl = params.get('redirect_open');
- // 验证提取的 URL 是否合法
- if (targetUrl && (targetUrl.startsWith('http://') || targetUrl.startsWith('https://'))) {
- return targetUrl;
- }
- } catch (e) {
- console.error('Failed to parse file:// URL:', e);
- }
- return null;
- }
- function extractTypeFromFileProtocol(fileUrl) {
- try {
- const urlObj = new URL(fileUrl);
- const params = new URLSearchParams(urlObj.search);
- const targetUrl = params.get('redirect_type');
- // 验证提取的 URL 是否合法
- if (targetUrl) {
- return targetUrl;
- }
- else
- return "log";
- } catch (e) {
- console.error('Failed to parse file:// URL:', e);
- }
- return null;
- }
- function getCurrentTabUrlWithRetry(maxRetries = 40, retryDelay = 50) {
- chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
- if (tabs[0] && tabs[0].url && tabs[0].url.length > 0) {
- // 成功获取有效 URL
- currentUrl = tabs[0].url;
- console.log("当前 URL:", currentUrl);
- handleUrlLogic(currentUrl, tabs); // 处理你的业务逻辑
- } else {
- // URL 无效,触发重试
- if (maxRetries > 0) {
- console.warn(`URL 为空,剩余重试次数: ${maxRetries}`);
- setTimeout(() => {
- getCurrentTabUrlWithRetry(maxRetries - 1, retryDelay);
- }, retryDelay);
- } else {
- console.error("无法获取有效 URL,重试次数用尽");
- eventBus.dispatchEvent(new CustomEvent(WS_CALLBACK_COMPLETE, {
- detail: { success: false, data: "无法获取标签页 URL" }
- }));
- }
- }
- });
- }
- function handleUrlLogic(currentUrl, tabs) {
- const urlType = "log";
- dstWs_logger = dstWs_logger + urlType;
- if (currentUrl.startsWith('file:///')) {
- console.log("begin with file:///");
- urlParam = extractUrlFromFileProtocol(currentUrl);
- console.log("解析的url为:" + urlParam);
- if (urlParam) {
- // 使插件生效
- config = data; // modify config which make
- storeInBrowserStorage({ config: JSON.stringify(data) });
- started = 'on';
- addListener();
- isSuc = true;
- console.log("重载为:", urlParam);
- chrome.tabs.update(tabs[0].id, { url: urlParam });
-
- eventBus.dispatchEvent(new CustomEvent(WS_CALLBACK_COMPLETE, {
- detail: { success: true, data: "操作完成" }
- }));
- }
- } else {
- started = 'off';
- eventBus.dispatchEvent(new CustomEvent(WS_CALLBACK_COMPLETE, {
- detail: { success: false, data: "操作失败" }
- }));
- }
- }
- function loadConfigurationFromLocalStorage() {
-
- if (config_read_type == 'websocket') {
- connectWebSocket(function (dataStr) {
- if (dataStr == null)
- return;
- data = JSON.parse(dataStr);
- log("current new config:" + JSON.stringify(data));
- getCurrentTabUrlWithRetry();
- /*
- chrome.tabs.query({ active: true }, (tabs) => {
- chrome.tabs.update(tabs[0].id, { url: "https://oa.cmbchina.com" });
- });
- */
- });
- }
- eventBus.addEventListener(WS_CALLBACK_COMPLETE, async (e) => {
- const logger = new WebSocketLogger({
- url: dstWs_logger,
- logging: true // 开启调试日志
- });
- if (isSuc) {
- logger.log({
- ResultMsg: "重载为:" + urlParam
- });
- } else {
- logger.log({
- ResultMsg: "不运行插件, 当前url地址为:" + currentUrl
- });
- }
- logger.close();
- });
- }
- function loadFromBrowserStorage(item, callback_function) {
- chrome.storage.local.get(item, callback_function);
- }
- function storeInBrowserStorage(item, callback_function) {
- chrome.storage.local.set(item, callback_function);
- }
- function cookie_keyvalues_set(original_cookies, key, value) {
- let new_element = " " + key + "=" + value; // not used if value is undefined.
- let cookies_ar = original_cookies.split(";").filter(e => e.trim().length > 0);
- let selected_cookie_index = cookies_ar.findIndex(kv => kv.trim().startsWith(key + "="));
- if ((selected_cookie_index == -1) && (value != undefined)) cookies_ar.push(new_element);
- else {
- if (value === undefined)
- cookies_ar.splice(selected_cookie_index, 1);
- else
- cookies_ar.splice(selected_cookie_index, 1, new_element);
- }
- return cookies_ar.join(";");
- }
- function set_cookie_modify_cookie_value(original_set_cookie_header_content, key, new_value) {
- let trimmed = original_set_cookie_header_content.trimStart();
- let original_attributes = trimmed.indexOf(";") === -1 ? "" : trimmed.substring(trimmed.indexOf(";"))
- return key + "=" + new_value + original_attributes;
- }
- /*
- * Standard function to log messages
- *
- */
- function log(message) {
- console.log(new Date() + " SimpleModifyHeader : " + message);
- }
- /*
- * Rewrite the request header (add , modify or delete)
- *
- */
- function rewriteRequestHeader(e) {
- if (config.debug_mode)
- log("Start modify request headers for url " + e.url + "use_url_excepts:" + config.use_url_excepts)
- for (let to_modify of config.headers) {
- if (config.debug_mode)
- log("to_modify.url_contains:" + to_modify.url_contains + " e.url:" + e.url + ", result:" + !e.url.includes(to_modify.url_contains.trim()));
- const shouldApplyModification = (to_modify, config, e) => {
- const isStatusOn = to_modify.status === "on";
- const isApplyOnReq = to_modify.apply_on === "req";
- const isUrlExcepted = config.use_url_excepts
- ? to_modify.url_contains.length > 0 && e.url.includes(to_modify.url_contains.trim())
- : false;
- return isStatusOn && isApplyOnReq && !isUrlExcepted;
- };
- if (shouldApplyModification(to_modify, config, e)) {
- if (to_modify.action === "add") {
- let new_header = { "name": to_modify.header_name, "value": to_modify.header_value };
- e.requestHeaders.push(new_header);
- if (config.debug_mode) log("Add request header : name=" + to_modify.header_name +
- ",value=" + to_modify.header_value + " for url " + e.url + " url_contains " + to_modify.url_contains);
- }
- else if (to_modify.action === "modify") {
- log("modify request header");
- for (let header of e.requestHeaders) {
- if (header.name.toLowerCase() === to_modify.header_name.toLowerCase()) {
- if (config.debug_mode) log("Modify request header : name= " + to_modify.header_name +
- ",old value=" + header.value + ",new value=" + to_modify.header_value +
- " for url " + e.url);
- header.value = to_modify.header_value;
- }
- }
- }
- else if (to_modify.action === "delete") {
- log("Delete request header");
- let index = -1;
- for (let i = 0; i < e.requestHeaders.length; i++) {
- if (e.requestHeaders[i].name.toLowerCase() === to_modify.header_name.toLowerCase()) index = i;
- }
- if (index !== -1) {
- e.requestHeaders.splice(index, 1);
- if (config.debug_mode) log("Delete request header : name=" + to_modify.header_name.toLowerCase() +
- " for url " + e.url);
- }
- }
- else if (to_modify.action === "cookie_add_or_modify") {
- log("cookie_add_or_modify.req");
- let header_cookie = e.requestHeaders.find(header => header.name.toLowerCase() === "cookie");
- let new_cookie = cookie_keyvalues_set(header_cookie === undefined ? "" : header_cookie.value, to_modify.header_name, to_modify.header_value);
- if (header_cookie === undefined) {
- e.requestHeaders.push({ "name": "Cookie", "value": new_cookie });
- if (config.debug_mode) log("cookie_add_or_modify.req new_header : name=Cookie,value=" + new_cookie + " for url " + e.url);
- }
- else {
- header_cookie.value = new_cookie;
- if (config.debug_mode) log("cookie_add_or_modify.req modify_header : name=Cookie,value=" + new_cookie + " for url " + e.url);
- }
- }
- else if (to_modify.action === "cookie_delete") {
- log("cookie_delete.req");
- let header_cookie = e.requestHeaders.find(header => header.name.toLowerCase() === "cookie");
- let new_cookie = cookie_keyvalues_set(header_cookie === undefined ? "" : header_cookie.value, to_modify.header_name, undefined);
- if (header_cookie === undefined) {
- if (config.debug_mode) log("cookie_delete.req: no cookie header found. doing nothing for url " + e.url);
- }
- else {
- header_cookie.value = new_cookie;
- if (config.debug_mode) log("cookie_delete.req modify_header : name=Cookie,value=" + new_cookie + " for url " + e.url);
- }
- }
- }
- }
- if (config.debug_mode) log("End modify request headers for url " + e.url);
- return { requestHeaders: e.requestHeaders };
- }
- /*
- * Rewrite the response header (add , modify or delete)
- *
- */
- function rewriteResponseHeader(e) {
- //if (config.debug_mode) log("Start modify response headers for url " + e.url);
- for (let to_modify of config.headers) {
- if ((to_modify.status === "on") && (to_modify.apply_on === "res") && (!config.use_url_excepts || (config.use_url_excepts && e.url.includes(to_modify.url_contains.trim())))) {
- if (to_modify.action === "add") {
- let new_header = { "name": to_modify.header_name, "value": to_modify.header_value };
- e.responseHeaders.push(new_header);
- if (config.debug_mode) log("Add response header : name=" + to_modify.header_name
- + ",value=" + to_modify.header_value + " for url " + e.url);
- }
- else if (to_modify.action === "modify") {
- for (let header of e.responseHeaders) {
- if (header.name.toLowerCase() === to_modify.header_name.toLowerCase()) {
- if (config.debug_mode) log("Modify response header : name= " + to_modify.header_name + ",old value="
- + header.value + ",new value=" + to_modify.header_value + " for url " + e.url);
- header.value = to_modify.header_value;
- }
- }
- }
- else if (to_modify.action === "delete") {
- let index = -1;
- for (let i = 0; i < e.responseHeaders.length; i++) {
- if (e.responseHeaders[i].name.toLowerCase() === to_modify.header_name.toLowerCase()) index = i;
- }
- if (index !== -1) {
- e.responseHeaders.splice(index, 1);
- if (config.debug_mode) log("Delete response header : name=" + to_modify.header_name.toLowerCase()
- + " for url " + e.url);
- }
- }
- else if (to_modify.action === "cookie_add_or_modify") {
- let header_cookie = e.responseHeaders.find(header =>
- header.name.toLowerCase() === "set-cookie" &&
- header.value.toLowerCase().trim().startsWith(to_modify.header_name.toLowerCase() + "=")
- );
- let new_header_value = set_cookie_modify_cookie_value(header_cookie === undefined ? "" : header_cookie.value, to_modify.header_name, to_modify.header_value);
- if (header_cookie === undefined) {
- log("SimpleModifyHeaders.Warning: you're using cookie_add_or_modify in Response. While adding new cookie in response, this plugin only generates `Set-Cookie: cookie-name=cookie-value `, without ANY additional attributes. Add a `Set-Cookie` header if you need them. ");
- e.responseHeaders.push({ "name": "Set-Cookie", "value": new_header_value });
- if (config.debug_mode) log("cookie_add_or_modify.resp new_header : name=Cookie,value=" + new_header_value + " for url " + e.url);
- }
- else {
- header_cookie.value = new_header_value;
- if (config.debug_mode) log("cookie_add_or_modify.resp modify_header : name=Cookie,value=" + new_header_value + " for url " + e.url);
- }
- }
- else if (to_modify.action === "cookie_delete") {
- let index = e.responseHeaders.findIndex(header =>
- header.name.toLowerCase() === "set-cookie" &&
- header.value.toLowerCase().trim().startsWith(to_modify.header_name.toLowerCase() + "=")
- );
- if (index === -1) {
- if (config.debug_mode) log("cookie_delete.resp: no matching set-cookie header. doing nothing for url " + e.url);
- }
- else {
- e.responseHeaders.splice(index, 1);
- if (config.debug_mode) log("cookie_delete.resp delete_header : name=" + to_modify.header_name + " for url " + e.url);
- }
- }
- }
- }
- //if (config.debug_mode) log("End modify response headers for url " + e.url);
- return { responseHeaders: e.responseHeaders };
- }
- /*
- * Listen for message form config.js
- * if message is reload : reload the configuration
- * if message is on : start the modify header
- * if message is off : stop the modify header
- *
- **/
- function notify(message) {
- if (message === "reload") {
- if (config.debug_mode) log("Reload configuration");
- loadFromBrowserStorage(['config'], function (result) {
- config = JSON.parse(result.config);
- if (started === "on") {
- removeListener();
- addListener();
- }
- });
- }
- else if (message === "off") {
- removeListener();
- started = "off";
- if (config.debug_mode) log("Stop modifying headers");
- }
- else if (message === "on") {
- addListener();
- started = "on";
- if (config.debug_mode) log("Start modifying headers");
- }
- }
- /*
- * Add rewriteRequestHeader as a listener to onBeforeSendHeaders, only for the target pages.
- * Add rewriteResponseHeader as a listener to onHeadersReceived, only for the target pages.
- * Make it "blocking" so we can modify the headers.
- */
- function addListener() {
- //return;
- let target = "<all_urls>";
- // need to had "extraHeaders" option for chrome https://developer.chrome.com/extensions/webRequest#life_cycle_footnote
- if (isChrome) {
- chrome.webRequest.onBeforeSendHeaders.addListener(rewriteRequestHeader,
- { urls: target.split(";") },
- ["blocking", "requestHeaders", "extraHeaders"]);
- chrome.webRequest.onHeadersReceived.addListener(rewriteResponseHeader,
- { urls: target.split(";") },
- ["blocking", "responseHeaders", "extraHeaders"]);
- }
- else {
- chrome.webRequest.onBeforeSendHeaders.addListener(rewriteRequestHeader,
- { urls: target.split(";") },
- ["blocking", "requestHeaders"]);
- chrome.webRequest.onHeadersReceived.addListener(rewriteResponseHeader,
- { urls: target.split(";") },
- ["blocking", "responseHeaders"]);
- }
- }
- /*
- * Remove the two listener
- *
- */
- function removeListener() {
- chrome.webRequest.onBeforeSendHeaders.removeListener(rewriteRequestHeader);
- chrome.webRequest.onHeadersReceived.removeListener(rewriteResponseHeader);
- }
|