vg-coder-cli 2.0.31 → 2.0.33
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/README.md +0 -11
- package/dist/vg-coder-bundle.js +42 -0
- package/package.json +19 -11
- package/src/index.js +28 -220
- package/src/server/api-server.js +120 -428
- package/src/server/views/css/bubble.css +81 -0
- package/src/server/views/css/code-viewer.css +58 -0
- package/src/server/views/css/terminal.css +59 -155
- package/src/server/views/dashboard.css +78 -678
- package/src/server/views/dashboard.html +39 -278
- package/src/server/views/js/api.js +2 -22
- package/src/server/views/js/config.js +27 -15
- package/src/server/views/js/event-protocol.js +263 -0
- package/src/server/views/js/features/bubble-features/index.js +125 -0
- package/src/server/views/js/features/bubble-features/paste-run-feature.js +16 -0
- package/src/server/views/js/features/bubble-features/terminal-feature.js +16 -0
- package/src/server/views/js/features/bubble.js +175 -0
- package/src/server/views/js/features/code-viewer.js +90 -0
- package/src/server/views/js/features/commands.js +34 -81
- package/src/server/views/js/features/editor-tabs.js +19 -46
- package/src/server/views/js/features/git-view.js +63 -81
- package/src/server/views/js/features/iframe-manager.js +3 -97
- package/src/server/views/js/features/monaco-manager.js +19 -39
- package/src/server/views/js/features/project-switcher.js +7 -63
- package/src/server/views/js/features/resize.js +5 -16
- package/src/server/views/js/features/structure.js +38 -106
- package/src/server/views/js/features/terminal.js +102 -418
- package/src/server/views/js/handlers.js +60 -43
- package/src/server/views/js/main.js +75 -179
- package/src/server/views/js/shadow-entry.js +21 -0
- package/src/server/views/js/utils.js +48 -28
- package/src/server/views/vg-coder/_metadata/generated_indexed_rulesets/_ruleset1 +0 -0
- package/src/server/views/vg-coder/controller.js +33 -258
- package/.vgignore +0 -10
- package/src/server/views/dashboard.js +0 -457
- package/test-pty.js +0 -31
- package/vetgo-auto/README.md +0 -3
- package/vetgo-auto/chrome/CSP_IMPROVEMENTS.md +0 -147
- package/vetgo-auto/chrome/MANIFEST_V3_MIGRATION.md +0 -123
- package/vetgo-auto/chrome/assets/icon128.png +0 -0
- package/vetgo-auto/chrome/assets/icon16.png +0 -0
- package/vetgo-auto/chrome/assets/icon48.png +0 -0
- package/vetgo-auto/chrome/environments/environment.ts +0 -13
- package/vetgo-auto/chrome/manifest.json +0 -66
- package/vetgo-auto/chrome/rules.json +0 -23
- package/vetgo-auto/chrome/src/background.ts +0 -200
- package/vetgo-auto/chrome/src/controller.ts +0 -172
- package/vetgo-auto/chrome/src/controllers/common.firebase.ts +0 -31
- package/vetgo-auto/chrome/src/controllers/firebase-crud.ts +0 -147
- package/vetgo-auto/chrome/src/controllers/load-common-fuc.controller.ts +0 -24
- package/vetgo-auto/chrome/src/controllers/load-script.controller.ts +0 -23
- package/vetgo-auto/chrome/src/script-injector.ts +0 -305
- package/vetgo-auto/chrome/src/sidepanel.css +0 -166
- package/vetgo-auto/chrome/src/sidepanel.html +0 -48
- package/vetgo-auto/chrome/src/sidepanel.ts +0 -127
- package/vetgo-auto/chrome/src/utils/ai-domains.ts +0 -33
- package/vetgo-auto/chrome/src/utils/db-utils.ts +0 -2
- package/vetgo-auto/chrome/src/utils/environment-storage.service.ts +0 -85
- package/vetgo-auto/chrome/src/utils/injector-script.ts +0 -272
- package/vetgo-auto/chrome/webpack.config.js +0 -53
- package/vetgo-auto/chrome/webpack.config.prod.js +0 -54
- package/vetgo-auto/package.json +0 -30
- package/vetgo-auto/tsconfig.json +0 -27
- package/vetgo-auto/vg-coder.zip +0 -0
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# VetGo Pro Extension - Manifest V3 Migration
|
|
2
|
-
|
|
3
|
-
## Tóm tắt các thay đổi
|
|
4
|
-
|
|
5
|
-
Extension VetGo Pro đã được cập nhật thành công từ Manifest V2 lên Manifest V3. Dưới đây là chi tiết các thay đổi:
|
|
6
|
-
|
|
7
|
-
## 1. Cập nhật manifest.json
|
|
8
|
-
|
|
9
|
-
### Thay đổi chính:
|
|
10
|
-
- `manifest_version`: 2 → 3
|
|
11
|
-
- `background.scripts` → `background.service_worker`
|
|
12
|
-
- Tách `permissions` thành `permissions` và `host_permissions`
|
|
13
|
-
- Cập nhật `content_security_policy` theo chuẩn V3
|
|
14
|
-
- Thêm `declarative_net_request` configuration
|
|
15
|
-
|
|
16
|
-
### Permissions mới:
|
|
17
|
-
- Thêm `scripting` permission
|
|
18
|
-
- Thêm `declarativeNetRequest` permission
|
|
19
|
-
- Chuyển `<all_urls>` sang `host_permissions`
|
|
20
|
-
|
|
21
|
-
## 2. Background Script → Service Worker
|
|
22
|
-
|
|
23
|
-
### Thay đổi trong background.ts:
|
|
24
|
-
- Loại bỏ `webRequest.onHeadersReceived` (blocking)
|
|
25
|
-
- Thay thế bằng `declarativeNetRequest` rules
|
|
26
|
-
- Cập nhật `webRequest.onBeforeRequest` → `webNavigation.onCompleted`
|
|
27
|
-
- Thay thế `chrome.tabs.executeScript` → `chrome.scripting.executeScript`
|
|
28
|
-
- Cải thiện error handling với `chrome.runtime.lastError`
|
|
29
|
-
|
|
30
|
-
## 3. Declarative Net Request
|
|
31
|
-
|
|
32
|
-
### File rules.json mới:
|
|
33
|
-
- Tự động loại bỏ `content-security-policy` headers
|
|
34
|
-
- Tự động loại bỏ `x-frame-options` headers
|
|
35
|
-
- Áp dụng cho tất cả main_frame và sub_frame
|
|
36
|
-
|
|
37
|
-
## 4. Content Script Updates
|
|
38
|
-
|
|
39
|
-
### Thay đổi trong controller.ts:
|
|
40
|
-
- Thêm TypeScript types cho parameters
|
|
41
|
-
- Cải thiện error handling
|
|
42
|
-
- Thêm null checks cho DOM elements
|
|
43
|
-
|
|
44
|
-
## 5. Build Configuration
|
|
45
|
-
|
|
46
|
-
### Webpack updates:
|
|
47
|
-
- Thêm copy rules.json vào cả dev và production builds
|
|
48
|
-
- Cập nhật cả webpack.config.js và webpack.config.prod.js
|
|
49
|
-
|
|
50
|
-
## 6. Tương thích ngược
|
|
51
|
-
|
|
52
|
-
### Chức năng được bảo toàn:
|
|
53
|
-
✅ Inject scripts động vào trang web
|
|
54
|
-
✅ Lưu sheetID và profile vào localStorage
|
|
55
|
-
✅ Quản lý Zalo tabs (đóng tab trùng lặp)
|
|
56
|
-
✅ Giao tiếp giữa content script và background
|
|
57
|
-
✅ Tự xóa extension functionality
|
|
58
|
-
✅ Chrome ID management
|
|
59
|
-
|
|
60
|
-
### Cải tiến:
|
|
61
|
-
✅ Hiệu suất tốt hơn với service worker
|
|
62
|
-
✅ Bảo mật tăng cường với CSP mới
|
|
63
|
-
✅ Declarative rules thay vì blocking requests
|
|
64
|
-
✅ Better error handling
|
|
65
|
-
|
|
66
|
-
## 7. Testing
|
|
67
|
-
|
|
68
|
-
Extension đã được test build thành công:
|
|
69
|
-
- Development build: ✅ Passed
|
|
70
|
-
- Production build: ✅ Passed
|
|
71
|
-
- Package creation: ✅ Passed
|
|
72
|
-
|
|
73
|
-
## 8. Deployment
|
|
74
|
-
|
|
75
|
-
File `vetgo-extension-build.zip` đã sẵn sàng để upload lên Chrome Web Store.
|
|
76
|
-
|
|
77
|
-
## 9. Giải pháp CSP Script Injection
|
|
78
|
-
|
|
79
|
-
### Vấn đề:
|
|
80
|
-
Extension gặp lỗi CSP khi inject inline script:
|
|
81
|
-
```
|
|
82
|
-
Refused to execute inline script because it violates the following Content Security Policy directive
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Giải pháp đa tầng:
|
|
86
|
-
1. **ScriptInjector Class**: Tạo class với 4 phương pháp injection
|
|
87
|
-
- **Blob URL**: Tạo blob object và inject qua src
|
|
88
|
-
- **Data URL**: Sử dụng base64 data URL
|
|
89
|
-
- **Background Injection**: Sử dụng chrome.scripting với world: 'MAIN'
|
|
90
|
-
- **PostMessage Bridge**: Tạo bridge script để giao tiếp
|
|
91
|
-
|
|
92
|
-
2. **Fallback Chain**: Thử từng phương pháp cho đến khi thành công
|
|
93
|
-
|
|
94
|
-
3. **Async Handling**: Chuyển sang async/await pattern
|
|
95
|
-
|
|
96
|
-
### Files mới:
|
|
97
|
-
- `chrome/src/script-injector.ts`: Class xử lý injection với DOM safety
|
|
98
|
-
- Cập nhật `controller.ts` để sử dụng ScriptInjector và DOM ready detection
|
|
99
|
-
- `chrome/test-injection.html`: Test page để verify script injection
|
|
100
|
-
|
|
101
|
-
### Fixes cho DOM Issues:
|
|
102
|
-
- **getHeadElement()**: Safe method để get head element với fallbacks
|
|
103
|
-
- **waitForDOM()**: Promise-based DOM ready detection
|
|
104
|
-
- **Error handling**: Comprehensive error handling cho tất cả injection methods
|
|
105
|
-
- **Async/await**: Proper async handling để tránh race conditions
|
|
106
|
-
|
|
107
|
-
## 10. Lưu ý quan trọng
|
|
108
|
-
|
|
109
|
-
1. **Service Worker Limitations**: Service workers có lifecycle khác background pages, có thể bị terminate sau một thời gian không hoạt động.
|
|
110
|
-
|
|
111
|
-
2. **Declarative Net Request**: Không thể modify requests dynamically như webRequest, chỉ có thể sử dụng static rules.
|
|
112
|
-
|
|
113
|
-
3. **CSP Restrictions**: Một số website có CSP rất nghiêm ngặt, cần multiple fallback methods.
|
|
114
|
-
|
|
115
|
-
4. **Chrome Store Review**: Manifest V3 extensions có thể cần review kỹ hơn từ Chrome Web Store.
|
|
116
|
-
|
|
117
|
-
## 11. Khuyến nghị
|
|
118
|
-
|
|
119
|
-
- Test kỹ trên nhiều website khác nhau, đặc biệt các site có CSP nghiêm ngặt
|
|
120
|
-
- Monitor console logs để đảm bảo script injection thành công
|
|
121
|
-
- Kiểm tra performance impact của multiple injection methods
|
|
122
|
-
- Chuẩn bị rollback plan nếu cần thiết
|
|
123
|
-
- Test trên các browser khác nhau (Chrome, Edge, etc.)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const environment = {
|
|
2
|
-
production: false,
|
|
3
|
-
environmentName: 'VGCODER',
|
|
4
|
-
firebaseConfig: {
|
|
5
|
-
apiKey: "AIzaSyDrpNMso-DXeN7c4vwbpV0idpxnV2vtXhQ",
|
|
6
|
-
authDomain: "vetgo-chrome.firebaseapp.com",
|
|
7
|
-
databaseURL: "https://vetgo-chrome-default-rtdb.asia-southeast1.firebasedatabase.app",
|
|
8
|
-
projectId: "vetgo-chrome",
|
|
9
|
-
storageBucket: "vetgo-chrome.appspot.com",
|
|
10
|
-
messagingSenderId: "211178224097",
|
|
11
|
-
appId: "1:211178224097:web:f73bf5a81c2f4c32fc7aa0"
|
|
12
|
-
}
|
|
13
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"manifest_version": 3,
|
|
3
|
-
"name": "VetGo Pro",
|
|
4
|
-
"short_name": "VetGoPro",
|
|
5
|
-
"version": "1.0.0",
|
|
6
|
-
"description": "VetGo Copyright VetGo ",
|
|
7
|
-
"permissions": [
|
|
8
|
-
"sidePanel",
|
|
9
|
-
"management",
|
|
10
|
-
"webNavigation",
|
|
11
|
-
"notifications",
|
|
12
|
-
"cookies",
|
|
13
|
-
"storage",
|
|
14
|
-
"tabs",
|
|
15
|
-
"nativeMessaging",
|
|
16
|
-
"downloads",
|
|
17
|
-
"scripting",
|
|
18
|
-
"declarativeNetRequest"
|
|
19
|
-
],
|
|
20
|
-
"host_permissions": [
|
|
21
|
-
"<all_urls>"
|
|
22
|
-
],
|
|
23
|
-
"icons": {
|
|
24
|
-
"128": "assets/icon128.png",
|
|
25
|
-
"48": "assets/icon48.png",
|
|
26
|
-
"16": "assets/icon16.png"
|
|
27
|
-
},
|
|
28
|
-
"action": {
|
|
29
|
-
"default_title": "VetGo Pro - Cấu hình",
|
|
30
|
-
"default_icon": {
|
|
31
|
-
"128": "assets/icon128.png",
|
|
32
|
-
"48": "assets/icon48.png",
|
|
33
|
-
"16": "assets/icon16.png"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"content_scripts": [
|
|
37
|
-
{
|
|
38
|
-
"matches": [
|
|
39
|
-
"<all_urls>"
|
|
40
|
-
],
|
|
41
|
-
"js": [
|
|
42
|
-
"controller.js"
|
|
43
|
-
],
|
|
44
|
-
"all_frames": true,
|
|
45
|
-
"run_at": "document_start"
|
|
46
|
-
}
|
|
47
|
-
],
|
|
48
|
-
"background": {
|
|
49
|
-
"service_worker": "background.js"
|
|
50
|
-
},
|
|
51
|
-
"content_security_policy": {
|
|
52
|
-
"extension_pages": "script-src 'self'; object-src 'self'"
|
|
53
|
-
},
|
|
54
|
-
"side_panel": {
|
|
55
|
-
"default_path": "sidepanel.html"
|
|
56
|
-
},
|
|
57
|
-
"declarative_net_request": {
|
|
58
|
-
"rule_resources": [
|
|
59
|
-
{
|
|
60
|
-
"id": "ruleset_1",
|
|
61
|
-
"enabled": true,
|
|
62
|
-
"path": "rules.json"
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": 1,
|
|
4
|
-
"priority": 1,
|
|
5
|
-
"action": {
|
|
6
|
-
"type": "modifyHeaders",
|
|
7
|
-
"responseHeaders": [
|
|
8
|
-
{
|
|
9
|
-
"header": "content-security-policy",
|
|
10
|
-
"operation": "remove"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"header": "x-frame-options",
|
|
14
|
-
"operation": "remove"
|
|
15
|
-
}
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
"condition": {
|
|
19
|
-
"urlFilter": "*",
|
|
20
|
-
"resourceTypes": ["main_frame", "sub_frame"]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
]
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { LoadScriptController } from "./controllers/load-script.controller";
|
|
2
|
-
import { Observable } from "rxjs";
|
|
3
|
-
import { CommonFunc } from "./controllers/load-common-fuc.controller";
|
|
4
|
-
import { uuid } from "./utils/db-utils";
|
|
5
|
-
|
|
6
|
-
// Type declaration for chrome.sidePanel API (not yet in @types/chrome)
|
|
7
|
-
declare global {
|
|
8
|
-
namespace chrome {
|
|
9
|
-
namespace sidePanel {
|
|
10
|
-
function open(options: { tabId?: number; windowId?: number }): Promise<void>;
|
|
11
|
-
function setOptions(options: { tabId?: number; path?: string; enabled?: boolean }): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Handle extension icon click to open side panel
|
|
17
|
-
chrome.action.onClicked.addListener((tab) => {
|
|
18
|
-
if (tab.id) {
|
|
19
|
-
(chrome as any).sidePanel.open({ tabId: tab.id }).catch((err: Error) => {
|
|
20
|
-
console.error('Failed to open side panel:', err);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Service Worker không hỗ trợ BehaviorSubject như trong background page
|
|
27
|
-
// Sử dụng chrome.storage để lưu trữ state thay thế
|
|
28
|
-
// const $eventOpenZalo = new BehaviorSubject<boolean>(null);
|
|
29
|
-
|
|
30
|
-
// Manifest V3 không còn hỗ trợ webRequest blocking
|
|
31
|
-
// Chuyển sang sử dụng declarativeNetRequest thông qua rules.json
|
|
32
|
-
// Headers sẽ được xử lý bởi declarative rules thay vì code
|
|
33
|
-
|
|
34
|
-
// Manifest V3: Thay thế webRequest.onBeforeRequest bằng webNavigation
|
|
35
|
-
// Vì không thể chặn request, ta sẽ lắng nghe navigation events
|
|
36
|
-
chrome.webNavigation.onCompleted.addListener(async (details) => {
|
|
37
|
-
if (details.frameId === 0) { // Chỉ xử lý main frame
|
|
38
|
-
try {
|
|
39
|
-
const url = new URL(details.url);
|
|
40
|
-
const params = new URLSearchParams(url.search);
|
|
41
|
-
const sheetID = params.get('sheetID');
|
|
42
|
-
const profile = params.get('profile');
|
|
43
|
-
|
|
44
|
-
if (sheetID) {
|
|
45
|
-
console.log('Found navigation with sheetID:', details.url);
|
|
46
|
-
// Manifest V3: Sử dụng chrome.scripting thay vì chrome.tabs.executeScript
|
|
47
|
-
await chrome.scripting.executeScript({
|
|
48
|
-
target: { tabId: details.tabId },
|
|
49
|
-
func: (sheetID) => {
|
|
50
|
-
localStorage.setItem("sheetID", sheetID);
|
|
51
|
-
},
|
|
52
|
-
args: [sheetID]
|
|
53
|
-
});
|
|
54
|
-
console.log('sheetID saved to local storage:', sheetID);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (profile) {
|
|
58
|
-
console.log('Found navigation with profile:', details.url);
|
|
59
|
-
await chrome.scripting.executeScript({
|
|
60
|
-
target: { tabId: details.tabId },
|
|
61
|
-
func: (profile) => {
|
|
62
|
-
localStorage.setItem("phone", profile);
|
|
63
|
-
},
|
|
64
|
-
args: [profile]
|
|
65
|
-
});
|
|
66
|
-
console.log('profile saved to local storage:', profile);
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error('Error processing navigation:', error);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
chrome.webNavigation.onBeforeNavigate.addListener((details) => {
|
|
75
|
-
// Log the URL of the navigation
|
|
76
|
-
console.log('Navigating to:', details.url);
|
|
77
|
-
chrome.tabs.query({ currentWindow: true }, (tabs) => {
|
|
78
|
-
tabs.filter(tab => tab.url && tab.url.includes('id.zalo.me')).forEach((tab) => {
|
|
79
|
-
if(tab.id && tab.id !== details.tabId) {
|
|
80
|
-
chrome.tabs.remove(tab.id);
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
}, { url: [{ hostEquals: 'id.zalo.me' }] });
|
|
85
|
-
const getChromeId = ():Observable<string> =>{
|
|
86
|
-
return new Observable((ob) => {
|
|
87
|
-
chrome.storage.sync.get(({id}) => {
|
|
88
|
-
if(!id) {
|
|
89
|
-
const chromeId = uuid();
|
|
90
|
-
chrome.storage.sync.set({id: chromeId});
|
|
91
|
-
ob.next(chromeId);
|
|
92
|
-
} else {
|
|
93
|
-
ob.next(id);
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
chrome.runtime.onInstalled.addListener(() => {
|
|
99
|
-
getChromeId().subscribe((id) => {
|
|
100
|
-
console.log("id",id);
|
|
101
|
-
});
|
|
102
|
-
// chrome.storage.sync.clear(() => console.log("Clear store......"));
|
|
103
|
-
// chrome.cookies.getAll({}, function(cookies) {
|
|
104
|
-
// var json = JSON.stringify(cookies);
|
|
105
|
-
// var blob = new Blob([json], {type: "application/json"});
|
|
106
|
-
// var url = URL.createObjectURL(blob);
|
|
107
|
-
//
|
|
108
|
-
// chrome.downloads.download({
|
|
109
|
-
// url: url,
|
|
110
|
-
// filename: "cookies.json"
|
|
111
|
-
// });
|
|
112
|
-
// });
|
|
113
|
-
});
|
|
114
|
-
// function zaloTab() {
|
|
115
|
-
// chrome.tabs.query({ currentWindow: true }, (tabs) => {
|
|
116
|
-
// const isNewTab = tabs.map(tab => tab.url).some( url => url.includes('chat.zalo.me') || url.includes('id.zalo.me'));
|
|
117
|
-
// if(!isNewTab) {
|
|
118
|
-
// chrome.tabs.create({ url: 'https://chat.zalo.me', active: false });
|
|
119
|
-
// }
|
|
120
|
-
// });
|
|
121
|
-
// }
|
|
122
|
-
// Listen for tab removal
|
|
123
|
-
// chrome.tabs.onActivated.addListener((activeInfo) => {
|
|
124
|
-
// $eventOpenZalo.next(true);
|
|
125
|
-
// });
|
|
126
|
-
// chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
|
|
127
|
-
// $eventOpenZalo.next(true);
|
|
128
|
-
// });
|
|
129
|
-
chrome.tabs.onCreated.addListener(() => {
|
|
130
|
-
// console.log(JSON.stringify(tab));
|
|
131
|
-
// alert(JSON.stringify(tab))
|
|
132
|
-
});
|
|
133
|
-
chrome.cookies.onChanged.addListener(() => {
|
|
134
|
-
// console.log(JSON.stringify(changeInfo.cookie))
|
|
135
|
-
});
|
|
136
|
-
chrome.runtime.onMessage.addListener((request, sender, respond) => {
|
|
137
|
-
console.log(sender.tab ?
|
|
138
|
-
"from a content script:" + sender.tab.url :
|
|
139
|
-
"from the extension");
|
|
140
|
-
const handler = new Promise((resolve, reject) => {
|
|
141
|
-
if ( request.action === 'REMOVE_EXTENSION' ) {
|
|
142
|
-
// ham nay de tu xoa extension
|
|
143
|
-
chrome.management.uninstallSelf();
|
|
144
|
-
resolve(request);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
if(request.action === 'SHEET') {
|
|
148
|
-
resolve(request);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (request.action === 'INJECT_SCRIPT') {
|
|
152
|
-
// Inject script using chrome.scripting API to bypass CSP
|
|
153
|
-
if (sender.tab && sender.tab.id) {
|
|
154
|
-
chrome.scripting.executeScript({
|
|
155
|
-
target: { tabId: sender.tab.id },
|
|
156
|
-
world: 'MAIN', // Execute in main world to access page's window object
|
|
157
|
-
func: (scriptCode) => {
|
|
158
|
-
try {
|
|
159
|
-
// Execute script in page context
|
|
160
|
-
const func = new Function(scriptCode);
|
|
161
|
-
func();
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.error('Script execution error:', error);
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
args: [request.script]
|
|
167
|
-
}).then(() => {
|
|
168
|
-
resolve({ success: true });
|
|
169
|
-
}).catch((error) => {
|
|
170
|
-
console.error('Chrome scripting injection failed:', error);
|
|
171
|
-
resolve({ success: false, error: error.message });
|
|
172
|
-
});
|
|
173
|
-
} else {
|
|
174
|
-
resolve({ success: false, error: 'No tab ID available' });
|
|
175
|
-
}
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
if (request.action == 'CONTROLLER') {
|
|
179
|
-
const actionType = request.actionType || "MAIN";
|
|
180
|
-
getChromeId().subscribe((id) => {
|
|
181
|
-
console.log(id);
|
|
182
|
-
CommonFunc.load().then((commonCode)=> {
|
|
183
|
-
LoadScriptController.loadScriptByDomain(request.domain, actionType).then((code) => {
|
|
184
|
-
let script = `
|
|
185
|
-
window.vetgo = {...(window.vetgo || {} ) ,chromeId:"${id}"};
|
|
186
|
-
${commonCode}
|
|
187
|
-
${code}
|
|
188
|
-
`;
|
|
189
|
-
resolve({ script });
|
|
190
|
-
});
|
|
191
|
-
})
|
|
192
|
-
})
|
|
193
|
-
} else {
|
|
194
|
-
reject('//request is empty.');
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
handler.then(message => respond(message)).catch(error => respond(error));
|
|
198
|
-
return true;
|
|
199
|
-
|
|
200
|
-
});
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { ScriptInjector } from './script-injector';
|
|
2
|
-
import { isAIChatDomain } from './utils/ai-domains';
|
|
3
|
-
import { VG_CODER_INJECTOR_SCRIPT } from './utils/injector-script';
|
|
4
|
-
|
|
5
|
-
const addScript = async (script: string, actionType: string) => {
|
|
6
|
-
try {
|
|
7
|
-
const success = await ScriptInjector.injectScript(script, actionType);
|
|
8
|
-
if (!success) {
|
|
9
|
-
console.error('All script injection methods failed for:', actionType);
|
|
10
|
-
}
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.error('Script injection error:', error);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
// Wait for DOM to be ready before executing
|
|
16
|
-
const waitForDOM = (): Promise<void> => {
|
|
17
|
-
return new Promise((resolve) => {
|
|
18
|
-
if (document.readyState === 'loading') {
|
|
19
|
-
document.addEventListener('DOMContentLoaded', () => resolve(), { once: true });
|
|
20
|
-
} else {
|
|
21
|
-
resolve();
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Multi-layer detection to check if current page is loaded inside VG Coder's iframe
|
|
28
|
-
* Returns true if this is a nested context (should skip injection)
|
|
29
|
-
*/
|
|
30
|
-
const detectVGCoderContext = async (): Promise<boolean> => {
|
|
31
|
-
// Layer 1: URL parameter check (fastest)
|
|
32
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
33
|
-
if (urlParams.has('vg_coder_context')) {
|
|
34
|
-
console.log('⚡ VG Coder context detected: URL parameter');
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Layer 2: Referrer check (backup)
|
|
39
|
-
const referrer = document.referrer;
|
|
40
|
-
if (referrer && (referrer.includes(':6868') || referrer.includes('vg-coder'))) {
|
|
41
|
-
console.log('⚡ VG Coder context detected: Referrer contains :6868');
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Layer 3: PostMessage ping (most reliable for iframe detection)
|
|
46
|
-
if (window.self !== window.top) {
|
|
47
|
-
try {
|
|
48
|
-
const isVGCoder = await new Promise<boolean>((resolve) => {
|
|
49
|
-
const timeout = setTimeout(() => resolve(false), 200);
|
|
50
|
-
|
|
51
|
-
const handler = (event: MessageEvent) => {
|
|
52
|
-
if (event.data?.type === 'VG_CODER_PARENT') {
|
|
53
|
-
clearTimeout(timeout);
|
|
54
|
-
window.removeEventListener('message', handler);
|
|
55
|
-
resolve(true);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
window.addEventListener('message', handler);
|
|
60
|
-
window.parent.postMessage({ type: 'VG_CODER_PING' }, '*');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if (isVGCoder) {
|
|
64
|
-
console.log('⚡ VG Coder context detected: PostMessage confirmation');
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
} catch (e) {
|
|
68
|
-
console.log('PostMessage detection failed (expected for cross-origin):', e);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
console.log('✅ Normal context - not inside VG Coder iframe');
|
|
73
|
-
return false;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const initializeController = async () => {
|
|
77
|
-
try {
|
|
78
|
-
// Check if we're in VG Coder's iframe context
|
|
79
|
-
const isVGCoderNested = await detectVGCoderContext();
|
|
80
|
-
|
|
81
|
-
if (isVGCoderNested) {
|
|
82
|
-
console.log('🚫 VG Coder nested iframe context detected - skipping all script injections');
|
|
83
|
-
sessionStorage.setItem('VG_CODER_NESTED', 'true');
|
|
84
|
-
return; // Early exit - don't inject any scripts
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Ensure DOM is ready
|
|
88
|
-
await waitForDOM();
|
|
89
|
-
|
|
90
|
-
const currentHostname = window.location.hostname.replace(/(https?:\/\/)?(www.)?/i, '');
|
|
91
|
-
|
|
92
|
-
// Check if this is an AI chat domain - use bundled injector
|
|
93
|
-
if (isAIChatDomain(currentHostname)) {
|
|
94
|
-
console.log('🤖 AI chat domain detected:', currentHostname);
|
|
95
|
-
console.log('📦 Using bundled VG Coder injector (no Firebase needed)');
|
|
96
|
-
|
|
97
|
-
// Execute bundled injector script
|
|
98
|
-
await addScript(VG_CODER_INJECTOR_SCRIPT, 'VG_CODER_INJECTOR');
|
|
99
|
-
return; // Done - no need for Firebase script
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// For non-AI domains, continue with Firebase script loading
|
|
103
|
-
const actionType = new URL(window.location.href).searchParams.get("actionType") || "MAIN";
|
|
104
|
-
const cache = sessionStorage.getItem(actionType);
|
|
105
|
-
|
|
106
|
-
if (cache) {
|
|
107
|
-
await addScript(cache, actionType);
|
|
108
|
-
} else {
|
|
109
|
-
chrome.runtime.sendMessage({
|
|
110
|
-
action: "CONTROLLER",
|
|
111
|
-
domain: currentHostname,
|
|
112
|
-
actionType: actionType
|
|
113
|
-
}, async (response) => {
|
|
114
|
-
if (chrome.runtime.lastError) {
|
|
115
|
-
console.error('Runtime error:', chrome.runtime.lastError);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (response && response.script) {
|
|
119
|
-
const fullScript = `var chromeId = "${chrome.runtime.id}"; ${response.script}`;
|
|
120
|
-
await addScript(fullScript, actionType);
|
|
121
|
-
sessionStorage.setItem(actionType, fullScript);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
} catch (err) {
|
|
126
|
-
console.error('Controller initialization error:', err);
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
// Initialize controller
|
|
131
|
-
initializeController();
|
|
132
|
-
const setupRemoveExtensionListener = async () => {
|
|
133
|
-
try {
|
|
134
|
-
// Wait for DOM and body to be ready
|
|
135
|
-
await waitForDOM();
|
|
136
|
-
|
|
137
|
-
// Wait for body element
|
|
138
|
-
const waitForBody = (): Promise<HTMLBodyElement> => {
|
|
139
|
-
return new Promise((resolve) => {
|
|
140
|
-
const checkBody = () => {
|
|
141
|
-
const body = document.querySelector('body');
|
|
142
|
-
if (body) {
|
|
143
|
-
resolve(body as HTMLBodyElement);
|
|
144
|
-
} else {
|
|
145
|
-
setTimeout(checkBody, 100);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
checkBody();
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const body = await waitForBody();
|
|
153
|
-
|
|
154
|
-
// cach dung: document.querySelector('body').dispatchEvent(new CustomEvent('REMOVE_EXTENSION', { detail: { key: 'value' } }));
|
|
155
|
-
body.addEventListener('REMOVE_EXTENSION', function(event: any) {
|
|
156
|
-
console.log(event.detail); // { key: 'value' }
|
|
157
|
-
chrome.runtime.sendMessage({action: "REMOVE_EXTENSION", data: event.detail}, (response) => {
|
|
158
|
-
if (chrome.runtime.lastError) {
|
|
159
|
-
console.error('Runtime error:', chrome.runtime.lastError);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
console.log('tu huy thanh cong', response);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
} catch (err) {
|
|
166
|
-
console.error('Setup remove extension listener error:', err);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// Setup remove extension listener
|
|
171
|
-
setupRemoveExtensionListener();
|
|
172
|
-
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import firebase from 'firebase/compat/app';
|
|
2
|
-
import 'firebase/compat/firestore';
|
|
3
|
-
import "firebase/compat/database";
|
|
4
|
-
import { EnvironmentStorageService } from '../utils/environment-storage.service';
|
|
5
|
-
|
|
6
|
-
// Không export trực tiếp biến đã khởi tạo nữa vì cần chờ async config
|
|
7
|
-
// export const FirebaseDatabase = firebase.database();
|
|
8
|
-
|
|
9
|
-
let initializedApp: firebase.app.App = null;
|
|
10
|
-
|
|
11
|
-
export const getFirebaseDatabase = async () => {
|
|
12
|
-
if (!initializedApp) {
|
|
13
|
-
// Lấy config từ storage hoặc mặc định
|
|
14
|
-
const config = await EnvironmentStorageService.getFirebaseConfig();
|
|
15
|
-
|
|
16
|
-
// Kiểm tra xem đã có app nào tên mặc định chưa để tránh lỗi duplicate app
|
|
17
|
-
if (firebase.apps.length === 0) {
|
|
18
|
-
initializedApp = firebase.initializeApp(config);
|
|
19
|
-
} else {
|
|
20
|
-
// Nếu đã có rồi (do reload extension context) thì dùng lại,
|
|
21
|
-
// nhưng nếu config thay đổi thì cần logic phức tạp hơn (xóa app cũ).
|
|
22
|
-
// Ở đây giả định đơn giản là dùng app hiện tại hoặc tái khởi tạo nếu cần.
|
|
23
|
-
// Với extension service worker, biến toàn cục có thể bị reset.
|
|
24
|
-
|
|
25
|
-
// Để an toàn, ta delete app cũ và init lại với config mới nhất
|
|
26
|
-
await firebase.app().delete().catch(() => { });
|
|
27
|
-
initializedApp = firebase.initializeApp(config);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return initializedApp.database();
|
|
31
|
-
};
|