استخدام الموقع الجغرافي

إذا أردت الحصول على معلومات الموقع الجغرافي في إضافة Chrome، يمكنك استخدام واجهة برمجة التطبيقات navigator.geolocation Web Platform API نفسها التي تستخدمها عادةً أي موقع إلكتروني. تظهر هذه المقالة لأنّ إضافات Chrome تتعامل مع إذن الوصول إلى البيانات الحسّاسة بشكل مختلف عن المواقع الإلكترونية. تجدر الإشارة إلى أنّ رصد الموقع الجغرافي هو بيانات حسّاسة للغاية، لذا تضمن المتصفِّحات أنّ المستخدمين على دراية كاملة بأوقات وأين تتم مشاركة موقعهم الجغرافي الدقيق ويمكنهم التحكّم به.

استخدام ميزة رصد الموقع الجغرافي في إضافات MV3

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

لقطة شاشة لمطالبة الإذن التي تظهر لك عندما يطلب موقع إلكتروني الوصول إلى واجهة برمجة تطبيقات رصد الموقع الجغرافي
طلب إذن رصد الموقع الجغرافي

الأذونات ليست الفرق الوحيد. كما ذكرنا أعلاه، navigator.geolocation هي واجهة برمجة تطبيقات من النوع DOM، وهي جزء من واجهات برمجة التطبيقات التي تتألف منها المواقع الإلكترونية. ونتيجةً لذلك، لا يمكن الوصول إليه ضمن سياقات المشغّلين، مثل عامل تشغيل خدمات الإضافات الذي يشكّل العمود الفقري للإضافات المستنِدة إلى إصدار Manifest v3. ومع ذلك، لا يزال بإمكانكِ بالتأكيد استخدام geolocation. هناك فروق دقيقة فقط في طريقة ومكان استخدامهما.

استخدام ميزة رصد الموقع الجغرافي في مشغّلي الخدمات

ما مِن عنصر navigator داخل مشغّلي الخدمة. ولا تتوفّر هذه الميزة إلا داخل السياقات التي يمكنها الوصول إلى عنصر document في الصفحة. للوصول إلى مشغّل الخدمات من الداخل، استخدِم Offscreen Document، الذي يوفّر إمكانية الوصول إلى ملف HTML يمكنك تجميعه مع إضافتك.

للبدء، أضِف "offscreen" إلى القسم "permissions" في ملف البيان.

manifest.json:

{
  "name": "My extension",
    ...
  "permissions": [
    ...
   "offscreen"
  ],
  ...
}

بعد إضافة إذن ""offscreen""، أضِف إلى إضافتك ملف HTML يتضمّن المستند خارج الشاشة. لا تستخدم هذه الحالة أيًا من محتوى الصفحة، لذا يمكن أن يكون هذا الملف فارغًا تقريبًا. بل يجب أن يكون ملف HTML صغيرًا يتم تحميله في النص البرمجي.

offscreen.html:

<!doctype html>
<title>offscreenDocument</title>
<script src="offscreen.js"></script>

احفظ هذا الملف في جذر مشروعك باسم offscreen.html.

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

offscreen.js:

chrome.runtime.onMessage.addListener(handleMessages);
function handleMessages(message, sender, sendResponse) {
  // Return early if this message isn't meant for the offscreen document.
  if (message.target !== 'offscreen') {
    return;
  }

  if (message.type !== 'get-geolocation') {
    console.warn(`Unexpected message type received: '${message.type}'.`);
    return;
  }

  // You can directly respond to the message from the service worker with the
  // provided `sendResponse()` callback. But in order to be able to send an async
  // response, you need to explicitly return `true` in the onMessage handler
  // As a result, you can't use async/await here. You'd implicitly return a Promise.
  getLocation().then((loc) => sendResponse(loc));

  return true;
}

// getCurrentPosition() returns a prototype-based object, so the properties
// end up being stripped off when sent to the service worker. To get
// around this, create a deep clone.
function clone(obj) {
  const copy = {};
  // Return the value of any non true object (typeof(null) is "object") directly.
  // null will throw an error if you try to for/in it. Just return
  // the value early.
  if (obj === null || !(obj instanceof Object)) {
    return obj;
  } else {
    for (const p in obj) {
      copy[p] = clone(obj[p]);
    }
  }
  return copy;
}

async function getLocation() {
  // Use a raw Promise here so you can pass `resolve` and `reject` into the
  // callbacks for getCurrentPosition().
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (loc) => resolve(clone(loc)),
      // in case the user doesnt have/is blocking `geolocation`
      (err) => reject(err)
    );
  });
}

وبعد تنفيذ ذلك، يمكنك الآن الوصول إلى المستند خارج الشاشة في مشغّل الخدمات.

chrome.offscreen.createDocument({
  url: 'offscreen.html',
  reasons: [chrome.offscreen.Reason.GEOLOCATION || chrome.offscreen.Reason.DOM_SCRAPING],
  justification: 'geolocation access',
});

يُرجى العلم أنّه عند الوصول إلى مستند خارج الشاشة، يجب تضمين reason. لم يكن السبب geolocation متاحًا في الأصل، لذا يُرجى تحديد عنصر احتياطي عن DOM_SCRAPING، وشرح الإجراء الذي ينفّذه الرمز فعليًا في القسم justification. تستخدم عملية المراجعة في "سوق Chrome الإلكتروني" هذه المعلومات لضمان استخدام المستندات خارج الشاشة لغرض صالح.

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

.

service_worker.js:

const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html';
let creating; // A global promise to avoid concurrency issues

chrome.runtime.onMessage.addListener(handleMessages);

async function getGeolocation() {
  await setupOffscreenDocument(OFFSCREEN_DOCUMENT_PATH);
  const geolocation = await chrome.runtime.sendMessage({
    type: 'get-geolocation',
    target: 'offscreen'
  });
  await closeOffscreenDocument();
  return geolocation;
}

async function hasDocument() {
  // Check all windows controlled by the service worker to see if one
  // of them is the offscreen document with the given path
  const offscreenUrl = chrome.runtime.getURL(OFFSCREEN_DOCUMENT_PATH);
  const matchedClients = await clients.matchAll();

  return matchedClients.some(c => c.url === offscreenUrl)
}

async function setupOffscreenDocument(path) {
  //if we do not have a document, we are already setup and can skip
  if (!(await hasDocument())) {
    // create offscreen document
    if (creating) {
      await creating;
    } else {
      creating = chrome.offscreen.createDocument({
        url: path,
        reasons: [chrome.offscreen.Reason.GEOLOCATION || chrome.offscreen.Reason.DOM_SCRAPING],
        justification: 'add justification for geolocation use here',
      });

      await creating;
      creating = null;
    }
  }
}

async function closeOffscreenDocument() {
  if (!(await hasDocument())) {
    return;
  }
  await chrome.offscreen.closeDocument();
}

والآن، عندما تريد الحصول على الموقع الجغرافي من مشغّل الخدمات، ما عليك سوى الاتصال على:

const location = await getGeolocation()

استخدام ميزة رصد الموقع الجغرافي في نافذة منبثقة أو لوحة جانبية

من السهل جدًا استخدام ميزة رصد الموقع الجغرافي في نافذة منبثقة أو لوحة جانبية. النوافذ المنبثقة واللوحات الجانبية هي مجرد مستندات ويب، وبالتالي يمكنها الوصول إلى واجهات برمجة تطبيقات DOM العادية. يمكنك الوصول إلى "navigator.geolocation" مباشرةً. الاختلاف الوحيد عن المواقع الإلكترونية العادية هو أنّك تحتاج إلى استخدام الحقل "permission" manifest.json لطلب إذن "geolocation". إذا لم يتم تضمين الإذن، سيظل بإمكانك الوصول إلى "navigator.geolocation". ومع ذلك، ستؤدي أي محاولة لاستخدامه إلى حدوث خطأ فوري، مثلما يحدث إذا رفض المستخدم الطلب. يمكنك رؤية هذا في نموذج النافذة المنبثقة.

استخدام الموقع الجغرافي في نص برمجي للمحتوى

وتمامًا مثل النافذة المنبثقة، يملك النص البرمجي للمحتوى إمكانية الوصول الكامل إلى واجهة برمجة تطبيقات DOM. ومع ذلك، سينتقل المستخدمون إلى المسار العادي لأذونات المستخدم. ويعني ذلك أنّ إضافة "geolocation" إلى "permissions" لن تتيح لك تلقائيًا الوصول إلى بيانات المستخدمين. معلومات الموقع الجغرافي. يمكنك الاطّلاع على ذلك في نموذج النص البرمجي للمحتوى.