Skip to content

Commit ca58d80

Browse files
authored
Merge pull request #38 from Aiden-FE/master
#31 支持通过关闭配置项来劫持页面内的 iframe 元素
2 parents 48f4ff9 + a29151d commit ca58d80

File tree

2 files changed

+151
-70
lines changed

2 files changed

+151
-70
lines changed

content.js

Lines changed: 135 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,95 +2,162 @@
22
// 设置iframeVisible默认值,刷新后重置storage
33
chrome.storage.local.set({iframeVisible: true});
44

5-
function injectedScript (path) {
5+
async function injectedScript (path, root = document.documentElement) {
6+
// 获取顶层插入开关设置
7+
const result = await chrome.storage.local.get(['ajaxToolsTopLevelOnly']);
8+
const { ajaxToolsTopLevelOnly = true } = result;
69
// 只在最顶层嵌入 https://github.com/PengChen96/ajax-tools/issues/18
7-
if (window.self === window.top) {
10+
if (window.self === window.top || !ajaxToolsTopLevelOnly) {
811
const scriptNode = document.createElement('script');
912
scriptNode.src= chrome.runtime.getURL(path);
10-
document.documentElement.appendChild(scriptNode);
13+
root.appendChild(scriptNode);
1114
return scriptNode;
1215
}
1316
}
14-
function injectedCss(path) {
15-
if (window.self === window.top) {
17+
async function injectedCss(path, root = document.documentElement) {
18+
// 获取顶层插入开关设置
19+
const result = await chrome.storage.local.get(['ajaxToolsTopLevelOnly']);
20+
const { ajaxToolsTopLevelOnly = true } = result;
21+
// 只在最顶层嵌入 https://github.com/PengChen96/ajax-tools/issues/18
22+
if (window.self === window.top || !ajaxToolsTopLevelOnly) {
1623
const linkElement = document.createElement('link');
1724
linkElement.rel = 'stylesheet';
1825
linkElement.href = chrome.runtime.getURL(path);
19-
document.documentElement.appendChild(linkElement);
26+
root.appendChild(linkElement);
2027
return linkElement;
2128
}
2229
}
23-
function injectedStyle(styleContent) {
24-
if (window.self === window.top) {
30+
async function injectedStyle(styleContent, root = document.documentElement) {
31+
// 获取顶层插入开关设置
32+
const result = await chrome.storage.local.get(['ajaxToolsTopLevelOnly']);
33+
const { ajaxToolsTopLevelOnly = true } = result;
34+
// 只在最顶层嵌入 https://github.com/PengChen96/ajax-tools/issues/18
35+
if (window.self === window.top || !ajaxToolsTopLevelOnly) {
2536
const styleElement = document.createElement('style');
2637
styleElement.textContent = styleContent;
27-
document.documentElement.appendChild(styleElement);
38+
root.appendChild(styleElement);
2839
return styleElement;
2940
}
3041
}
31-
injectedStyle(`
32-
.ajax-interceptor-container {
33-
display: flex;
34-
flex-direction: column;
35-
height: 100% !important;
36-
width: 580px !important;
37-
min-width: 1px !important;
38-
position: fixed !important;
39-
inset: 0px 0px auto auto !important;
40-
z-index: 2147483647 !important;
41-
transform: translateX(0px) !important;
42-
transition: all 0.4s ease 0s !important;
43-
box-shadow: rgba(0, 0, 0, 0.12) 0px 0px 15px 2px !important;
44-
background: #fff;
45-
overflow: hidden;
46-
}
47-
.ajax-interceptor-action-bar {
48-
height: 40px;
49-
min-height: 40px;
50-
padding: 0 12px 0 8px;
51-
display: flex;
52-
justify-content: space-between;
53-
align-items: center;
54-
}
55-
.ajax-interceptor-iframe {
56-
border: none;
57-
height: calc(100% - 40px);
58-
width: 100%;
59-
border-top: 1px solid #d1d3d8;
60-
}
61-
.ajax-interceptor-icon {
62-
cursor: pointer;
63-
position: relative;
64-
}
65-
.ajax-interceptor-new::after {
66-
content: '';
67-
width: 6px;
68-
height: 6px;
69-
border-radius: 50%;
70-
background: #ff0000;
71-
position: absolute;
72-
right: -2px;
73-
top: -2px;
74-
}
75-
.ajax-interceptor-mr-8 {
76-
margin-right: 8px;
42+
43+
async function injectContent() {
44+
injectedStyle(`
45+
.ajax-interceptor-container {
46+
display: flex;
47+
flex-direction: column;
48+
height: 100% !important;
49+
width: 580px !important;
50+
min-width: 1px !important;
51+
position: fixed !important;
52+
inset: 0px 0px auto auto !important;
53+
z-index: 2147483647 !important;
54+
transform: translateX(0px) !important;
55+
transition: all 0.4s ease 0s !important;
56+
box-shadow: rgba(0, 0, 0, 0.12) 0px 0px 15px 2px !important;
57+
background: #fff;
58+
overflow: hidden;
59+
}
60+
.ajax-interceptor-action-bar {
61+
height: 40px;
62+
min-height: 40px;
63+
padding: 0 12px 0 8px;
64+
display: flex;
65+
justify-content: space-between;
66+
align-items: center;
67+
}
68+
.ajax-interceptor-iframe {
69+
border: none;
70+
height: calc(100% - 40px);
71+
width: 100%;
72+
border-top: 1px solid #d1d3d8;
73+
}
74+
.ajax-interceptor-icon {
75+
cursor: pointer;
76+
position: relative;
77+
}
78+
.ajax-interceptor-new::after {
79+
content: '';
80+
width: 6px;
81+
height: 6px;
82+
border-radius: 50%;
83+
background: #ff0000;
84+
position: absolute;
85+
right: -2px;
86+
top: -2px;
87+
}
88+
.ajax-interceptor-mr-8 {
89+
margin-right: 8px;
90+
}
91+
`);
92+
injectedCss('icons/iconfont/iconfont.css');
93+
injectedScript('html/iframePage/mock.js');
94+
const pageScripts = await injectedScript('pageScripts/index.js');
95+
if (pageScripts) {
96+
pageScripts.addEventListener('load', () => {
97+
chrome.storage.local.get(['iframeVisible', 'ajaxToolsSwitchOn', 'ajaxToolsSwitchOnNot200', 'ajaxDataList', 'ajaxToolsSkin'], (result) => {
98+
// console.log('【ajaxTools content.js】【storage】', result);
99+
const {ajaxToolsSwitchOn = true, ajaxToolsSwitchOnNot200 = true, ajaxDataList = []} = result;
100+
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxDataList', value: ajaxDataList});
101+
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxToolsSwitchOn', value: ajaxToolsSwitchOn});
102+
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxToolsSwitchOnNot200', value: ajaxToolsSwitchOnNot200});
103+
});
104+
});
77105
}
78-
`);
79-
injectedCss('icons/iconfont/iconfont.css');
80-
injectedScript('html/iframePage/mock.js');
81-
const pageScripts = injectedScript('pageScripts/index.js');
82-
if (pageScripts) {
83-
pageScripts.addEventListener('load', () => {
84-
chrome.storage.local.get(['iframeVisible', 'ajaxToolsSwitchOn', 'ajaxToolsSwitchOnNot200', 'ajaxDataList', 'ajaxToolsSkin'], (result) => {
85-
// console.log('【ajaxTools content.js】【storage】', result);
86-
const {ajaxToolsSwitchOn = true, ajaxToolsSwitchOnNot200 = true, ajaxDataList = []} = result;
87-
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxDataList', value: ajaxDataList});
88-
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxToolsSwitchOn', value: ajaxToolsSwitchOn});
89-
postMessage({type: 'ajaxTools', to: 'pageScript', key: 'ajaxToolsSwitchOnNot200', value: ajaxToolsSwitchOnNot200});
106+
}
107+
injectContent();
108+
109+
async function callbackIframeLoad(iframe) {
110+
try {
111+
await injectedScript('html/iframePage/mock.js', iframe.contentDocument.documentElement);
112+
const pageScripts = await injectedScript('pageScripts/index.js', iframe.contentDocument.documentElement);
113+
if (pageScripts) {
114+
pageScripts.addEventListener('load', () => {
115+
chrome.storage.local.get(['ajaxToolsSwitchOn', 'ajaxToolsSwitchOnNot200', 'ajaxDataList'], (result) => {
116+
const {ajaxToolsSwitchOn = true, ajaxToolsSwitchOnNot200 = true, ajaxDataList = []} = result;
117+
iframe.contentWindow.postMessage({
118+
type: 'ajaxTools',
119+
to: 'pageScript',
120+
key: 'ajaxDataList',
121+
value: ajaxDataList
122+
}, '*');
123+
iframe.contentWindow.postMessage({
124+
type: 'ajaxTools',
125+
to: 'pageScript',
126+
key: 'ajaxToolsSwitchOn',
127+
value: ajaxToolsSwitchOn
128+
}, '*');
129+
iframe.contentWindow.postMessage({
130+
type: 'ajaxTools',
131+
to: 'pageScript',
132+
key: 'ajaxToolsSwitchOnNot200',
133+
value: ajaxToolsSwitchOnNot200
134+
}, '*');
135+
});
136+
});
137+
}
138+
} catch (err) {
139+
console.error('Failed to inject scripts into iframe:', err);
140+
}
141+
}
142+
143+
const observer = new MutationObserver((mutations) => {
144+
mutations.forEach((mutation) => {
145+
mutation.addedNodes.forEach((node) => {
146+
if (node.nodeName === 'IFRAME') {
147+
const iframe = node;
148+
if (iframe.complete || (iframe.contentDocument && iframe.contentDocument.readyState === 'complete')) {
149+
callbackIframeLoad(iframe);
150+
} else {
151+
iframe.addEventListener('load', () => {
152+
callbackIframeLoad(iframe);
153+
});
154+
}
155+
}
90156
});
91157
});
92-
}
158+
});
93159

160+
observer.observe(document, { childList: true, subtree: true });
94161

95162
function closeButton (container) {
96163
const closeIcon = document.createElement('i');

html/iframePage/main/App.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,19 @@ function App() {
3232
const [ajaxToolsSkin, setAjaxToolsSkin] = useState('light');
3333
const [ajaxToolsSwitchOn, setAjaxToolsSwitchOn] = useState(true); // 默认开启
3434
const [ajaxToolsSwitchOnNot200, setAjaxToolsSwitchOnNot200] = useState(true); // 默认开启
35+
const [ajaxToolsTopLevelOnly, setAjaxToolsTopLevelOnly] = useState(true); // 默认开启
3536
const [ajaxDataList, setAjaxDataList] = useState(defaultAjaxDataList);
3637

3738
useEffect(() => {
3839
if (chrome.storage) {
39-
chrome.storage.local.get(['ajaxDataList', 'ajaxToolsSwitchOn', 'ajaxToolsSwitchOnNot200', 'ajaxToolsSkin'], (result) => {
40-
const { ajaxDataList = [], ajaxToolsSwitchOn = true, ajaxToolsSwitchOnNot200 = true, ajaxToolsSkin = 'light' } = result;
40+
chrome.storage.local.get(['ajaxDataList', 'ajaxToolsSwitchOn', 'ajaxToolsSwitchOnNot200', 'ajaxToolsSkin', 'ajaxToolsTopLevelOnly'], (result) => {
41+
const { ajaxDataList = [], ajaxToolsSwitchOn = true, ajaxToolsSwitchOnNot200 = true, ajaxToolsSkin = 'light', ajaxToolsTopLevelOnly = true } = result;
4142
if (ajaxDataList.length > 0) {
4243
setAjaxDataList(ajaxDataList);
4344
}
4445
setAjaxToolsSwitchOn(ajaxToolsSwitchOn);
4546
setAjaxToolsSwitchOnNot200(ajaxToolsSwitchOnNot200);
47+
setAjaxToolsTopLevelOnly(ajaxToolsTopLevelOnly);
4648
setAjaxToolsSkin(ajaxToolsSkin);
4749
});
4850
}
@@ -274,6 +276,18 @@ function App() {
274276
</Dropdown.Button>
275277
</Space>
276278
<div>
279+
<Checkbox
280+
defaultChecked
281+
checked={ajaxToolsTopLevelOnly}
282+
onChange={(e) => {
283+
setAjaxToolsTopLevelOnly(e.target.checked);
284+
chrome.storage.local.set({ ajaxToolsTopLevelOnly: e.target.checked });
285+
}}
286+
>
287+
<span title="Inject Ajax Tools plugin only at the top level. Disable this option when you need to hijack requests within an iframe.">
288+
Top Level Only
289+
</span>
290+
</Checkbox>
277291
<Checkbox
278292
defaultChecked
279293
checked={ajaxToolsSwitchOnNot200}

0 commit comments

Comments
 (0)