تمرير الرسالة

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

يعمل التواصل بين الإضافات والنصوص البرمجية للمحتوى من خلال تمرير الرسائل. أيّ منهما يمكن للطرف الآخر الاستماع إلى الرسائل المرسلة من الطرف الآخر والرد على القناة نفسها. يمكن لرسالة يحتوي على أي كائن JSON صالح (فارغ أو منطقي أو رقم أو سلسلة أو مصفوفة أو كائن). هناك مخطط واجهة برمجة تطبيقات للطلبات التي تتم لمرة واحدة وواجهة برمجة تطبيقات أكثر تعقيدًا تتيح لك فترة طويلة الاتصالات لتبادل رسائل متعددة في سياق مشترك. من الممكن أيضًا إرسال رسالة إلى إضافة أخرى إذا كنت تعرف رقم تعريفها، والذي يتم تناوله في الإضافة المتقاطعة الرسائل.

طلبات بسيطة لمرة واحدة

إذا كنت تحتاج فقط إلى إرسال رسالة واحدة إلى جزء آخر من إضافتك (ويمكنك الحصول على الرد)، فينبغي عليك استخدام طريقة runtime.sendMessage المبسّطة أو tabs.sendMessage . يتيح لك ذلك إرسال رسالة قابلة لمتسلسلة JSON لمرة واحدة من نص برمجي للمحتوى إلى إضافة، أو vice بالعكس، على التوالي . تتيح لك معلمة معاودة الاتصال الاختيارية التعامل مع الرد من الجانب، إذا كان هناك واحد.

يبدو إرسال طلب من نص برمجي للمحتوى كما يلي:

chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
  console.log(response.farewell);
});

يبدو إرسال طلب من الإضافة إلى نص برمجي للمحتوى متشابهًا إلى حد كبير، باستثناء أنك تحتاج إلى لتحديد علامة التبويب التي تريد الإرسال إليها. يوضح هذا المثال إرسال رسالة إلى النص البرمجي للمحتوى. في علامة التبويب المحددة.

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
    console.log(response.farewell);
  });
});

على الطرف المتلقي، تحتاج إلى إعداد أداة معالجة حدث runtime.onMessage لمعالجة . يتشابه ذلك من خلال نص برمجي للمحتوى أو صفحة إضافة.

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello")
      sendResponse({farewell: "goodbye"});
  }
);

في المثال أعلاه، تم استدعاء sendResponse بشكل متزامن. إذا كنت تريد استخدام sendResponse، أضِف return true; إلى معالِج أحداث "onMessage".

ملاحظة: إذا كانت هناك صفحات متعددة تستمع إلى أحداث onMessage، لن ينجح إرسال الرد سوى أول من يستدعي SendResponse() لحدث معيّن. وسيتم تجاهل جميع الردود الأخرى على هذا الحدث.
ملاحظة: لا تكون معاودة الاتصال sendResponse صالحة إلا إذا تم استخدامها بشكل متزامن، أو إذا عرض معالج الحدث true للإشارة إلى أنه سيستجيب بشكل غير متزامن. سيتم استدعاء دالة الاستدعاء الخاصة بدالة sendMessage تلقائيًا إذا لم تَرجع أي معالِجات إلى القيمة "صحيح" أو إذا كانت دالة الاستدعاء sendResponse مجمّعة.

اتصالات طويلة الأمد

قد يكون من المفيد أحيانًا إجراء محادثة تستمر لفترة أطول من طلب وردّ واحد. في هذه الحالة، يمكنك فتح قناة طويلة الأمد من النص البرمجي للمحتوى إلى صفحة إضافة ، أو والعكس صحيح، باستخدام runtime.connect أو tabs.connect، على التوالي . يمكن للقناة لها اسم اختياريًا، مما يتيح لك التمييز بين أنواع الاتصالات المختلفة.

يمكن أن تتمثل إحدى حالات الاستخدام في إضافة تعبئة نموذج تلقائية. يمكن للنص البرمجي للمحتوى فتح قناة صفحة الإضافة الخاصة بمعلومات تسجيل دخول معيّنة، وإرسال رسالة إلى الإضافة عند كل إدخال على الصفحة لطلب ملء بيانات النموذج. يسمح الاتصال المشترك بالإضافة للحفاظ على حالة المشاركة التي تربط الرسائل المتعددة الواردة من النص البرمجي للمحتوى.

