النصوص البرمجية للمحتوى

النصوص البرمجية للمحتوى هي ملفات يتم تشغيلها في سياق صفحات الويب. استخدام المستند القياسي نموذج الكائن (DOM): القدرة على قراءة تفاصيل صفحات الويب التي يزورها المتصفّح تغييرات عليها، وتمرير المعلومات إلى الإضافة الرئيسية.

فهم إمكانات النصوص البرمجية للمحتوى

يمكن للنصوص البرمجية للمحتوى الوصول مباشرةً إلى واجهات برمجة تطبيقات الإضافات التالية:

لا يمكن للنصوص البرمجية للمحتوى الوصول إلى واجهات برمجة التطبيقات الأخرى مباشرةً. ولكن يمكنهم الوصول إليها بشكل غير مباشر عن طريق تبادل الرسائل مع أجزاء أخرى من إضافتك.

يمكنك أيضًا الوصول إلى الملفات الأخرى في إضافتك من نص برمجي للمحتوى، وذلك باستخدام واجهات برمجة تطبيقات مثل 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 فقط من أجل تجنب هجمات &quot;man-in-the-middle&quot;.

لذا، احرص على إجراء الفلترة بحثًا عن صفحات الويب الضارّة. على سبيل المثال، الأنماط التالية خطيرة، غير مسموح به في الإصدار 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);