cari
Rumahhujung hadapan webtutorial jsMembina sambungan silang penyemak imbas yang menyekat tapak

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'"
  },
}
</all_urls></all_urls>

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'",
}
</all_urls>

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

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

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"]
  }],
}

manifest.firefox.json:

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

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

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'"
  },
}
</all_urls></all_urls>

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'",
}
</all_urls>

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

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

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"]
  }],
}

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
    ]
  }],
}

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'"
  },
}
</all_urls></all_urls>

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'"
  },
}
</all_urls></all_urls>

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'",
}
</all_urls>

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

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

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"]
  }],
}

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
    ]
  }],
}

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!

Kenyataan
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
Aplikasi JavaScript: Dari Front-End ke Back-EndAplikasi JavaScript: Dari Front-End ke Back-EndMay 04, 2025 am 12:12 AM

JavaScript boleh digunakan untuk pembangunan front-end dan back-end. Bahagian depan meningkatkan pengalaman pengguna melalui operasi DOM, dan back-end mengendalikan tugas pelayan melalui Node.js. 1. Contoh front-end: Tukar kandungan teks laman web. 2. Contoh backend: Buat pelayan Node.js.

Python vs JavaScript: Bahasa mana yang harus anda pelajari?Python vs JavaScript: Bahasa mana yang harus anda pelajari?May 03, 2025 am 12:10 AM

Memilih Python atau JavaScript harus berdasarkan perkembangan kerjaya, keluk pembelajaran dan ekosistem: 1) Pembangunan Kerjaya: Python sesuai untuk sains data dan pembangunan back-end, sementara JavaScript sesuai untuk pembangunan depan dan penuh. 2) Kurva Pembelajaran: Sintaks Python adalah ringkas dan sesuai untuk pemula; Sintaks JavaScript adalah fleksibel. 3) Ekosistem: Python mempunyai perpustakaan pengkomputeran saintifik yang kaya, dan JavaScript mempunyai rangka kerja front-end yang kuat.

Rangka Kerja JavaScript: Menguasai Pembangunan Web ModenRangka Kerja JavaScript: Menguasai Pembangunan Web ModenMay 02, 2025 am 12:04 AM

Kuasa rangka kerja JavaScript terletak pada pembangunan yang memudahkan, meningkatkan pengalaman pengguna dan prestasi aplikasi. Apabila memilih rangka kerja, pertimbangkan: 1.

Hubungan antara JavaScript, C, dan penyemak imbasHubungan antara JavaScript, C, dan penyemak imbasMay 01, 2025 am 12:06 AM

Pengenalan Saya tahu anda mungkin merasa pelik, apa sebenarnya yang perlu dilakukan oleh JavaScript, C dan penyemak imbas? Mereka seolah -olah tidak berkaitan, tetapi sebenarnya, mereka memainkan peranan yang sangat penting dalam pembangunan web moden. Hari ini kita akan membincangkan hubungan rapat antara ketiga -tiga ini. Melalui artikel ini, anda akan mempelajari bagaimana JavaScript berjalan dalam penyemak imbas, peranan C dalam enjin pelayar, dan bagaimana mereka bekerjasama untuk memacu rendering dan interaksi laman web. Kita semua tahu hubungan antara JavaScript dan penyemak imbas. JavaScript adalah bahasa utama pembangunan front-end. Ia berjalan secara langsung di penyemak imbas, menjadikan laman web jelas dan menarik. Adakah anda pernah tertanya -tanya mengapa Javascr

Aliran node.js dengan typescriptAliran node.js dengan typescriptApr 30, 2025 am 08:22 AM

Node.js cemerlang pada I/O yang cekap, sebahagian besarnya terima kasih kepada aliran. Aliran memproses data secara berperingkat, mengelakkan beban memori-ideal untuk fail besar, tugas rangkaian, dan aplikasi masa nyata. Menggabungkan sungai dengan keselamatan jenis typescript mencipta powe

Python vs JavaScript: Pertimbangan Prestasi dan KecekapanPython vs JavaScript: Pertimbangan Prestasi dan KecekapanApr 30, 2025 am 12:08 AM

Perbezaan prestasi dan kecekapan antara Python dan JavaScript terutamanya dicerminkan dalam: 1) sebagai bahasa yang ditafsirkan, Python berjalan perlahan tetapi mempunyai kecekapan pembangunan yang tinggi dan sesuai untuk pembangunan prototaip pesat; 2) JavaScript adalah terhad kepada benang tunggal dalam penyemak imbas, tetapi I/O multi-threading dan asynchronous boleh digunakan untuk meningkatkan prestasi dalam node.js, dan kedua-duanya mempunyai kelebihan dalam projek sebenar.

Asal JavaScript: Meneroka Bahasa PelaksanaannyaAsal JavaScript: Meneroka Bahasa PelaksanaannyaApr 29, 2025 am 12:51 AM

JavaScript berasal pada tahun 1995 dan dicipta oleh Brandon Ike, dan menyedari bahasa itu menjadi C. 1.C Language menyediakan keupayaan pengaturcaraan prestasi tinggi dan sistem untuk JavaScript. 2. Pengurusan memori JavaScript dan pengoptimuman prestasi bergantung pada bahasa C. 3. Ciri lintas platform bahasa C membantu JavaScript berjalan dengan cekap pada sistem operasi yang berbeza.

Di sebalik tabir: Apa bahasa JavaScript?Di sebalik tabir: Apa bahasa JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript berjalan dalam penyemak imbas dan persekitaran Node.js dan bergantung pada enjin JavaScript untuk menghuraikan dan melaksanakan kod. 1) menjana pokok sintaks abstrak (AST) di peringkat parsing; 2) menukar AST ke bytecode atau kod mesin dalam peringkat penyusunan; 3) Laksanakan kod yang disusun dalam peringkat pelaksanaan.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

SublimeText3 Linux versi baharu

SublimeText3 Linux versi baharu

SublimeText3 Linux versi terkini

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Persekitaran pembangunan bersepadu PHP yang berkuasa

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini

EditPlus versi Cina retak

EditPlus versi Cina retak

Saiz kecil, penyerlahan sintaks, tidak menyokong fungsi gesaan kod

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.