Rumah > hujung hadapan web > tutorial js > Membina sambungan silang penyemak imbas yang menyekat tapak

Membina sambungan silang penyemak imbas yang menyekat tapak

Mary-Kate Olsen
Lepaskan: 2025-01-22 22:33:16
asal
522 orang telah melayarinya

Dalam artikel ini, saya akan menerangkan proses langkah demi langkah saya untuk membina sambungan penyemak imbas untuk menyekat tapak web dan menerangkan cabaran yang saya hadapi dan penyelesaian yang saya hasilkan. Ini tidak dimaksudkan untuk menjadi panduan yang lengkap. Saya tidak mengaku pakar dalam apa-apa pun. Saya hanya ingin berkongsi proses pemikiran saya di sebalik pembinaan projek ini. Jadi bawa semuanya di sini dengan sebutir garam. Saya tidak akan merangkumi setiap baris tetapi sebaliknya menumpukan pada perkara utama projek, perjuangan, kes menarik dan kebiasaan projek. Anda dialu-alukan untuk menerokai kod sumber dengan lebih terperinci untuk diri sendiri.


Daftar Kandungan:

  • Pendahuluan
  • Menyediakan projek
  • Mencipta borang input utama
  • Mengendalikan blok URL
  • Membuat halaman pilihan
  • Melaksanakan mod ketat
  • Kesimpulan

Mukadimah

Sama seperti kebanyakan orang, saya bergelut dengan memfokuskan pada tugasan yang berbeza, terutamanya dengan Internet menjadi pengacau di mana-mana. Nasib baik, sebagai seorang pengaturcara, saya telah membangunkan kemahiran mencipta masalah yang hebat, jadi saya memutuskan bahawa, daripada mencari penyelesaian sedia ada yang lebih baik, saya akan mencipta sambungan penyemak imbas saya sendiri yang akan menyekat tapak web yang ingin dihadkan oleh pengguna.
Pertama, mari kita gariskan keperluan dan ciri utama. Sambungan mesti:

  • jadi penyemak imbas silang.
  • sekat tapak web daripada senarai hitam.
  • benarkan untuk memilih pilihan menyekat: sama ada menyekat keseluruhan domain dengan subdomainnya atau menyekat hanya URL yang dipilih.
  • menyediakan keupayaan untuk melumpuhkan tapak web yang disekat tanpa memadamkannya daripada senarai hitam.
  • berikan pilihan untuk menyekat akses secara automatik jika pengguna berulang atau terlupa untuk mendayakan semula URL yang dilumpuhkan (membantu untuk penghidap ADHD).

Menyediakan projek

Pertama, berikut ialah susunan utama yang saya pilih:

  • TypeScript: Saya memilih TS berbanding JS kerana banyak API yang tidak dikenali untuk sambungan pergi tanpa ciri autolengkap.
  • Webpack: Lebih mudah digunakan dalam konteks ini berbanding tsc untuk kompilasi TS. Selain itu, saya menghadapi masalah menjana JS yang mematuhi penyemak imbas dengan tsc.
  • CSS: CSS Vanila sepadan dengan matlamat saya untuk kesederhanaan, saiz berkas yang lebih kecil dan kebergantungan minimum. Selain itu, saya merasakan apa-apa lagi akan menjadi keterlaluan untuk sambungan dengan hanya beberapa halaman. Atas sebab itu saya juga memutuskan untuk tidak menggunakan alatan seperti React atau rangka kerja pembinaan sambungan tertentu.

Perbezaan utama pembangunan sambungan daripada pembangun web biasa ialah sambungan bergantung pada pekerja perkhidmatan yang mengendalikan kebanyakan acara, skrip kandungan dan pemesejan di antara mereka.

Mencipta Manifes

Untuk menyokong fungsi merentas pelayar, saya mencipta dua fail manifes:

  • manifest.chrome.json: Untuk keperluan Manifest v3 Chrome.
  • manifest.firefox.json: Untuk Firefox, yang lebih baik menyokong Manifest v2. Berikut ialah perbezaan utama antara 2 fail:

