Các kịch bản nội dung được thực thi trong môi trường "thế giới biệt lập" . Bạn phải tiêm state()
phương pháp của bạn vào chính trang đó.
Khi bạn muốn sử dụng một trong các chrome.*
API trong tập lệnh, bạn phải triển khai một trình xử lý sự kiện đặc biệt, như được mô tả trong câu trả lời này: Tiện ích mở rộng của Chrome - lấy thông điệp gốc của Gmail .
Mặt khác, nếu bạn không phải sử dụng chrome.*
API, tôi thực sự khuyên bạn nên tiêm tất cả mã JS của mình vào trang thông qua việc thêm <script>
thẻ:
Mục lục
- Phương pháp 1: Tiêm một tệp khác
- Phương pháp 2: Tiêm mã nhúng
- Phương pháp 2b: Sử dụng hàm
- Phương pháp 3: Sử dụng một sự kiện nội tuyến
- Giá trị động trong mã được tiêm
Phương pháp 1: Tiêm một tệp khác
Đây là phương pháp dễ nhất / tốt nhất khi bạn có nhiều mã. Bao gồm mã JS thực tế của bạn trong một tệp trong phần mở rộng của bạn, giả sử script.js
. Sau đó, hãy để tập lệnh nội dung của bạn như sau (giải thích tại đây: Ứng dụng Google Chome Lối tắt Short Javascript tùy chỉnh ):
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.runtime.getURL('script.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
Lưu ý: Nếu bạn sử dụng phương pháp này, script.js
tệp được chèn phải được thêm vào "web_accessible_resources"
phần ( ví dụ ). Nếu bạn không làm như vậy, Chrome sẽ từ chối tải tập lệnh của bạn và hiển thị lỗi sau trong bảng điều khiển:
Từ chối tải phần mở rộng chrome: // [EXTENSIONID] /script.js. Tài nguyên phải được liệt kê trong khóa tệp kê khai web_accessible_resource để được tải bởi các trang bên ngoài tiện ích mở rộng.
Phương pháp 2: Tiêm mã nhúng
Phương pháp này hữu ích khi bạn muốn chạy nhanh một đoạn mã nhỏ. (Xem thêm: Làm cách nào để tắt các phím nóng facebook với tiện ích mở rộng Chrome? ).
var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
Lưu ý: nghĩa đen mẫu chỉ được hỗ trợ trong Chrome 41 trở lên. Nếu bạn muốn tiện ích mở rộng hoạt động trong Chrome 40-, hãy sử dụng:
var actualCode = ['/* Code here. Example: */' + 'alert(0);',
'// Beware! This array have to be joined',
'// using a newline. Otherwise, missing semicolons',
'// or single-line comments (//) will mess up your',
'// code ----->'].join('\n');
Phương pháp 2b: Sử dụng hàm
Đối với một đoạn mã lớn, trích dẫn chuỗi là không khả thi. Thay vì sử dụng một mảng, một hàm có thể được sử dụng và xâu chuỗi:
var actualCode = '(' + function() {
// All code is executed in a local scope.
// For example, the following does NOT overwrite the global `alert` method
var alert = null;
// To overwrite a global variable, prefix `window`:
window.alert = null;
} + ')();';
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
Phương thức này hoạt động, bởi vì +
toán tử trên chuỗi và hàm chuyển đổi tất cả các đối tượng thành chuỗi. Nếu bạn có ý định sử dụng mã nhiều lần, bạn nên tạo một hàm để tránh lặp lại mã. Một triển khai có thể trông giống như:
function injectScript(func) {
var actualCode = '(' + func + ')();'
...
}
injectScript(function() {
alert("Injected script");
});
Lưu ý: Vì chức năng được tuần tự hóa, phạm vi ban đầu và tất cả các thuộc tính ràng buộc sẽ bị mất!
var scriptToInject = function() {
console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output: "undefined"
Phương pháp 3: Sử dụng một sự kiện nội tuyến
Đôi khi, bạn muốn chạy một số mã ngay lập tức, ví dụ để chạy một số mã trước khi <head>
phần tử được tạo. Điều này có thể được thực hiện bằng cách chèn một <script>
thẻ với textContent
(xem phương pháp 2 / 2b).
Một cách khác, nhưng không được khuyến nghị là sử dụng các sự kiện nội tuyến. Không khuyến khích vì nếu trang xác định chính sách Bảo mật Nội dung cấm các tập lệnh nội tuyến, thì trình lắng nghe sự kiện nội tuyến sẽ bị chặn. Các tập lệnh nội tuyến được chèn bởi phần mở rộng, mặt khác, vẫn chạy. Nếu bạn vẫn muốn sử dụng các sự kiện nội tuyến, đây là cách:
var actualCode = '// Some code example \n' +
'console.log(document.documentElement.outerHTML);';
document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');
Lưu ý: Phương pháp này giả định rằng không có người nghe sự kiện toàn cầu nào khác xử lý reset
sự kiện này. Nếu có, bạn cũng có thể chọn một trong những sự kiện toàn cầu khác. Chỉ cần mở bảng điều khiển JavaScript (F12), nhập document.documentElement.on
và chọn các sự kiện có sẵn.
Giá trị động trong mã được tiêm
Đôi khi, bạn cần truyền một biến tùy ý cho hàm được chèn. Ví dụ:
var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
alert(GREETING + NAME);
};
Để tiêm mã này, bạn cần truyền các biến làm đối số cho hàm ẩn danh. Hãy chắc chắn để thực hiện nó một cách chính xác! Những điều sau đây sẽ không hoạt động:
var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME + ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi, I'm ,Rob)";
// ^^^^^^^^ ^^^ No string literals!
Giải pháp là sử dụng JSON.stringify
trước khi truyền đối số. Thí dụ:
var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';
Nếu bạn có nhiều biến, đáng để sử dụng JSON.stringify
một lần, để cải thiện khả năng đọc, như sau:
...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';
player.addEventListener("onStateChange", state);