vg-coder-cli 2.0.22 → 2.0.24

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.
Files changed (50) hide show
  1. package/.vg/tree-state.json +9 -0
  2. package/package.json +3 -1
  3. package/scripts/build.js +49 -6
  4. package/src/server/api-server.js +46 -0
  5. package/src/server/terminal-manager.js +10 -1
  6. package/src/server/views/css/structure.css +4 -1
  7. package/src/server/views/dashboard.css +24 -1
  8. package/src/server/views/dashboard.html +2 -0
  9. package/src/server/views/js/api.js +24 -0
  10. package/src/server/views/js/features/resize.js +57 -0
  11. package/src/server/views/js/features/structure.js +109 -16
  12. package/src/server/views/js/main.js +5 -0
  13. package/src/server/views/vg-coder/background.js +48201 -2
  14. package/src/server/views/vg-coder/controller.js +496 -1
  15. package/src/server/views/vg-coder/manifest.json +13 -5
  16. package/src/server/views/vg-coder/{options.css → sidepanel.css} +34 -32
  17. package/src/server/views/vg-coder/{options.html → sidepanel.html} +2 -2
  18. package/src/server/views/vg-coder/sidepanel.js +347 -0
  19. package/vetgo-auto/README.md +3 -0
  20. package/vetgo-auto/chrome/CSP_IMPROVEMENTS.md +147 -0
  21. package/vetgo-auto/chrome/MANIFEST_V3_MIGRATION.md +123 -0
  22. package/vetgo-auto/chrome/assets/icon128.png +0 -0
  23. package/vetgo-auto/chrome/assets/icon16.png +0 -0
  24. package/vetgo-auto/chrome/assets/icon48.png +0 -0
  25. package/vetgo-auto/chrome/environments/environment.ts +13 -0
  26. package/vetgo-auto/chrome/manifest.json +66 -0
  27. package/vetgo-auto/chrome/rules.json +23 -0
  28. package/vetgo-auto/chrome/src/background.ts +200 -0
  29. package/vetgo-auto/chrome/src/controller.ts +98 -0
  30. package/vetgo-auto/chrome/src/controllers/common.firebase.ts +31 -0
  31. package/vetgo-auto/chrome/src/controllers/firebase-crud.ts +147 -0
  32. package/vetgo-auto/chrome/src/controllers/load-common-fuc.controller.ts +24 -0
  33. package/vetgo-auto/chrome/src/controllers/load-script.controller.ts +23 -0
  34. package/vetgo-auto/chrome/src/script-injector.ts +305 -0
  35. package/vetgo-auto/chrome/src/sidepanel.css +166 -0
  36. package/vetgo-auto/chrome/src/sidepanel.html +48 -0
  37. package/vetgo-auto/chrome/src/sidepanel.ts +127 -0
  38. package/vetgo-auto/chrome/src/utils/db-utils.ts +2 -0
  39. package/vetgo-auto/chrome/src/utils/environment-storage.service.ts +85 -0
  40. package/vetgo-auto/chrome/webpack.config.js +53 -0
  41. package/vetgo-auto/chrome/webpack.config.prod.js +54 -0
  42. package/vetgo-auto/package.json +30 -0
  43. package/vetgo-auto/tsconfig.json +27 -0
  44. package/vg-coder-cli-2.0.23.tgz +0 -0
  45. package/vg-coder-cli-2.0.24.tgz +0 -0
  46. package/src/server/views/vg-coder/background.js.LICENSE.txt +0 -118
  47. package/src/server/views/vg-coder/options.js +0 -1
  48. package/vg-coder-cli-2.0.21.tgz +0 -0
  49. package/vg-coder-cli-2.0.22.tgz +0 -0
  50. package/vg-coder.zip +0 -0
@@ -0,0 +1,147 @@
1
+ # CSP Script Injection Improvements
2
+
3
+ ## Vấn đề ban đầu
4
+
5
+ Extension gặp lỗi CSP khi inject script trên các website có Content Security Policy nghiêm ngặt:
6
+
7
+ ```
8
+ Refused to load the script 'blob:...' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval'..."
9
+ ```
10
+
11
+ ## Giải pháp đã implement
12
+
13
+ ### 1. CSP Detection Logic
14
+
15
+ ```typescript
16
+ private static detectStrictCSP(): boolean {
17
+ // Check CSP meta tags
18
+ // Check known strict domains (midjourney.com, github.com, etc.)
19
+ }
20
+ ```
21
+
22
+ **Domains được detect:**
23
+ - midjourney.com ✅
24
+ - openai.com
25
+ - github.com
26
+ - google.com
27
+ - googletagmanager.com
28
+ - facebook.com
29
+ - twitter.com
30
+ - linkedin.com
31
+
32
+ ### 2. Smart Injection Order
33
+
34
+ **Cho sites có CSP nghiêm ngặt:**
35
+ 1. 🎯 **Background Injection** (chrome.scripting với world: 'MAIN')
36
+ 2. 🔧 **Eval Method** (direct execution trong content script)
37
+ 3. 💬 **PostMessage Bridge**
38
+ 4. 🎈 **Blob URL** (sẽ fail nhưng vẫn thử)
39
+ 5. 📄 **Data URL** (sẽ fail nhưng vẫn thử)
40
+
41
+ **Cho sites bình thường:**
42
+ 1. 🎈 **Blob URL** (fastest)
43
+ 2. 📄 **Data URL**
44
+ 3. 🎯 **Background Injection**
45
+ 4. 🔧 **Eval Method**
46
+ 5. 💬 **PostMessage Bridge**
47
+
48
+ ### 3. Enhanced Logging
49
+
50
+ ```
51
+ Injecting script for MAIN (Strict CSP: true)
52
+ Trying Background injection...
53
+ ✅ Script injection successful via Background for MAIN
54
+ ```
55
+
56
+ ### 4. New Eval Method
57
+
58
+ ```typescript
59
+ static injectViaEval(script: string, actionType: string): Promise<boolean> {
60
+ // Direct eval trong isolated function context
61
+ // Fallback khi tất cả methods khác fail
62
+ }
63
+ ```
64
+
65
+ ## Kết quả Test
66
+
67
+ ### Trước khi cải thiện:
68
+ ```
69
+ ❌ Blob injection failed: CSP violation
70
+ ❌ Data URL injection failed: CSP violation
71
+ ✅ Background injection successful (nhưng có nhiều errors)
72
+ ```
73
+
74
+ ### Sau khi cải thiện:
75
+ ```
76
+ ✅ CSP detected: midjourney.com (Strict CSP: true)
77
+ ✅ Background injection successful (no errors)
78
+ ✅ Clean console output
79
+ ```
80
+
81
+ ## Performance Impact
82
+
83
+ | Build Type | Controller Size | Methods Available |
84
+ |------------|----------------|-------------------|
85
+ | Development | 73.7KB | 5 injection methods |
86
+ | Production | 11.1KB | 5 injection methods |
87
+
88
+ ## Browser Compatibility
89
+
90
+ | Method | Chrome | Edge | Firefox | Safari |
91
+ |--------|--------|------|---------|--------|
92
+ | Background | ✅ | ✅ | ❌ | ❌ |
93
+ | Blob URL | ✅ | ✅ | ✅ | ✅ |
94
+ | Data URL | ✅ | ✅ | ✅ | ✅ |
95
+ | Eval | ✅ | ✅ | ✅ | ✅ |
96
+ | PostMessage | ✅ | ✅ | ✅ | ✅ |
97
+
98
+ ## Test Cases
99
+
100
+ ### ✅ Passed
101
+ - midjourney.com (strict CSP)
102
+ - googletagmanager.com (strict CSP)
103
+ - Normal websites without CSP
104
+ - Extension test page với simulated CSP
105
+
106
+ ### 🧪 Recommended Tests
107
+ - github.com
108
+ - openai.com
109
+ - facebook.com
110
+ - twitter.com
111
+ - linkedin.com
112
+
113
+ ## Usage
114
+
115
+ Extension tự động detect CSP và chọn method phù hợp:
116
+
117
+ ```javascript
118
+ // Automatic usage
119
+ await ScriptInjector.injectScript(scriptCode, 'MAIN');
120
+
121
+ // Manual method selection (nếu cần)
122
+ await ScriptInjector.injectViaBackground(scriptCode, 'MAIN');
123
+ ```
124
+
125
+ ## Monitoring
126
+
127
+ Check console logs để xem method nào được sử dụng:
128
+
129
+ ```
130
+ Injecting script for MAIN (Strict CSP: true)
131
+ Trying Background injection...
132
+ ✅ Script injection successful via Background for MAIN
133
+ ```
134
+
135
+ ## Future Improvements
136
+
137
+ 1. **Dynamic CSP Detection**: Parse actual CSP headers từ network requests
138
+ 2. **Method Caching**: Cache successful methods per domain
139
+ 3. **Performance Metrics**: Track injection success rates
140
+ 4. **Fallback Strategies**: More sophisticated fallback logic
141
+
142
+ ## Deployment Notes
143
+
144
+ - Extension size tăng minimal (11.1KB minified)
145
+ - Backward compatible với tất cả existing functionality
146
+ - No breaking changes
147
+ - Ready for Chrome Web Store deployment
@@ -0,0 +1,123 @@
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.)
@@ -0,0 +1,13 @@
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
+ };
@@ -0,0 +1,66 @@
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
+ }
@@ -0,0 +1,23 @@
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
+ ]
@@ -0,0 +1,200 @@
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
+ });
@@ -0,0 +1,98 @@
1
+ import { ScriptInjector } from './script-injector';
2
+
3
+ const addScript = async (script: string, actionType: string) => {
4
+ try {
5
+ const success = await ScriptInjector.injectScript(script, actionType);
6
+ if (!success) {
7
+ console.error('All script injection methods failed for:', actionType);
8
+ }
9
+ } catch (error) {
10
+ console.error('Script injection error:', error);
11
+ }
12
+ }
13
+ // Wait for DOM to be ready before executing
14
+ const waitForDOM = (): Promise<void> => {
15
+ return new Promise((resolve) => {
16
+ if (document.readyState === 'loading') {
17
+ document.addEventListener('DOMContentLoaded', () => resolve(), { once: true });
18
+ } else {
19
+ resolve();
20
+ }
21
+ });
22
+ };
23
+
24
+ const initializeController = async () => {
25
+ try {
26
+ // Ensure DOM is ready
27
+ await waitForDOM();
28
+
29
+ const actionType = new URL(window.location.href).searchParams.get("actionType") || "MAIN";
30
+ const cache = sessionStorage.getItem(actionType);
31
+
32
+ if (cache) {
33
+ await addScript(cache, actionType);
34
+ } else {
35
+ chrome.runtime.sendMessage({
36
+ action: "CONTROLLER",
37
+ domain: window.location.hostname.replace(/(https?:\/\/)?(www.)?/i, ''),
38
+ actionType: actionType
39
+ }, async (response) => {
40
+ if (chrome.runtime.lastError) {
41
+ console.error('Runtime error:', chrome.runtime.lastError);
42
+ return;
43
+ }
44
+ if (response && response.script) {
45
+ const fullScript = `var chromeId = "${chrome.runtime.id}"; ${response.script}`;
46
+ await addScript(fullScript, actionType);
47
+ sessionStorage.setItem(actionType, fullScript);
48
+ }
49
+ });
50
+ }
51
+ } catch (err) {
52
+ console.error('Controller initialization error:', err);
53
+ }
54
+ };
55
+
56
+ // Initialize controller
57
+ initializeController();
58
+ const setupRemoveExtensionListener = async () => {
59
+ try {
60
+ // Wait for DOM and body to be ready
61
+ await waitForDOM();
62
+
63
+ // Wait for body element
64
+ const waitForBody = (): Promise<HTMLBodyElement> => {
65
+ return new Promise((resolve) => {
66
+ const checkBody = () => {
67
+ const body = document.querySelector('body');
68
+ if (body) {
69
+ resolve(body as HTMLBodyElement);
70
+ } else {
71
+ setTimeout(checkBody, 100);
72
+ }
73
+ };
74
+ checkBody();
75
+ });
76
+ };
77
+
78
+ const body = await waitForBody();
79
+
80
+ // cach dung: document.querySelector('body').dispatchEvent(new CustomEvent('REMOVE_EXTENSION', { detail: { key: 'value' } }));
81
+ body.addEventListener('REMOVE_EXTENSION', function(event: any) {
82
+ console.log(event.detail); // { key: 'value' }
83
+ chrome.runtime.sendMessage({action: "REMOVE_EXTENSION", data: event.detail}, (response) => {
84
+ if (chrome.runtime.lastError) {
85
+ console.error('Runtime error:', chrome.runtime.lastError);
86
+ return;
87
+ }
88
+ console.log('tu huy thanh cong', response);
89
+ });
90
+ });
91
+ } catch (err) {
92
+ console.error('Setup remove extension listener error:', err);
93
+ }
94
+ };
95
+
96
+ // Setup remove extension listener
97
+ setupRemoveExtensionListener();
98
+