النصوص البرمجية للمحتوى هي ملفات يتم تشغيلها في سياق صفحات الويب. استخدام المستند القياسي نموذج الكائن (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);
مع هذا التغيير، يظهر كلا التنبيهين في تسلسل عند النقر على الزر.
إدخال النصوص البرمجية
يمكن الإعلان بشكل ثابت عن النصوص البرمجية للمحتوى و أو بشكل ديناميكي أو يتم إدخالها آليًا.
الإدخال باستخدام تعريفات ثابتة
استخدام تعريفات النصوص البرمجية للمحتوى الثابت في ملف JSON.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 |
مصفوفة السلاسل | يجب ملء هذا الحقل. تحدِّد هذه السياسة الصفحات التي سيتم إدخال النص البرمجي للمحتوى فيها. ويمكنك الاطّلاع على أنماط المطابقة للحصول على تفاصيل حول بنية هذه السلاسل ومطابقة الأنماط والكرات الأرضية للحصول على معلومات حول كيفية استبعاد عناوين URL. |
css |
مصفوفة السلاسل | اختياري. قائمة ملفات CSS المراد إدخالها في الصفحات المطابقة وهي يتم إدخالها بالترتيب الذي تظهر به في هذا الصفيف، قبل إنشاء أو عرض أي كائن DOM الخاصة بالصفحة. |
js |
|
اختياري. قائمة ملفات JavaScript المراد إدخالها في الصفحات المطابقة Files من Google بالترتيب الذي تظهر به في هذه الصفيفة. يجب أن تحتوي كل سلسلة في هذه القائمة على مسار نسبي لمورد في الدليل الجذر للإضافة. الشرطات المائلة البادئة (`/`) هي التي يتم اقتصاصها تلقائيًا. |
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. تسمح واجهة برمجة تطبيقات النصوص البرمجية أيضًا لمطوّري الإضافات
إلى:
- تسجيل النصوص البرمجية للمحتوى
- الحصول على قائمة بنصوص المحتوى المسجَّلة
- تعديل قائمة النصوص البرمجية للمحتوى المسجّل
- إزالة النصوص البرمجية للمحتوى المسجّل
على غرار التعريفات الثابتة، يمكن أن تتضمّن التعريفات الديناميكية ملفات 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"
بشكل مؤقت
فيما يلي إصدارات مختلفة من إضافة نشطة مستندة إلى علامة التبويب.
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 التي تتطابق مع هذا العنوان
glob. مخصصة لمحاكاة @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 بنية مختلفة وأكثر مرونة من الأنماط المطابقة. الكرة الأرضية المقبولة
السلاسل هي عناوين 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"]
}
],
...
}
service-worker.js
chrome.scripting.registerContentScripts([{
id: "test",
matches : [ "https://*.nytimes.com/*" ],
allFrames : true,
js : [ "contentScript.js" ],
}]);
الاسم | النوع | الوصف |
---|---|---|
all_frames |
منطقي | اختياري. ويتم ضبط هذه القيمة تلقائيًا على false ، ما يعني أنّ الإطار العلوي فقط هو
متطابقة.إذا تم تحديد true ، فسيتم إدخال جميع الإطارات، حتى إذا كانت
الإطار ليس الإطار العلوي في علامة التبويب. يتم فحص كل إطار بشكل مستقل لعنوان URL
متطلبات المشروع. ولن يتم إدخاله في إطارات فرعية إذا لم يتم استيفاء متطلبات عناوين URL. |
إدخال الإطارات ذات الصلة
قد تحتاج الإضافات إلى تشغيل نصوص برمجية في إطارات مرتبطة بمطابقة ضمن الإطار، ولكنها لا تتطابق نفسها. سيناريو شائع عندما يكون هذا هو الحال للإطارات التي تحتوي على عناوين 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 للإطار نفسه. لاحظ أن هذا قد يختلف أيضًا عن
مصدر الإطار المستهدَف (مثل data:
عنوان URL له مصدر فارغ).
بادئ الإطار هو الإطار الذي أنشأ الهدف أو تجاوزه الإطار. وفي حين أن هذا هو عادةً الأصل المباشر أو الافتتاحية، إلا أنه قد لا يكون (كما في حالة إطار يتنقل في إطار iframe داخل إطار iframe).
ولأنّ هذا يقارن أصل إطار أداة البدء، سيتم استخدام إطار المُنشئ
على أي مسار من ذلك المصدر. وللتوضيح، يلجأ Chrome
يجب استخدام أي نصوص برمجية للمحتوى محدّدة في "match_origin_as_fallback"
.
ويتم تعيينها على true
لتحديد مسار *
أيضًا.
عند تحديد كل من "match_origin_as_fallback"
و"match_about_blank"
،
تكون الأولوية لتطبيق ""match_origin_as_fallback"
".
التواصل مع صفحة التضمين
على الرغم من عزل بيئات تنفيذ النصوص البرمجية للمحتوى والصفحات التي تستضيفها يتشاركان الوصول إلى DOM للصفحة. إذا كانت الصفحة تريد الاتصال النص البرمجي للمحتوى أو من خلال الإضافة من خلال النص البرمجي للمحتوى، يجب تنفيذ ذلك من خلال نموذج العناصر في المستند المشترك.
يمكن تقديم مثال باستخدام 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/*" ]
}
],
...
}
الحفاظ على أمانكِ
يمكن للعوالم المعزولة توفير طبقة حماية، إلّا أنّ استخدام النصوص البرمجية للمحتوى قد ينشأ
الثغرات الأمنية في الإضافة وصفحة الويب. إذا تلقّى نص المحتوى محتوًى من
لموقع إلكتروني منفصل، مثل طلب 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);