Coğrafi konumu kullan

Chrome uzantınızda coğrafi konum bilgilerini almak istiyorsanız herhangi bir web sitesinin normalde kullanacağı navigator.geolocation Web platformu API'sini kullanın. Bu makalenin nedeni, Chrome uzantılarının hassas verilere erişim iznini web sitelerinden farklı şekilde ele almalarıdır. Coğrafi konum çok hassas verilerdir, bu nedenle tarayıcılar, kullanıcıların tam konumlarının ne zaman ve nerede paylaşılacağının tamamen farkında olmasını ve kontrolünün sizde olmasını sağlar.

MV3 uzantılarında coğrafi konumu kullanın

Web’de tarayıcılar, kullanıcıların coğrafi konum verilerini kullanarak, ilgili konuma erişim izni vermelerini isteyen bir istem görüntüleyebilirsiniz. Aynı izin modeli, uzantılar için her zaman uygun olmayabilir.

Bir web sitesi coğrafi konum API'sine erişim istediğinde gördüğünüz izin isteminin ekran görüntüsü
Coğrafi konum izni istemi

Tek fark izinler değildir. Yukarıda belirtildiği gibi navigator.geolocation, web sitelerini oluşturan API'lerin parçası olan bir DOM API'sidir. Dolayısıyla manifest v3 uzantılarının bel kemiği olan uzantı hizmet çalışanı gibi çalışan bağlamlarında bu koda erişilemez. Yine de geolocation kullanmaya devam edebilirsiniz. Ancak nerede ve nasıl kullanıldığıyla ilgili bazı nüanslar söz konusudur.

Service Worker'larda coğrafi konumu kullanın

Service Worker'ların içinde navigator nesnesi yok. Yalnızca bir sayfanın document nesnesine erişimi olan bağlamlarda kullanılabilir. Bir hizmet çalışanının içine erişim elde etmek için Offscreen Document kullanın. Bu API, uzantınızla birlikte paket haline getirebileceğiniz bir HTML dosyasına erişim sağlar.

Başlamak için manifest dosyanızın "permissions" bölümüne "offscreen" kodunu ekleyin.

manifest.json:

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

"offscreen" iznini ekledikten sonra, uzantınıza ekran dışındaki dokümanınızı içeren bir HTML dosyası ekleyin. Bu destek kaydında sayfanın hiçbir içeriği kullanılmadığından neredeyse boş bir dosya olabilir. Bunun, komut dosyanıza yüklenen küçük bir HTML dosyası olması yeterlidir.

offscreen.html:

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

Bu dosyayı offscreen.html olarak projenizin kök konumuna kaydedin.

Belirtildiği gibi, offscreen.js adında bir komut dosyasına ihtiyacınız var. Ayrıca, bunu uzantınızla birlikte paketlemeniz gerekir. Bu, Service Worker'ın coğrafi konum bilgisi kaynağı olur. Gemini ile hizmet çalışanınız arasında mesaj aktarabilirsiniz.

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)
    );
  });
}

Bunu yaptıktan sonra hizmet çalışanında ekran dışı dokümana erişmeye hazırsınız demektir.

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

Ekran dışındaki bir dokümana eriştiğinizde reason eklemeniz gerektiğini unutmayın. geolocation nedeni başlangıçta mevcut değildi. Bu nedenle DOM_SCRAPING yedeğini belirtin ve justification bölümünde kodun ne yaptığını açıklayın. Bu bilgiler, Chrome Web Mağazası'nın inceleme sürecinde, ekran dışındaki dokümanların geçerli bir amaç doğrultusunda kullanıldığından emin olmak için kullanılır.

Ekran Dışı Doküman'a referans verdiğinizde, güncellenmiş coğrafi konum bilgilerini size vermesini istemek için bu dokümana bir mesaj gönderebilirsiniz.

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();
}

Bu sayede artık hizmet çalışanınızdan coğrafi konumu öğrenmek istediğinizde tek yapmanız gereken şunları aramaktır:

const location = await getGeolocation()

Pop-up veya yan panelde coğrafi konumu kullanın

Bir pop-up veya yan panelde coğrafi konum kullanımı çok kolaydır. Pop-up'lar ve yan paneller yalnızca web dokümanları olduğu için normal DOM API'lerine erişebilir. navigator.geolocation uygulamasına doğrudan erişebilirsiniz. Standart web sitelerinden tek fark, "geolocation" iznini istemek için manifest.json "permission" alanını kullanmanızın gerekmesidir. Bu izni eklemezseniz navigator.geolocation ürününe erişiminiz devam eder. Ancak bu özelliğin kullanılması, kullanıcının isteği reddetmesi gibi anında bir hataya neden olur. Bunu pop-up örneğinde görebilirsiniz.

İçerik komut dosyasında coğrafi konumu kullanma

Pop-up'larda olduğu gibi, içerik komut dosyalarının da DOM API'ye tam erişimi vardır; kullanıcılar normal kullanıcı izni akışından geçer. Diğer bir deyişle, "permissions" öğelerinize "geolocation" eklemek, kullanıcıların hesaplarına otomatik olarak erişim izni vermeyeceği anlamına gelir. coğrafi konum bilgisidir. Bunu içerik komut dosyası örneğinde görebilirsiniz.