manifest.chrome.json:

{
  "manifest_version": 3,
  "action": {
    "default_title": "Click to show the form"
  },
  "incognito": "split",
  "permissions": [
    "activeTab",
    "declarativeNetRequestWithHostAccess",
    "scripting",
    "storage",
    "tabs"
  ],
  "host_permissions": ["*://*/"], // get access to all URLs
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"]
  }],
  "web_accessible_resources": [
    {
      "resources": ["blocked.html", "options.html", "about.html", "icons/*.svg"],
      "matches": ["<all_urls>"]
    }
  ],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

manifest.firefox.json:

{
  "manifest_version": 2,
  "browser_action": {
    "default_title": "Click to show the form"
  },
  "permissions": [
    "activeTab",
    "declarativeNetRequest",
    "declarativeNetRequestWithHostAccess",
    "scripting", 
    "storage",
    "tabs",
    "*://*/"
  ],
  "background": {
    "scripts": [
      "background.js"
    ],
    "persistent": false
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": [
      "options.js",
      "blocked.js",
      "about.js"
    ]
  }],
  "web_accessible_resources": [
    "blocked.html",
    "options.html", 
    "icons/*.svg"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'",
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Satu perkara yang menarik di sini ialah Chrome memerlukan "inkognito": "split", sifat yang ditentukan untuk berfungsi dengan betul dalam mod inkognito manakala Firefox berfungsi dengan baik tanpanya.

Berikut ialah struktur fail asas sambungan:

dist/
node_modules/
src/
|-- background.tsc
|-- content.ts
static/
|-- manifest.chrome.json
|-- manifest.firefox.json
package.json
tsconfig.json
webpack.config.js
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sekarang mari kita bincangkan tentang cara sambungan itu sepatutnya berfungsi. Pengguna sepatutnya boleh mencetuskan beberapa jenis borang untuk menyerahkan URL yang ingin disekatnya. Apabila dia mengakses URL, sambungan akan memintas permintaan dan menyemak sama ada ia harus disekat atau dibenarkan. Ia juga memerlukan beberapa jenis halaman pilihan yang membolehkan pengguna melihat senarai semua URL yang disekat dan boleh menambah, mengedit, melumpuhkan atau memadamkan URL daripada senarai.

Mencipta borang input utama

Borang muncul dengan menyuntik HTML dan CSS ke dalam halaman semasa apabila pengguna mengklik pada ikon sambungan atau menaip pintasan papan kekunci. Terdapat pelbagai cara untuk memaparkan borang, seperti memanggil pop timbul, tetapi ia mempunyai pilihan penyesuaian terhad untuk citarasa saya. Skrip latar belakang kelihatan seperti ini:

latar belakang.ts:

import browser, { DeclarativeNetRequest } from 'webextension-polyfill';

// on icon click
const action = chrome.action ?? browser.browserAction; // Manifest v2 only has browserAction method
action.onClicked.addListener(tab => {
  triggerPopup(tab as browser.Tabs.Tab);
});

// on shortcut key press 
browser.commands.onCommand.addListener(command => {
  if (command === 'trigger_form') {
    browser.tabs.query({ active: true, currentWindow: true })
      .then((tabs) => {
        const tab = tabs[0];
        if (tab) {
          triggerPopup(tab);
        }
      })
      .catch(error => console.error(error));
  }
});

function triggerPopup(tab: browser.Tabs.Tab) {
  if (tab.id) {
    const tabId = tab.id;
    browser.scripting.insertCSS(({
      target: { tabId },
      files: ['global.css', './popup.css'],
    }))
      .then(() => {
        browser.scripting.executeScript
          ? browser.scripting.executeScript({
            target: { tabId },
            files: ['./content.js'], // refer to the compiled JS files, not the original TS ones 
          })
          : browser.tabs.executeScript({
            file: './content.js',
          });
      })
      .catch(error => console.error(error));
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Menyuntik HTML ke dalam setiap halaman boleh membawa kepada hasil yang tidak dapat diramalkan kerana sukar untuk meramalkan cara gaya halaman web yang berbeza akan mempengaruhi bentuk. Alternatif yang lebih baik nampaknya menggunakan Shadow DOM kerana ia mencipta skopnya sendiri untuk gaya. Sudah tentu potensi peningkatan yang saya ingin usahakan pada masa hadapan.

Saya menggunakan webextension-polyfill untuk keserasian penyemak imbas. Dengan menggunakannya, saya tidak perlu menulis sambungan berasingan untuk versi manifes yang berbeza. Anda boleh membaca lebih lanjut tentang apa yang ia lakukan di sini. Untuk menjadikannya berfungsi, saya menyertakan fail browser-polyfill.js sebelum skrip lain dalam fail manifes.

manifest.chrome.json:

{
  "content_scripts": [{
    "js": ["browser-polyfill.js"]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

manifest.firefox.json:

{
  "background": {
    "scripts": [
      "browser-polyfill.js",
      // other scripts
    ],
  },
  "content_scripts": [{
    "js": [
      "browser-polyfill.js",
      // other scripts
    ]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Proses menyuntik borang ialah manipulasi DOM yang mudah, tetapi ambil perhatian bahawa setiap elemen mesti dibuat secara individu berbanding menggunakan satu templat literal pada elemen. Walaupun lebih bertele-tele dan membosankan, kaedah ini mengelakkan amaran suntikan HTML Tidak Selamat yang kita akan dapat sebaliknya apabila cuba menjalankan kod yang disusun dalam penyemak imbas.

kandungan.ts:

import browser from 'webextension-polyfill';
import { maxUrlLength, minUrlLength } from "./globals";
import { GetCurrentUrl, ResToSend } from "./types";
import { handleFormSubmission } from './helpers';

async function showPopup() {
  const body = document.body;
  const formExists = document.getElementById('extension-popup-form');
  if (!formExists) {
    const msg: GetCurrentUrl = { action: 'getCurrentUrl' };

    try {
      const res: ResToSend = await browser.runtime.sendMessage(msg);

      if (res.success && res.url) {
        const currUrl: string = res.url;
        const popupForm = document.createElement('form');
        popupForm.classList.add('extension-popup-form');
        popupForm.id = 'extension-popup-form';

        /* Create every child element the same way as above */

        body.appendChild(popupForm);
        popupForm.addEventListener('submit', (e) => {
          e.preventDefault();
          handleFormSubmission(popupForm, handleSuccessfulSubmission); // we'll discuss form submission later
        });
        document.addEventListener('keydown', (e) => {
          if (e.key === 'Escape') {
            if (popupForm) {
              body.removeChild(popupForm);
            }
          }
        });
      }
    } catch (error) {
      console.error(error);
      alert('Something went wrong. Please try again.');
    }
  }
}

function handleSuccessfulSubmission() {
  hidePopup();
  setTimeout(() => {
    window.location.reload();
  }, 100); // need to wait a little bit in order to see the changes
}

function hidePopup() {
  const popup = document.getElementById('extension-popup-form');
  popup && document.body.removeChild(popup);
}
Salin selepas log masuk

Kini tiba masanya untuk memastikan borang dipaparkan dalam penyemak imbas. Untuk melaksanakan langkah kompilasi yang diperlukan, saya mengkonfigurasi Webpack seperti ini:

webpack.config.ts:

{
  "manifest_version": 3,
  "action": {
    "default_title": "Click to show the form"
  },
  "incognito": "split",
  "permissions": [
    "activeTab",
    "declarativeNetRequestWithHostAccess",
    "scripting",
    "storage",
    "tabs"
  ],
  "host_permissions": ["*://*/"], // get access to all URLs
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"]
  }],
  "web_accessible_resources": [
    {
      "resources": ["blocked.html", "options.html", "about.html", "icons/*.svg"],
      "matches": ["<all_urls>"]
    }
  ],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Pada asasnya, ia mengambil nama penyemak imbas daripada pembolehubah persekitaran bagi arahan yang saya jalankan untuk memilih antara 2 daripada fail manifes dan menyusun kod TypeScript ke dalam dist/ direktori.

Saya akan menulis ujian yang betul untuk sambungan, tetapi saya mendapati bahawa Puppeteer tidak menyokong ujian skrip kandungan, menjadikannya mustahil untuk menguji kebanyakan ciri. Jika anda tahu tentang sebarang penyelesaian untuk ujian skrip kandungan, saya ingin mendengarnya dalam ulasan.

Arahan binaan saya dalam package.json ialah:

{
  "manifest_version": 2,
  "browser_action": {
    "default_title": "Click to show the form"
  },
  "permissions": [
    "activeTab",
    "declarativeNetRequest",
    "declarativeNetRequestWithHostAccess",
    "scripting", 
    "storage",
    "tabs",
    "*://*/"
  ],
  "background": {
    "scripts": [
      "background.js"
    ],
    "persistent": false
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": [
      "options.js",
      "blocked.js",
      "about.js"
    ]
  }],
  "web_accessible_resources": [
    "blocked.html",
    "options.html", 
    "icons/*.svg"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'",
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jadi, sebagai contoh, setiap kali saya berlari

dist/
node_modules/
src/
|-- background.tsc
|-- content.ts
static/
|-- manifest.chrome.json
|-- manifest.firefox.json
package.json
tsconfig.json
webpack.config.js
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

fail untuk Chrome akan disusun ke dalam dist/ direktori. Selepas mencetuskan borang di mana-mana tapak sama ada dengan mengklik ikon tindakan atau menekan pintasan, borang kelihatan seperti ini:

Main form display

Mengendalikan blok URL

Sekarang borang utama sudah siap, tugas seterusnya ialah menyerahkannya. Untuk melaksanakan fungsi penyekatan, saya memanfaatkan API declarativeNetRequest dan peraturan dinamik. Peraturan akan disimpan dalam storan sambungan. Memanipulasi peraturan dinamik hanya boleh dilakukan dalam fail pekerja perkhidmatan, jadi untuk bertukar-tukar data antara pekerja perkhidmatan dan skrip kandungan, saya akan menghantar mesej antara mereka dengan data yang diperlukan. Memandangkan terdapat beberapa jenis operasi yang diperlukan untuk sambungan ini, saya mencipta jenis untuk setiap tindakan. Berikut ialah contoh jenis operasi:

jenis.ts:

import browser, { DeclarativeNetRequest } from 'webextension-polyfill';

// on icon click
const action = chrome.action ?? browser.browserAction; // Manifest v2 only has browserAction method
action.onClicked.addListener(tab => {
  triggerPopup(tab as browser.Tabs.Tab);
});

// on shortcut key press 
browser.commands.onCommand.addListener(command => {
  if (command === 'trigger_form') {
    browser.tabs.query({ active: true, currentWindow: true })
      .then((tabs) => {
        const tab = tabs[0];
        if (tab) {
          triggerPopup(tab);
        }
      })
      .catch(error => console.error(error));
  }
});

function triggerPopup(tab: browser.Tabs.Tab) {
  if (tab.id) {
    const tabId = tab.id;
    browser.scripting.insertCSS(({
      target: { tabId },
      files: ['global.css', './popup.css'],
    }))
      .then(() => {
        browser.scripting.executeScript
          ? browser.scripting.executeScript({
            target: { tabId },
            files: ['./content.js'], // refer to the compiled JS files, not the original TS ones 
          })
          : browser.tabs.executeScript({
            file: './content.js',
          });
      })
      .catch(error => console.error(error));
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Memandangkan adalah munasabah untuk dapat menambah URL baharu dari borang utama dan dari halaman pilihan, penyerahan telah dilaksanakan oleh fungsi boleh guna semula dalam fail baharu:

pembantu.ts:

{
  "content_scripts": [{
    "js": ["browser-polyfill.js"]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Saya memanggil handleFormSubmission() dalam content.ts yang mengesahkan URL yang disediakan dan kemudian menghantarnya kepada pekerja perkhidmatan untuk menambahkannya ke senarai hitam.

Peraturan dinamik telah menetapkan saiz maksimum yang perlu diambil kira. Melepasi rentetan URL yang terlalu panjang akan membawa kepada tingkah laku yang tidak dijangka apabila cuba menyimpan peraturan dinamik untuknya. Saya mendapati bahawa dalam kes saya, URL sepanjang 75 aksara ialah panjang maksimum yang baik untuk peraturan.

Begini cara pekerja perkhidmatan akan memproses mesej yang diterima:

latar belakang.ts:

{
  "background": {
    "scripts": [
      "browser-polyfill.js",
      // other scripts
    ],
  },
  "content_scripts": [{
    "js": [
      "browser-polyfill.js",
      // other scripts
    ]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Untuk penyerahan, saya mencipta objek peraturan baharu dan mengemas kini peraturan dinamik untuk memasukkannya. Regex bersyarat yang mudah membolehkan saya memilih antara menyekat keseluruhan domain atau hanya URL yang ditentukan.

Selepas selesai, saya menghantar semula mesej respons kepada skrip kandungan. Perkara yang paling menarik dalam coretan ini ialah penggunaan nanoid. Melalui percubaan dan kesilapan, saya mendapati bahawa terdapat had untuk jumlah peraturan dinamik - 5000 untuk penyemak imbas yang lebih lama dan 30000 untuk yang lebih baharu. Saya mendapati bahawa melalui pepijat apabila saya cuba memberikan ID kepada peraturan yang lebih besar daripada 5000. Saya tidak dapat membuat had untuk ID saya berada di bawah 4999, jadi saya terpaksa mengehadkan ID saya kepada nombor 3 digit ( 0-999, iaitu 1000 ID unik kesemuanya). Ini bermakna saya memotong jumlah peraturan untuk pelanjutan saya dari 5000 hingga 1000, yang pada satu tangan agak ketara, tetapi di sisi lain - kebarangkalian pengguna mempunyai URL yang banyak untuk menyekat adalah agak rendah, jadi saya memutuskan untuk berpuas hati dengan penyelesaian yang tidak begitu menarik ini.

Kini pengguna boleh menambah URL baharu pada senarai hitam dan memilih jenis blok yang ingin dia berikan kepada mereka. Jika dia cuba mengakses sumber yang disekat, dia akan diubah hala ke halaman blok:

Block page

Walau bagaimanapun, terdapat satu kes tepi yang perlu ditangani. Sambungan akan menyekat mana-mana URL yang tidak diingini jika pengguna mengaksesnya secara terus. Tetapi jika tapak web itu ialah SPA dengan ubah hala sisi klien, sambungan itu tidak akan menangkap URL terlarang di sana. Untuk mengendalikan kes ini, saya mengemas kini background.ts saya untuk mendengar tab semasa dan melihat sama ada URL telah berubah. Apabila ia berlaku, saya menyemak secara manual sama ada URL berada dalam senarai hitam dan jika ada, saya mengubah hala pengguna.

latar belakang.ts:

{
  "manifest_version": 3,
  "action": {
    "default_title": "Click to show the form"
  },
  "incognito": "split",
  "permissions": [
    "activeTab",
    "declarativeNetRequestWithHostAccess",
    "scripting",
    "storage",
    "tabs"
  ],
  "host_permissions": ["*://*/"], // get access to all URLs
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"]
  }],
  "web_accessible_resources": [
    {
      "resources": ["blocked.html", "options.html", "about.html", "icons/*.svg"],
      "matches": ["<all_urls>"]
    }
  ],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

getRules() ialah fungsi yang menggunakan kaedah declarativeNetRequest.getDynamicRules() untuk mendapatkan semula senarai semua peraturan dinamik yang saya tukar kepada format yang lebih mudah dibaca.

Kini sambungan menyekat URL yang diakses secara terus dan melalui SPA dengan betul.

Mencipta halaman pilihan

Halaman pilihan mempunyai antara muka yang ringkas, seperti yang ditunjukkan di bawah:

Options page

Ini ialah halaman dengan sebahagian besar ciri utama seperti mengedit, memadam, melumpuhkan dan menggunakan mod ketat. Begini cara saya menyambungkannya.

Edit & padam fungsi

Menyunting mungkin merupakan tugas yang paling kompleks. Pengguna boleh mengedit URL dengan mengubah suai rentetannya atau menukar jenis bloknya (sekat keseluruhan domain atau hanya yang khusus). Semasa mengedit, saya mengumpulkan ID URL yang diedit ke dalam tatasusunan. Selepas menyimpan, saya membuat peraturan dinamik yang dikemas kini yang saya berikan kepada pekerja perkhidmatan untuk menggunakan perubahan. Selepas setiap perubahan atau muat semula yang disimpan, saya mengambil semula peraturan dinamik dan menjadikannya dalam jadual. Di bawah ialah versi ringkasnya:

pilihan.ts:

{
  "manifest_version": 3,
  "action": {
    "default_title": "Click to show the form"
  },
  "incognito": "split",
  "permissions": [
    "activeTab",
    "declarativeNetRequestWithHostAccess",
    "scripting",
    "storage",
    "tabs"
  ],
  "host_permissions": ["*://*/"], // get access to all URLs
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"]
  }],
  "web_accessible_resources": [
    {
      "resources": ["blocked.html", "options.html", "about.html", "icons/*.svg"],
      "matches": ["<all_urls>"]
    }
  ],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  },
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Cara saya memutuskan sama ada untuk menyekat atau membenarkan peraturan tertentu adalah dengan menyemak secara bersyarat sifat isActivenya. Mengemas kini peraturan dan mendapatkan semula peraturan - itu adalah 2 lagi operasi untuk ditambahkan pada pendengar latar belakang saya:

latar belakang.ts:

{
  "manifest_version": 2,
  "browser_action": {
    "default_title": "Click to show the form"
  },
  "permissions": [
    "activeTab",
    "declarativeNetRequest",
    "declarativeNetRequestWithHostAccess",
    "scripting", 
    "storage",
    "tabs",
    "*://*/"
  ],
  "background": {
    "scripts": [
      "background.js"
    ],
    "persistent": false
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": [
      "options.js",
      "blocked.js",
      "about.js"
    ]
  }],
  "web_accessible_resources": [
    "blocked.html",
    "options.html", 
    "icons/*.svg"
  ],
  "content_security_policy": "script-src 'self'; object-src 'self'",
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Kefungsian mengemas kini agak sukar untuk diperbaiki kerana terdapat kes kelebihan apabila URL yang diedit menjadi pendua peraturan sedia ada. Selain itu, ia adalah permainan yang sama - kemas kini peraturan dinamik dan hantar mesej yang sesuai setelah selesai.

Memadamkan URL mungkin merupakan tugas yang paling mudah. Terdapat 2 jenis pemadaman dalam sambungan ini: pemadaman peraturan tertentu dan pemadaman semua peraturan.

pilihan.ts:

dist/
node_modules/
src/
|-- background.tsc
|-- content.ts
static/
|-- manifest.chrome.json
|-- manifest.firefox.json
package.json
tsconfig.json
webpack.config.js
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan, sama seperti sebelum ini, saya menambah 2 lagi tindakan pada pendengar pekerja perkhidmatan:

latar belakang.ts:

import browser, { DeclarativeNetRequest } from 'webextension-polyfill';

// on icon click
const action = chrome.action ?? browser.browserAction; // Manifest v2 only has browserAction method
action.onClicked.addListener(tab => {
  triggerPopup(tab as browser.Tabs.Tab);
});

// on shortcut key press 
browser.commands.onCommand.addListener(command => {
  if (command === 'trigger_form') {
    browser.tabs.query({ active: true, currentWindow: true })
      .then((tabs) => {
        const tab = tabs[0];
        if (tab) {
          triggerPopup(tab);
        }
      })
      .catch(error => console.error(error));
  }
});

function triggerPopup(tab: browser.Tabs.Tab) {
  if (tab.id) {
    const tabId = tab.id;
    browser.scripting.insertCSS(({
      target: { tabId },
      files: ['global.css', './popup.css'],
    }))
      .then(() => {
        browser.scripting.executeScript
          ? browser.scripting.executeScript({
            target: { tabId },
            files: ['./content.js'], // refer to the compiled JS files, not the original TS ones 
          })
          : browser.tabs.executeScript({
            file: './content.js',
          });
      })
      .catch(error => console.error(error));
  }
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Melaksanakan mod ketat

Mungkin, ciri utama sambungan ialah keupayaan untuk menguatkuasakan sekatan peraturan orang kurang upaya (dibenarkan untuk akses) secara automatik untuk orang yang memerlukan kawalan yang lebih tegar ke atas tabiat menyemak imbas mereka. Ideanya ialah apabila mod ketat dimatikan, mana-mana URL yang dilumpuhkan oleh pengguna akan kekal dilumpuhkan sehingga pengguna mengubahnya. Dengan mod ketat dihidupkan, sebarang peraturan yang dilumpuhkan akan didayakan semula secara automatik selepas 1 jam. Untuk melaksanakan ciri sedemikian, saya menggunakan storan setempat sambungan untuk menyimpan pelbagai objek yang mewakili setiap peraturan yang dilumpuhkan. Setiap objek termasuk ID peraturan, tarikh nyahsekat dan URL itu sendiri. Pada bila-bila masa pengguna mengakses sumber baharu atau memuat semula senarai hitam, sambungan akan menyemak storan terlebih dahulu untuk mengetahui peraturan yang telah tamat tempoh dan mengemas kininya dengan sewajarnya.

pilihan.ts:

{
  "content_scripts": [{
    "js": ["browser-polyfill.js"]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

isStrictModeOn boolean sedang disimpan dalam storan juga. Jika ia benar, saya mengulangi semua peraturan dan menambah pada storan yang dilumpuhkan dengan masa nyahsekat yang baru dibuat untuk mereka. Kemudian pada setiap respons, saya menyemak storan untuk sebarang peraturan yang dilumpuhkan, mengalih keluar peraturan yang telah tamat tempoh jika wujud dan mengemas kininya:

latar belakang.ts:

{
  "background": {
    "scripts": [
      "browser-polyfill.js",
      // other scripts
    ],
  },
  "content_scripts": [{
    "js": [
      "browser-polyfill.js",
      // other scripts
    ]
  }],
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Setelah itu selesai, sambungan menyekat tapak web selesai. Pengguna boleh menambah, mengedit, memadam dan melumpuhkan mana-mana URL yang mereka kehendaki, menggunakan sebahagian atau keseluruhan blok domain dan menggunakan mod ketat untuk membantu mereka mengekalkan lebih disiplin dalam penyemakan imbas mereka.

Extension work example


Kesimpulan

Itulah gambaran keseluruhan asas sambungan penyekatan tapak saya. Ia adalah sambungan pertama saya, dan ia merupakan pengalaman yang menarik, terutamanya memandangkan bagaimana dunia pembangun web kadangkala boleh menjadi biasa. Pasti ada ruang untuk penambahbaikan dan ciri baharu. Bar carian untuk URL dalam senarai hitam, menambah ujian yang betul, tempoh masa tersuai untuk mod ketat, penyerahan berbilang URL sekaligus - ini hanyalah beberapa perkara dalam fikiran saya yang saya ingin tambahkan pada projek ini suatu hari nanti. Saya juga pada mulanya merancang untuk membuat sambungan merentas platform tetapi tidak dapat menjalankannya pada telefon saya.
Jika anda gemar membaca panduan ini, mempelajari sesuatu yang baharu atau mempunyai sebarang maklum balas lain, ulasan anda amat dihargai. Terima kasih kerana membaca.

Kod sumber
Versi langsung

Atas ialah kandungan terperinci Membina sambungan silang penyemak imbas yang menyekat tapak. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan