भौगोलिक स्थान का इस्तेमाल करें

अगर आपको अपने Chrome एक्सटेंशन में भौगोलिक जगह की जानकारी चाहिए, तो उसी navigator.geolocation वेब प्लैटफ़ॉर्म एपीआई का इस्तेमाल करें जिसका इस्तेमाल आम तौर पर कोई भी वेबसाइट करती है. यह लेख इसलिए मौजूद है, क्योंकि Chrome एक्सटेंशन, संवेदनशील जानकारी को ऐक्सेस करने की अनुमति को वेबसाइटों की तुलना में अलग तरीके से मैनेज करते हैं. जियोलोकेशन का डेटा बहुत संवेदनशील होता है. इसलिए, ब्राउज़र यह पक्का करते हैं कि उपयोगकर्ताओं को इस बात की पूरी जानकारी हो. साथ ही, यह भी तय किया जा सकता है कि उनकी जगह की सटीक जानकारी कब और कहां शेयर की जाए.

MV3 एक्सटेंशन में जियोलोकेशन का इस्तेमाल करें

वेब पर, ब्राउज़र किसी खास ऑरिजिन से उपयोगकर्ताओं को उनकी जगह की जानकारी का ऐक्सेस देने का अनुरोध दिखाकर, उनके जियोलोकेशन के डेटा को सुरक्षित रखते हैं. एक्सटेंशन के लिए, अनुमति का एक ही मॉडल हमेशा सही नहीं होता.

अनुमति के अनुरोध का स्क्रीनशॉट, जो आपको किसी वेबसाइट के भौगोलिक स्थान एपीआई के ऐक्सेस का अनुरोध करने पर दिखता है
जियोलोकेशन की अनुमति का अनुरोध

अनुमतियों में एकमात्र अंतर नहीं है. जैसा कि ऊपर बताया गया है, navigator.geolocation एक DOM एपीआई है. यह एक ऐसी चीज़ है जो वेबसाइटें बनाने वाले एपीआई का हिस्सा है. इस वजह से, इसे वर्कर कॉन्टेक्स्ट में ऐक्सेस नहीं किया जा सकता, जैसे कि एक्सटेंशन सर्विस वर्कर, जो मेनिफ़ेस्ट v3 एक्सटेंशन का आधार है. हालांकि, आप अब भी geolocation का इस्तेमाल कर सकते हैं. आपने इसे कहां और कैसे इस्तेमाल किया है, इसमें बस बारीकियां हैं.

सर्विस वर्कर में जियोलोकेशन का इस्तेमाल करना

सर्विस वर्कर के अंदर कोई navigator ऑब्जेक्ट नहीं है. यह सिर्फ़ उन कॉन्टेक्स्ट में उपलब्ध होता है जिनके पास पेज के document ऑब्जेक्ट का ऐक्सेस होता है. किसी सर्विस वर्कर के अंदर ऐक्सेस पाने के लिए, Offscreen Document का इस्तेमाल करें, जो ऐसी एचटीएमएल फ़ाइल का ऐक्सेस देता है जिसे अपने एक्सटेंशन के साथ बंडल किया जा सकता है.

शुरू करने के लिए, "offscreen" को अपने मेनिफ़ेस्ट के "permissions" सेक्शन में जोड़ें.

manifest.json:

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

"offscreen" अनुमति जोड़ने के बाद, अपने एक्सटेंशन में एक ऐसी एचटीएमएल फ़ाइल जोड़ें जिसमें आपका ऑफ़स्क्रीन दस्तावेज़ शामिल हो. यह मामला पेज के किसी भी कॉन्टेंट का इस्तेमाल नहीं कर रहा है. इसलिए, यह करीब-करीब खाली फ़ाइल हो सकती है. इसे बस एक छोटी एचटीएमएल फ़ाइल की ज़रूरत होती है, जो आपकी स्क्रिप्ट में लोड होती है.

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 Web Store की समीक्षा की प्रोसेस में किया जाता है. इससे यह पक्का किया जाता है कि ऑफ़स्क्रीन दस्तावेज़ों का इस्तेमाल, मान्य काम के लिए किया जा रहा है या नहीं.

ऑफ़स्क्रीन दस्तावेज़ का रेफ़रंस मिलने के बाद, उस दस्तावेज़ को एक मैसेज भेजा जा सकता है. इसमें, आपको भौगोलिक स्थान की अपडेट की गई जानकारी देने के लिए कहा जा सकता है.

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 को सीधे ऐक्सेस किया जा सकता है. स्टैंडर्ड वेबसाइटों में सिर्फ़ यह अंतर होता है कि आपको "geolocation" की अनुमति का अनुरोध करने के लिए, manifest.json "permission" फ़ील्ड का इस्तेमाल करना होगा. अगर अनुमति नहीं दी जाती है, तो भी आपके पास navigator.geolocation का ऐक्सेस रहेगा. हालांकि, इसका इस्तेमाल करने की किसी भी कोशिश से तुरंत गड़बड़ी हो जाएगी, यह ठीक उसी तरह होगी जैसे उपयोगकर्ता ने अनुरोध को अस्वीकार कर दिया हो. इसे पॉप-अप सैंपल में देखा जा सकता है.

किसी कॉन्टेंट स्क्रिप्ट में जियोलोकेशन का इस्तेमाल करना

पॉप-अप की तरह ही, कॉन्टेंट स्क्रिप्ट के पास भी DOM एपीआई का पूरा ऐक्सेस होता है. हालांकि, इसे उपयोगकर्ता की अनुमति के सामान्य फ़्लो से गुज़रना होगा. इसका मतलब है कि "geolocation" को अपने "permissions" में जोड़ने से, आपको उपयोगकर्ताओं की भौगोलिक जगह की जानकारी का ऐक्सेस अपने-आप नहीं मिलेगा. इसे कॉन्टेंट स्क्रिप्ट सैंपल में देखा जा सकता है.