عند إنشاء اتصال، يتم تخصيص كائن runtime.Port لكل طرف، ويُستخدم هذا الكائن في إرسال واستقبال الرسائل من خلال هذا الاتصال.

في ما يلي كيفية فتح قناة من نص برمجي للمحتوى وإرسال الرسائل والاستماع إليها:

var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
  if (msg.question == "Who's there?")
    port.postMessage({answer: "Madame"});
  else if (msg.question == "Madame who?")
    port.postMessage({answer: "Madame... Bovary"});
});

يبدو إرسال طلب من الإضافة إلى نص برمجي للمحتوى متشابهًا إلى حد كبير، باستثناء أنك تحتاج إلى لتحديد علامة التبويب التي تريد الاتصال بها. ما عليك سوى استبدال المكالمة للاتصال في المثال أعلاه tabs.connect.

لمعالجة الاتصالات الواردة، عليك إعداد حدث runtime.onConnect. المستمع. يتشابه ذلك من نص برمجي للمحتوى أو صفحة إضافة. عندما يحدث جزء آخر من التي تستدعي الإضافة "connect()"، ويتم تنشيط هذا الحدث إلى جانب الكائن runtime.Port الذي يمكنك التي تستخدمها لإرسال الرسائل وتلقيها عبر الاتصال. إليك ما يبدو أنّه سيتم الردّ على الاتصالات الواردة:

chrome.runtime.onConnect.addListener(function(port) {
  console.assert(port.name == "knockknock");
  port.onMessage.addListener(function(msg) {
    if (msg.joke == "Knock knock")
      port.postMessage({question: "Who's there?"});
    else if (msg.answer == "Madame")
      port.postMessage({question: "Madame who?"});
    else if (msg.answer == "Madame... Bovary")
      port.postMessage({question: "I don't get it."});
  });
});

العمر الافتراضي للمنفذ

تم تصميم المنافذ كطريقة اتصال ثنائي الاتجاه بين أجزاء مختلفة من الإضافة، حيث إطار (المستوى الأعلى) يُنظر إليه على أنه الجزء الأصغر. عند الاتصال بـ tabs.connect أو runtime.connect أو runtime.connectNative أو منفذ يتم إنشاؤه. يمكن استخدام هذا المنفذ على الفور لإرسال الرسائل إلى الطرف الآخر عبر postMessage:

إذا كانت هناك إطارات متعددة في علامة تبويب، سيؤدي استدعاء tabs.connect إلى استدعاءات متعددة حدث runtime.onConnect (مرة لكل إطار في علامة التبويب). وبالمثل، إذا يتمّ استخدام runtime.connect، ثم قد يتم تنشيط حدث onConnect عدة مرات (مرة واحدة لكل كل). إطارك في عملية التمديد).

قد تحتاج إلى معرفة متى يتم إغلاق الاتصال، على سبيل المثال إذا كنت تحتفظ بدليل منفصل لكل منفذ مفتوح. لإجراء ذلك، يمكنك الاستماع إلى الحدث runtime.Port.onDisconnect. هذا النمط في حال عدم وجود منافذ صالحة على الجانب الآخر من القناة. يحدث هذا في المواقف التالية:

  • لا توجد أدوات معالجة لـ runtime.onConnect على الطرف الآخر.
  • تم إلغاء تحميل علامة التبويب التي تحتوي على المنفذ (على سبيل المثال، إذا تم التنقّل في علامة التبويب).
  • تم إلغاء تحميل الإطار الذي تم استدعاء "connect" منه.
  • تم إلغاء تحميل جميع اللقطات التي استلمت المنفذ (من خلال runtime.onConnect).
  • يتم استدعاء runtime.Port.disconnect من خلال الطرف الآخر. لاحظ أنه إذا أدت مكالمة connect في عدة منافذ عند طرف المُستلِم، ويتم استدعاء disconnect() في أي من هذه المنافذ، ثم يتم إطلاق حدث onDisconnect في منفذ المُرسِل فقط، وليس في المنافذ الأخرى.

المراسلة عبر الإضافات

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

يتشابه الاستماع إلى الطلبات والاتصالات الواردة مع الحالة الداخلية، باستثناء أنك تستخدم runtime.onMessageExternal أو runtime.onConnectExternal. إليك مثال على كل منها:

// For simple requests:
chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id == blocklistedExtension)
      return;  // don't allow this extension access
    else if (request.getTargetData)
      sendResponse({targetData: targetData});
    else if (request.activateLasers) {
      var success = activateLasers();
      sendResponse({activateLasers: success});
    }
  });

// For long-lived connections:
chrome.runtime.onConnectExternal.addListener(function(port) {
  port.onMessage.addListener(function(msg) {
    // See other examples for sample onMessage handlers.
  });
});

وبالمثل، فإنّ إرسال رسالة إلى إضافة أخرى يشبه إرسال إحدى الإضافات ضمن إضافتك. الاختلاف الوحيد هو أنه يجب عليك تمرير معرّف الإضافة التي تريد الاتصال بها. بالنسبة مثال:

// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
  function(response) {
    if (targetInRange(response.targetData))
      chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
  }
);

// Start a long-running conversation:
var port = chrome.runtime.connect(laserExtensionId);
port.postMessage(...);

إرسال رسائل من صفحات الويب

كما هو الحال بالنسبة إلى المراسلة بين الإضافات، يمكن للتطبيق أو الإضافة تلقي الرسائل والاستجابة لها رسائل من صفحات ويب عادية. لاستخدام هذه الميزة، يجب أولاً التحديد في ملف البيان.json مواقع الويب التي تريد التواصل معها. على سبيل المثال:

"externally_connectable": {
  "matches": ["*://*.example.com/*"]
}

سيؤدي ذلك إلى عرض واجهة برمجة التطبيقات للمراسلة على أي صفحة تتطابق مع أنماط عناوين URL التي تحدّدها. عنوان URL على نطاق من المستوى الثاني على الأقل، أي أنماط اسم المضيف مثل "*"، " *.com" و" *.co.uk" و" *.appspot.com" محظورًا. من صفحة الويب، استخدم العنصر واجهات برمجة التطبيقات runtime.sendMessage أو runtime.connect لإرسال رسالة إلى تطبيق محدّد الإضافة. على سبيل المثال:

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
  function(response) {
    if (!response.success)
      handleError(url);
  });

من التطبيق أو الإضافة، يمكنك الاستماع إلى رسائل من صفحات الويب عبر واجهات برمجة التطبيقات runtime.onMessageExternal أو runtime.onConnectExternal إلى جانب الإضافة المتقاطعة المراسلة. يمكن لصفحة الويب فقط بدء الاتصال. يُرجى الاطّلاع على المثال أدناه:

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.url == blocklistedWebsite)
      return;  // don't allow this web page access
    if (request.openUrlInEditor)
      openUrl(request.openUrlInEditor);
  });

المراسلة الأصلية

يمكن للإضافات والتطبيقات تبادل الرسائل مع التطبيقات الأصلية المسجَّلة كـ مضيف المراسلة مع التطبيقات الأصلية. للتعرّف على مزيد من المعلومات حول هذه الميزة، يمكنك الاطّلاع على المراسلة الأصلية.

الاعتبارات الأمنية

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

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

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

يجب توخّي الحذر عند تلقّي رسالة من نص برمجي للمحتوى أو إضافة أخرى لن يقع ضحية النصوص البرمجية للمواقع الإلكترونية المختلفة. تنطبق هذه النصيحة على النصوص البرمجية التي يتم تشغيلها داخل صفحة الخلفية للإضافة بالإضافة إلى النصوص البرمجية للمحتوى قيد التشغيل داخل أصول الويب الأخرى. على وجه التحديد، تجنَّب استخدام واجهات برمجة التطبيقات الخطيرة مثل تلك الواردة أدناه:

chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
  // WARNING! Might be evaluating an evil script!
  var resp = eval("(" + response.farewell + ")");
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
  // WARNING! Might be injecting a malicious script!
  document.getElementById("resp").innerHTML = response.farewell;
});

بدلاً من ذلك، يمكنك تفضيل واجهات برمجة التطبيقات الأكثر أمانًا التي لا تشغّل النصوص البرمجية:

chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
  // JSON.parse does not evaluate the attacker's scripts.
  var resp = JSON.parse(response.farewell);
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
  // innerText does not let the attacker inject HTML elements.
  document.getElementById("resp").innerText = response.farewell;
});

أمثلة

يمكنك العثور على أمثلة بسيطة للتواصل عبر الرسائل في الأمثلة/واجهة برمجة التطبيقات/المراسلة. الدليل. يوضح نموذج الرسائل الأصلية كيف يمكن لتطبيق Chrome التواصل مع تطبيق محلي. لمزيد من الأمثلة والحصول على المساعدة في عرض رمز المصدر، اطّلِع على عيّنات.