نصوص المحتوى البرمجية هي ملفات يتم تشغيلها في سياق صفحات الويب. باستخدام نموذج كائن المستند (DOM) العادي، يمكنها قراءة تفاصيل صفحات الويب التي يتصفّحها المتصفّح وإجراء تغييرات عليها وتمرير المعلومات إلى الإضافة الرئيسية.
التعرّف على إمكانات النصوص البرمجية للمحتوى
يمكن لنصوص المحتوى البرمجية الوصول إلى واجهات برمجة التطبيقات التالية للإضافات مباشرةً:
dom
i18n
storage
runtime.connect()
runtime.getManifest()
runtime.getURL()
runtime.id
runtime.onConnect
runtime.onMessage
runtime.sendMessage()
لا يمكن للنصوص البرمجية للمحتوى الوصول إلى واجهات برمجة التطبيقات الأخرى مباشرةً. ولكن يمكنهم الوصول إليها بشكل غير مباشر من خلال تبادل الرسائل مع أجزاء أخرى من الإضافة.
يمكنك أيضًا الوصول إلى ملفات أخرى في الإضافة من نص برمجي خاص بالمحتوى، وذلك باستخدام واجهات برمجة تطبيقات مثل fetch()
. لإجراء ذلك، عليك تعريفها على أنّها
موارد يمكن الوصول إليها على الويب. يُرجى العِلم أنّ هذا الإجراء يعرّض الموارد أيضًا لأي نصوص برمجية تابعة للطرف الأول أو الثالث يتم تشغيلها على الموقع الإلكتروني نفسه.
العمل في عوالم معزولة
تعمل نصوص المحتوى البرمجية في بيئة معزولة، ما يسمح لنص المحتوى البرمجي بإجراء تغييرات على بيئة JavaScript بدون حدوث تعارض مع الصفحة أو نصوص المحتوى البرمجية الخاصة بالإضافات الأخرى.
قد يتم تشغيل إضافة في صفحة ويب باستخدام رمز مشابه للمثال التالي.
webPage.html
<html>
<button id="mybutton">click me</button>
<script>
var greeting = "hello, ";
var button = document.getElementById("mybutton");
button.person_name = "Bob";
button.addEventListener(
"click", () => alert(greeting + button.person_name + "."), false);
</script>
</html>
يمكن أن تُدخل هذه الإضافة نص برمجي للمحتوى باستخدام إحدى التقنيات الموضّحة في قسم إدخال النصوص البرمجية.
content-script.js
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener(
"click", () => alert(greeting + button.person_name + "."), false);
بعد تطبيق هذا التغيير، سيظهر كلا التنبيهَين بالتسلسل عند النقر على الزر.
إدراج نصوص برمجية
يمكن تحديد نصوص البرامج الثابتة بشكل ثابت أو تحديدها بشكل ديناميكي أو إدخالها آليًا.
إدخال بيانات باستخدام تعريفات ثابتة
استخدِم بيانات وصفية ثابتة لنصوص المحتوى البرمجية في ملف manifest.json للنصوص البرمجية التي يجب تشغيلها تلقائيًا على مجموعة معروفة من الصفحات.
يتم تسجيل النصوص البرمجية التي تم تعريفها بشكل ثابت في ملف البيان ضمن المفتاح "content_scripts"
.
ويمكن أن تتضمّن ملفات JavaScript أو ملفات CSS أو كليهما. يجب أن تحدّد جميع نصوص المحتوى البرمجية التي يتم تشغيلها تلقائيًا أنماط المطابقة.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"css": ["my-styles.css"],
"js": ["content-script.js"]
}
],
...
}
الاسم | النوع | الوصف |
---|---|---|
matches |
مصفوفة سلاسل | مطلوبة. تحدّد هذه السمة الصفحات التي سيتم إدراج نص المحتوى البرمجي فيها. اطّلِع على أنماط المطابقة لمعرفة تفاصيل حول بنية هذه السلاسل، وعلى أنماط المطابقة وglob للحصول على معلومات حول كيفية استبعاد عناوين URL. |
css |
مصفوفة سلاسل | اختياري. قائمة بملفات CSS التي سيتم إدراجها في الصفحات المطابقة ويتم إدراجها بالترتيب الذي تظهر به في هذه المصفوفة، قبل إنشاء أي DOM أو عرضه للصفحة. |
js |
|
اختياري. قائمة ملفات JavaScript التي سيتم إدراجها في الصفحات المطابقة يتم إدراج الملفات بالترتيب الذي تظهر به في هذه المصفوفة. يجب أن تحتوي كل سلسلة في هذه القائمة على مسار نسبي إلى أحد الموارد في الدليل الجذري للإضافة. تتم إزالة الشرطات المائلة في البداية تلقائيًا. |
run_at |
RunAt | اختياري. تحدّد هذه السمة وقت إدخال النص البرمجي في الصفحة. القيمة التلقائية هي
document_idle . |
match_about_blank |
قيمة منطقية | اختياري. تحديد ما إذا كان يجب إدراج النص البرمجي في إطار about:blank حيث يتطابق الإطار الرئيسي أو إطار الفتح مع أحد الأنماط المحدّدة في matches القيمة التلقائية هي "خطأ". |
match_origin_as_fallback |
قيمة منطقية |
اختياري. تحديد ما إذا كان يجب إدراج النص البرمجي في إطارات تم إنشاؤها من خلال مصدر مطابق، ولكن قد لا يتطابق عنوان URL أو المصدر مباشرةً مع النمط. وتشمل هذه الإطارات مخططات مختلفة، مثل about: وdata: وblob: وfilesystem: . يُرجى الاطّلاع أيضًا على
إدخال الإعلانات في إطارات ذات صلة.
|
world |
ExecutionWorld |
اختياري. بيئة JavaScript التي سيتم تنفيذ النص البرمجي فيها القيمة التلقائية هي ISOLATED . راجِع أيضًا
العمل في عوالم معزولة.
|
إدخال إعلانات باستخدام تعريفات ديناميكية
تكون نصوص المحتوى الديناميكي البرمجية مفيدة عندما لا تكون أنماط المطابقة لنصوص المحتوى البرمجية معروفة جيدًا أو عندما لا يجب دائمًا إدخال نصوص المحتوى البرمجية على المضيفين المعروفين.
تتشابه الإعدادات الديناميكية، التي تم طرحها في الإصدار 96 من Chrome، مع الإعدادات الثابتة، ولكن يتم تسجيل عنصر النص البرمجي للمحتوى في Chrome باستخدام طرق في مساحة الاسم chrome.scripting
بدلاً من manifest.json. تتيح Scripting API أيضًا لمطوّري الإضافات تنفيذ ما يلي:
- تسجيل النصوص البرمجية للمحتوى
- الحصول على قائمة بنصوص المحتوى البرمجية المسجّلة
- عدِّل قائمة النصوص البرمجية للمحتوى المسجّلة.
- إزالة نصوص المحتوى البرمجية المسجّلة
مثل البيانات الثابتة، يمكن أن تتضمّن البيانات الديناميكية ملفات JavaScript أو ملفات CSS أو كليهما.
service-worker.js
chrome.scripting
.registerContentScripts([{
id: "session-script",
js: ["content.js"],
persistAcrossSessions: false,
matches: ["*://example.com/*"],
runAt: "document_start",
}])
.then(() => console.log("registration complete"))
.catch((err) => console.warn("unexpected error", err))
service-worker.js
chrome.scripting
.updateContentScripts([{
id: "session-script",
excludeMatches: ["*://admin.example.com/*"],
}])
.then(() => console.log("registration updated"));
service-worker.js
chrome.scripting
.getRegisteredContentScripts()
.then(scripts => console.log("registered content scripts", scripts));
service-worker.js
chrome.scripting
.unregisterContentScripts({ ids: ["session-script"] })
.then(() => console.log("un-registration complete"));
الإدخال بشكل آلي
استخدِم عملية الإدخال آليًا لبرامج النصوص الخاصة بالمحتوى التي يجب تنفيذها استجابةً للأحداث أو في مناسبات معيّنة.
لإدخال نص برمجي للمحتوى آليًا، يجب أن تملك الإضافة أذونات المضيف للصفحة التي تحاول إدخال النصوص البرمجية فيها. يمكن منح أذونات المضيف من خلال طلبها كجزء من بيان الإضافة أو بشكل مؤقت باستخدام "activeTab"
.
في ما يلي إصدارات مختلفة من إضافة تستند إلى activeTab.
manifest.json:
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
يمكن إدخال النصوص البرمجية للمحتوى كملفات.
content-script.js
document.body.style.backgroundColor = "orange";
service-worker.js:
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"]
});
});
أو يمكن إدخال نص الدالة وتنفيذه كنص برمجي للمحتوى.
service-worker.js:
function injectedFunction() {
document.body.style.backgroundColor = "orange";
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
});
});
يُرجى العِلم أنّ الدالة التي تم إدخالها هي نسخة من الدالة المشار إليها في استدعاء chrome.scripting.executeScript()
، وليست الدالة الأصلية نفسها. نتيجةً لذلك، يجب أن يكون نص الدالة
مستقلاً بذاته، لأنّ الإشارات إلى المتغيرات خارج الدالة ستؤدي إلى أن يعرض البرنامج النصي للمحتوى الخطأ ReferenceError
.
عند إدخال البيانات كدالة، يمكنك أيضًا تمرير وسيطات إلى الدالة.
service-worker.js
function injectedFunction(color) {
document.body.style.backgroundColor = color;
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
args : [ "orange" ],
});
});
استبعاد التطابقات والأنماط العامة
لتخصيص مطابقة الصفحات المحدّدة، أدرِج الحقول التالية في تسجيل تعريفي.
الاسم | النوع | الوصف |
---|---|---|
exclude_matches |
مصفوفة سلاسل | اختياري. يستبعد هذا المفتاح الصفحات التي كان سيتم إدراج نص برمجي للمحتوى فيها. لمعرفة تفاصيل حول بنية هذه السلاسل، يُرجى الاطّلاع على أنماط المطابقة. |
include_globs |
مصفوفة سلاسل | اختياري. يتم تطبيقه بعد matches لتضمين عناوين URL التي تتطابق أيضًا مع هذا النمط العام. يهدف ذلك إلى محاكاة الكلمة الرئيسية @include في Greasemonkey. |
exclude_globs |
مصفوفة من السلاسل | اختياري. يتم تطبيقها بعد matches لاستبعاد عناوين URL التي تتطابق مع هذا النمط العام. تهدف إلى محاكاة الكلمة الرئيسية @exclude في Greasemonkey. |
سيتم إدخال النص البرمجي للمحتوى في الصفحة إذا تحقّق الشرطان التاليان:
- يتطابق عنوان URL مع أي نمط
matches
وأي نمطinclude_globs
. - لا يطابق عنوان URL أيضًا نمط
exclude_matches
أوexclude_globs
. بما أنّ السمةmatches
مطلوبة، لا يمكن استخدامexclude_matches
وinclude_globs
وexclude_globs
إلا للحدّ من الصفحات التي ستتأثر.
تُدرج الإضافة التالية النص البرمجي للمحتوى في https://www.nytimes.com/health
ولكن ليس في https://www.nytimes.com/business
.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.nytimes.com/*" ],
excludeMatches : [ "*://*/*business*" ],
js : [ "contentScript.js" ],
}]);
تتّبع سمات Glob بنية مختلفة وأكثر مرونةً من أنماط المطابقة. سلاسل glob المقبولة هي عناوين URL قد تحتوي على علامات نجمية وعلامات استفهام "أحرف بدل". تتطابق علامة النجمة (*
) مع أي سلسلة بأي طول، بما في ذلك السلسلة الفارغة، بينما تتطابق علامة الاستفهام (?
) مع أي حرف مفرد.
على سبيل المثال، يتطابق النمط العام https://???.example.com/foo/\*
مع أي مما يلي:
https://www.example.com/foo/bar
https://the.example.com/foo/
ومع ذلك، لا يتطابق مع ما يلي:
https://my.example.com/foo/bar
https://example.com/foo/
https://www.example.com/foo
تحقن هذه الإضافة النص البرمجي للمحتوى في https://www.nytimes.com/arts/index.html
وhttps://www.nytimes.com/jobs/index.htm*
، ولكن ليس في https://www.nytimes.com/sports/index.html
:
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
تحقن هذه الإضافة النص البرمجي للمحتوى في https://history.nytimes.com
وhttps://.nytimes.com/history
، ولكن ليس في https://science.nytimes.com
أو https://www.nytimes.com/science
:
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
يمكن تضمين بعض هذه العناصر أو كلها أو أحدها لتحقيق النطاق الصحيح.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
وقت التنفيذ
يتحكّم الحقل run_at
في وقت إدخال ملفات JavaScript في صفحة الويب. القيمة المفضّلة والتلقائية هي "document_idle"
. راجِع نوع RunAt للاطّلاع على القيم المحتملة الأخرى.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.nytimes.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
الاسم | النوع | الوصف |
---|---|---|
document_idle |
سلسلة | الخيار المفضّل: استخدِم "document_idle" متى أمكن ذلك.يختار المتصفّح وقتًا لإدراج النصوص البرمجية بين "document_end" وبعد تفعيل الحدث window.onload مباشرةً. يعتمد وقت الإضافة الدقيق على مدى تعقيد المستند والوقت الذي يستغرقه تحميله، ويتم تحسينه لزيادة سرعة تحميل الصفحة.لا تحتاج النصوص البرمجية للمحتوى التي يتم تشغيلها في "document_idle" إلى انتظار حدث window.onload ، إذ يُضمَن تشغيلها بعد اكتمال بنية DOM. إذا كان النص البرمجي يحتاج بالتأكيد إلى التنفيذ بعد window.onload ، يمكن للإضافة التحقّق مما إذا تم تشغيل onload باستخدام السمة document.readyState . |
document_start |
سلسلة | يتم إدراج النصوص البرمجية بعد أي ملفات من css ، ولكن قبل إنشاء أي DOM آخر أو تشغيل أي نص برمجي آخر. |
document_end |
سلسلة | يتم إدخال النصوص البرمجية مباشرةً بعد اكتمال DOM، ولكن قبل تحميل الموارد الفرعية، مثل الصور والأُطر. |
تحديد اللقطات
بالنسبة إلى النصوص البرمجية الخاصة بالمحتوى التعريفية المحدّدة في ملف البيان، يتيح الحقل "all_frames"
للملحق تحديد ما إذا كان يجب إدخال ملفات JavaScript وCSS في جميع الإطارات التي تستوفي متطلبات عنوان URL المحدّد أو في الإطار العلوي فقط في علامة تبويب:
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
عند تسجيل برامج نصية للمحتوى آليًا باستخدام chrome.scripting.registerContentScripts(...)
، يمكن استخدام المَعلمة allFrames
لتحديد ما إذا كان يجب إدراج البرنامج النصي للمحتوى في جميع الإطارات التي تتطابق مع متطلبات عنوان URL المحدّدة أو في الإطار العلوي فقط في علامة تبويب. يمكن استخدام هذا الخيار مع tabId فقط، ولا يمكن استخدامه في حال تحديد frameIds أو documentIds:
service-worker.js
chrome.scripting.registerContentScripts([{
id: "test",
matches : [ "https://*.nytimes.com/*" ],
allFrames : true,
js : [ "contentScript.js" ],
}]);
إضافة إطار ذي صلة
قد تحتاج الإضافات إلى تشغيل نصوص برمجية في إطارات ذات صلة بإطار مطابق، ولكنها لا تتطابق معه. من السيناريوهات الشائعة التي يحدث فيها ذلك، الإطارات التي تتضمّن عناوين URL تم إنشاؤها بواسطة إطار مطابق، ولكن عناوين URL هذه لا تتطابق مع الأنماط المحدّدة في النص البرمجي.
ويحدث ذلك عندما يريد أحد الإضافات إدخال محتوى في إطارات تتضمّن عناوين URL تستخدم المخططات about:
وdata:
وblob:
وfilesystem:
. في هذه الحالات، لن يتطابق عنوان URL مع نمط البرنامج النصي للمحتوى (وفي حالة about:
وdata:
، لن يتضمّن عنوان URL حتى عنوان URL أو المصدر الرئيسي على الإطلاق، كما هو الحال في about:blank
أو data:text/html,<html>Hello, World!</html>
). ومع ذلك، يمكن ربط هذه الإطارات بالإطار الذي تم إنشاؤها فيه.
لإضافة محتوى إلى هذه الإطارات، يمكن للإضافات تحديد السمة "match_origin_as_fallback"
في مواصفات نص برمجي للمحتوى في ملف البيان.
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.google.com/*"],
"match_origin_as_fallback": true,
"js": ["contentScript.js"]
}
],
...
}
عند تحديد القيمة true
، سيفحص Chrome مصدر الجهة التي بدأت عملية تحميل الإطار لتحديد ما إذا كان الإطار مطابقًا، بدلاً من فحص عنوان URL الخاص بالإطار نفسه. يُرجى العِلم أنّ هذا قد يختلف أيضًا عن مصدر الإطار المستهدف (مثلاً، تحتوي عناوين URL الخاصة بـ data:
على مصدر فارغ).
مُنشئ الإطار هو الإطار الذي أنشأ الإطار المستهدف أو انتقل إليه. على الرغم من أنّ هذا العنصر يكون عادةً العنصر الرئيسي المباشر أو العنصر الذي فتح النافذة، قد لا يكون كذلك (كما هو الحال عند انتقال إطار إلى iframe داخل iframe).
بما أنّ هذا الإجراء يقارن المصدر لإطار البادئ، يمكن أن يكون إطار البادئ على أي مسار من هذا المصدر. لتوضيح هذا المعنى الضمني، يشترط Chrome أن تحدّد أي نصوص برمجية للمحتوى تم تحديدها باستخدام "match_origin_as_fallback"
القيمة true
مسارًا بقيمة *
.
عند تحديد كلّ من "match_origin_as_fallback"
و"match_about_blank"
، تكون الأولوية لـ "match_origin_as_fallback"
.
التواصل مع الصفحة المضمّنة
على الرغم من أنّ بيئات التنفيذ الخاصة بنصوص المحتوى البرمجية والصفحات التي تستضيفها معزولة عن بعضها، إلا أنّها تشترك في إمكانية الوصول إلى نموذج المستند الخاص بالصفحة. إذا أرادت الصفحة التواصل مع النص البرمجي الخاص بالمحتوى أو مع الإضافة من خلال النص البرمجي الخاص بالمحتوى، عليها إجراء ذلك من خلال نموذج المستند المشترك.
يمكن تنفيذ مثال باستخدام window.postMessage()
:
content-script.js
var port = chrome.runtime.connect();
window.addEventListener("message", (event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return;
}
if (event.data.type && (event.data.type === "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
}
}, false);
example.js
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
تنشر الصفحة غير التابعة للإضافة، example.html، الرسائل إلى نفسها. يتم اعتراض هذه الرسالة وفحصها من خلال النص البرمجي للمحتوى، ثم يتم نشرها في عملية الإضافة. بهذه الطريقة، تنشئ الصفحة قناة تواصل مع عملية الإضافة. ويمكن إجراء العكس بالطريقة نفسها.
الوصول إلى ملفات البيانات الموسّعة
للوصول إلى ملف إضافة من نص برمجي خاص بالمحتوى، يمكنك استدعاء chrome.runtime.getURL()
للحصول على عنوان URL المطلق لأصل الإضافة كما هو موضّح في المثال التالي (content.js
):
content-script.js
let image = chrome.runtime.getURL("images/my_image.png")
لاستخدام خطوط أو صور في ملف CSS، يمكنك استخدام @@extension_id
لإنشاء عنوان URL كما هو موضّح في المثال التالي (content.css
):
content.css
body {
background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');
}
@font-face {
font-family: 'Stint Ultra Expanded';
font-style: normal;
font-weight: 400;
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Stint Ultra Expanded.woff') format('woff');
}
يجب تعريف جميع مواد العرض على أنّها موارد يمكن الوصول إليها على الويب في ملف manifest.json
:
manifest.json
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
سياسة أمان المحتوى
تتضمّن النصوص البرمجية للمحتوى التي يتم تشغيلها في عوالم معزولة سياسة أمان المحتوى (CSP) التالية:
script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' chrome-extension://abcdefghijklmopqrstuvwxyz/; object-src 'self';
وكما هو الحال مع القيود المفروضة على سياقات الإضافات الأخرى، يمنع ذلك استخدام eval()
بالإضافة إلى تحميل نصوص برمجية خارجية.
بالنسبة إلى الإضافات غير المضغوطة، تتضمّن سياسة CSP أيضًا localhost:
script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:* chrome-extension://abcdefghijklmopqrstuvwxyz/; object-src 'self';
عندما يتم إدخال نص برمجي للمحتوى في العالم الرئيسي، يتم تطبيق سياسة أمان المحتوى (CSP) الخاصة بالصفحة.
الحفاظ على الأمان
على الرغم من أنّ العوالم المعزولة توفّر مستوى من الحماية، إلا أنّ استخدام النصوص البرمجية للمحتوى يمكن أن يؤدي إلى حدوث ثغرات أمنية في الإضافة وصفحة الويب. إذا تلقّى النص البرمجي للمحتوى محتوًى من موقع إلكتروني منفصل، مثلاً من خلال استدعاء fetch()
، احرص على فلترة المحتوى ضد هجمات البرمجة عبر المواقع قبل إدخاله. يجب التواصل عبر HTTPS فقط لتجنُّب هجمات "man-in-the-middle".
احرص على فلترة صفحات الويب الضارة. على سبيل المثال، الأنماط التالية خطيرة وغير مسموح بها في الإصدار 3 من ملف البيان:
content-script.js
const data = document.getElementById("json-data"); // WARNING! Might be evaluating an evil script! const parsed = eval("(" + data + ")");
content-script.js
const elmt_id = ... // WARNING! elmt_id might be '); ... evil script ... //'! window.setTimeout("animate(" + elmt_id + ")", 200);
بدلاً من ذلك، ننصحك باستخدام واجهات برمجة تطبيقات أكثر أمانًا لا تشغّل النصوص البرمجية:
content-script.js
const data = document.getElementById("json-data") // JSON.parse does not evaluate the attacker's scripts. const parsed = JSON.parse(data);
content-script.js
const elmt_id = ... // The closure form of setTimeout does not evaluate scripts. window.setTimeout(() => animate(elmt_id), 200);