कॉन्टेंट स्क्रिप्ट

कॉन्टेंट स्क्रिप्ट, वे फ़ाइलें होती हैं जो वेब पेजों के संदर्भ में चलती हैं. स्टैंडर्ड डॉक्यूमेंट ऑब्जेक्ट मॉडल (DOM) का इस्तेमाल करके, वे ब्राउज़र पर विज़िट किए गए वेब पेजों की जानकारी पढ़ सकते हैं, उनमें बदलाव कर सकते हैं, और अपने पैरंट एक्सटेंशन को जानकारी दे सकते हैं.

कॉन्टेंट स्क्रिप्ट की सुविधाओं के बारे में जानकारी

कॉन्टेंट स्क्रिप्ट, इन एक्सटेंशन एपीआई को सीधे तौर पर ऐक्सेस कर सकती हैं:

कॉन्टेंट स्क्रिप्ट, सीधे तौर पर दूसरे एपीआई को ऐक्सेस नहीं कर सकतीं. हालांकि, वे आपके एक्सटेंशन के दूसरे हिस्सों के साथ मैसेज शेयर करके, इन फ़ील्ड को ऐक्सेस कर सकते हैं.

fetch() जैसे एपीआई का इस्तेमाल करके, कॉन्टेंट स्क्रिप्ट से अपने एक्सटेंशन में मौजूद अन्य फ़ाइलों को भी ऐक्सेस किया जा सकता है. ऐसा करने के लिए, आपको उन्हें वेब से ऐक्सेस किए जा सकने वाले रिसॉर्स के तौर पर एलान करना होगा. ध्यान दें कि इससे उसी साइट पर चल रही किसी भी पहली-पक्ष या तीसरे-पक्ष की स्क्रिप्ट को भी रिसॉर्स दिखते हैं.

अलग-अलग वर्ल्ड में काम करना

कॉन्टेंट स्क्रिप्ट अलग-अलग काम करती हैं. इसकी वजह से, कॉन्टेंट स्क्रिप्ट अपने JavaScript एनवायरमेंट में बदलाव कर सकती है. ऐसा करने पर, पेज या दूसरे एक्सटेंशन की कॉन्टेंट स्क्रिप्ट पर कोई असर नहीं पड़ता.

कोई एक्सटेंशन, नीचे दिए गए उदाहरण जैसे कोड वाले वेब पेज में चल सकता है.

webPage.html

<html>
  <button id="mybutton">click me</button>
  <script>
    var greeting = "hello, ";
    var button = document.getElementById("mybutton");
    button.person_name = "Bob";
    button.addEventListener(
        "click", () => alert(greeting + button.person_name + "."), false);
  </script>
</html>

वह एक्सटेंशन, स्क्रिप्ट इंजेक्ट करें सेक्शन में बताई गई किसी एक तकनीक का इस्तेमाल करके, नीचे दी गई कॉन्टेंट स्क्रिप्ट को इंजेक्ट कर सकता है.

content-script.js

var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener(
    "click", () => alert(greeting + button.person_name + "."), false);

इस बदलाव के बाद, बटन पर क्लिक करने पर दोनों सूचनाएं क्रम से दिखती हैं.

स्क्रिप्ट इंजेक्ट करना

कॉन्टेंट स्क्रिप्ट को स्टैटिक तौर पर, डाइनैमिक तौर पर या प्रोग्राम के ज़रिए इंजेक्ट किया जा सकता है.

स्टैटिक एलान के साथ इंजेक्ट करना

उन स्क्रिप्ट के लिए, manifest.json में स्टैटिक कॉन्टेंट स्क्रिप्ट के एलान का इस्तेमाल करें जिन्हें पेजों के किसी खास सेट पर अपने-आप चलना चाहिए.

स्टैटिक तौर पर एलान की गई स्क्रिप्ट, मेनिफ़ेस्ट में "content_scripts" बटन के नीचे रजिस्टर की जाती हैं. इनमें JavaScript फ़ाइलें, सीएसएस फ़ाइलें या दोनों शामिल हो सकती हैं. अपने-आप चलने वाली सभी कॉन्टेंट स्क्रिप्ट में, मैच पैटर्न की जानकारी होनी चाहिए.

manifest.json

{
 "name": "My extension",
 ...
 "content_scripts": [
   {
     "matches": ["https://*.nytimes.com/*"],
     "css": ["my-styles.css"],
     "js": ["content-script.js"]
   }
 ],
 ...
}

नाम टाइप ब्यौरा
matches स्ट्रिंग का कलेक्शन ज़रूरी है. इससे यह तय होता है कि इस कॉन्टेंट स्क्रिप्ट को किन पेजों में इंजेक्ट किया जाएगा. इन स्ट्रिंग के सिंटैक्स के बारे में जानकारी के लिए, मैच पैटर्न देखें. साथ ही, यूआरएल को बाहर रखने के तरीके के बारे में जानकारी के लिए, मैच पैटर्न और ग्लोब देखें.
css स्ट्रिंग का कलेक्शन ज़रूरी नहीं. मैच होने वाले पेजों में इंजेक्ट की जाने वाली सीएसएस फ़ाइलों की सूची. ये एलिमेंट, पेज के लिए कोई डीओएम बनाने या दिखाने से पहले, इस कलेक्शन में दिखने के क्रम में इंजेक्ट किए जाते हैं.
js स्ट्रिंग का कलेक्शन ज़रूरी नहीं. मैच करने वाले पेजों में इंजेक्ट की जाने वाली JavaScript फ़ाइलों की सूची. फ़ाइलें, इस कलेक्शन में दिखने के क्रम में इंजेक्ट की जाती हैं. इस सूची में मौजूद हर स्ट्रिंग में, एक्सटेंशन की रूट डायरेक्ट्री में मौजूद किसी रिसॉर्स का रिलेटिव पाथ होना चाहिए. शुरुआत में मौजूद स्लैश (`/`) को अपने-आप काट दिया जाता है.
run_at RunAt ज़रूरी नहीं. यह बताता है कि स्क्रिप्ट को पेज में कब इंजेक्ट किया जाना चाहिए. डिफ़ॉल्ट रूप से, यह वैल्यू document_idle पर सेट होती है.
match_about_blank बूलियन ज़रूरी नहीं. क्या स्क्रिप्ट को about:blank फ़्रेम में इंजेक्ट करना चाहिए जहां पैरंट या ओपनर फ़्रेम, matches में बताए गए किसी पैटर्न से मैच करता है. डिफ़ॉल्ट रूप से, यह 'गलत' पर सेट होती है.
match_origin_as_fallback बूलियन ज़रूरी नहीं. स्क्रिप्ट को उन फ़्रेम में इंजेक्ट करना चाहिए या नहीं जो मैच करने वाले ऑरिजिन से बनाए गए थे, लेकिन जिनका यूआरएल या ऑरिजिन सीधे तौर पर पैटर्न से मैच नहीं करता. इनमें अलग-अलग स्कीम वाले फ़्रेम शामिल हैं, जैसे कि about:, data:, blob:, और filesystem:. मिलते-जुलते फ़्रेम में इंजेक्ट करना भी देखें.
world ExecutionWorld ज़रूरी नहीं. स्क्रिप्ट को चलाने के लिए JavaScript वर्ल्ड. डिफ़ॉल्ट रूप से, यह ISOLATED पर सेट होती है. अलग-अलग वर्ल्ड में काम करना लेख भी पढ़ें.

डाइनैमिक एलान की मदद से इंजेक्ट करना

डाइनैमिक कॉन्टेंट स्क्रिप्ट तब काम की होती हैं, जब कॉन्टेंट स्क्रिप्ट के मैच पैटर्न के बारे में ज़्यादा जानकारी न हो या जब कॉन्टेंट स्क्रिप्ट को हमेशा जाने-पहचाने होस्ट पर इंजेक्ट न किया जाना चाहिए.

Chrome 96 में लॉन्च की गई डाइनैमिक डिक्लेरेशन, स्टैटिक डिक्लेरेशन से मिलती-जुलती हैं. हालांकि, कॉन्टेंट स्क्रिप्ट ऑब्जेक्ट को manifest.json के बजाय, chrome.scripting नेमस्पेस में मौजूद तरीकों का इस्तेमाल करके, Chrome के साथ रजिस्टर किया जाता है. Scripting API की मदद से, एक्सटेंशन डेवलपर ये काम भी कर सकते हैं:

स्टैटिक डिक्लेरेशन की तरह, डाइनैमिक डिक्लेरेशन में JavaScript फ़ाइलें, सीएसएस फ़ाइलें या दोनों शामिल हो सकती हैं.

service-worker.js

chrome.scripting
  .registerContentScripts([{
    id: "session-script",
    js: ["content.js"],
    persistAcrossSessions: false,
    matches: ["*://example.com/*"],
    runAt: "document_start",
  }])
  .then(() => console.log("registration complete"))
  .catch((err) => console.warn("unexpected error", err))

service-worker.js

chrome.scripting
  .updateContentScripts([{
    id: "session-script",
    excludeMatches: ["*://admin.example.com/*"],
  }])
  .then(() => console.log("registration updated"));

service-worker.js

chrome.scripting
  .getRegisteredContentScripts()
  .then(scripts => console.log("registered content scripts", scripts));

service-worker.js

chrome.scripting
  .unregisterContentScripts({ ids: ["session-script"] })
  .then(() => console.log("un-registration complete"));

प्रोग्राम के हिसाब से इंजेक्ट करना

प्रोग्रामैटिक इंजेक्शन का इस्तेमाल उन कॉन्टेंट स्क्रिप्ट के लिए करें जिन्हें इवेंट या खास अवसरों पर चलाना ज़रूरी है.

प्रोग्राम के हिसाब से कॉन्टेंट स्क्रिप्ट इंजेक्ट करने के लिए, आपके एक्सटेंशन को उस पेज के लिए होस्ट की अनुमतियां चाहिए जिसमें स्क्रिप्ट इंजेक्ट की जा रही हैं. होस्ट की अनुमतियां, एक्सटेंशन के मेनिफ़ेस्ट के हिस्से के तौर पर अनुरोध करके या कुछ समय के लिए "activeTab" का इस्तेमाल करके दी जा सकती हैं.

यहां activeTab पर आधारित एक्सटेंशन के अलग-अलग वर्शन दिए गए हैं.

manifest.json:

{
  "name": "My extension",
  ...
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_title": "Action Button"
  }
}

कॉन्टेंट स्क्रिप्ट को फ़ाइलों के तौर पर इंजेक्ट किया जा सकता है.

content-script.js


document.body.style.backgroundColor = "orange";

service-worker.js:

chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    files: ["content-script.js"]
  });
});

इसके अलावा, फ़ंक्शन बॉडी को कॉन्टेंट स्क्रिप्ट के तौर पर इंजेक्ट और लागू किया जा सकता है.

service-worker.js:

function injectedFunction() {
  document.body.style.backgroundColor = "orange";
}

chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target : {tabId : tab.id},
    func : injectedFunction,
  });
});

ध्यान रखें कि इंजेक्ट किया गया फ़ंक्शन, chrome.scripting.executeScript() कॉल में रेफ़र किए गए फ़ंक्शन की कॉपी है, न कि ओरिजनल फ़ंक्शन. इसलिए, फ़ंक्शन का मुख्य हिस्सा अपने-आप काम करना चाहिए. फ़ंक्शन के बाहर के वैरिएबल के रेफ़रंस की वजह से, कॉन्टेंट स्क्रिप्ट में ReferenceError दिखेगा.

फ़ंक्शन के तौर पर इंजेक्ट करते समय, फ़ंक्शन में आर्ग्युमेंट भी पास किए जा सकते हैं.

service-worker.js

function injectedFunction(color) {
  document.body.style.backgroundColor = color;
}

chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target : {tabId : tab.id},
    func : injectedFunction,
    args : [ "orange" ],
  });
});

मैच और ग्लोब को बाहर रखना

किसी पेज से मैच करने की सुविधा को पसंद के मुताबिक बनाने के लिए, एलान वाले रजिस्ट्रेशन में ये फ़ील्ड शामिल करें.

नाम टाइप ब्यौरा
exclude_matches स्ट्रिंग का कलेक्शन ज़रूरी नहीं. उन पेजों को बाहर रखता है जिनमें इस कॉन्टेंट स्क्रिप्ट को इंजेक्ट किया जाना था. इन स्ट्रिंग के सिंटैक्स के बारे में जानकारी पाने के लिए, मैच पैटर्न देखें.
include_globs स्ट्रिंग का कलेक्शन ज़रूरी नहीं. matches के बाद लागू किया जाता है, ताकि सिर्फ़ उन यूआरएल को शामिल किया जा सके जो इस ग्लोब से भी मैच करते हैं. इसका मकसद, @include Greasemonkey कीवर्ड को एमुलेट करना है.
exclude_globs स्ट्रिंग का कलेक्शन ज़रूरी नहीं. इस ग्लोब से मैच होने वाले यूआरएल को बाहर रखने के लिए, matches के बाद लागू किया जाता है. @exclude Greasemonkey कीवर्ड को एमुलेट करने के लिए.

कॉन्टेंट स्क्रिप्ट को पेज में तब इंजेक्ट किया जाएगा, जब ये दोनों बातें सही हों:

  • इसका यूआरएल, किसी भी matches पैटर्न और किसी भी include_globs पैटर्न से मेल खाता है.
  • यह यूआरएल, exclude_matches या exclude_globs पैटर्न से भी मैच नहीं करता. matches प्रॉपर्टी ज़रूरी है, इसलिए exclude_matches, include_globs, और exclude_globs का इस्तेमाल सिर्फ़ यह तय करने के लिए किया जा सकता है कि किन पेजों पर असर पड़ेगा.

यह एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को https://www.nytimes.com/health में इंजेक्ट करता है, लेकिन https://www.nytimes.com/business में नहीं .

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "exclude_matches": ["*://*/*business*"],
      "js": ["contentScript.js"]
    }
  ],
  ...
}

service-worker.js

chrome.scripting.registerContentScripts([{
  id : "test",
  matches : [ "https://*.nytimes.com/*" ],
  excludeMatches : [ "*://*/*business*" ],
  js : [ "contentScript.js" ],
}]);

ग्लोब प्रॉपर्टी, मैच पैटर्न के मुकाबले अलग और ज़्यादा सुविधाजनक सिंटैक्स का इस्तेमाल करती हैं. स्वीकार की जाने वाली ग्लोब स्ट्रिंग, ऐसे यूआरएल होते हैं जिनमें "वाइल्डकार्ड" तारे के निशान और सवाल के निशान हो सकते हैं. तारे का निशान (*), किसी भी लंबाई की किसी भी स्ट्रिंग से मैच करता है. इसमें खाली स्ट्रिंग भी शामिल है. वहीं, सवाल का निशान (?) किसी भी एक वर्ण से मैच करता है.

उदाहरण के लिए, ग्लोब https://???.example.com/foo/\* इनमें से किसी भी चीज़ से मेल खाता है:

  • https://www.example.com/foo/bar
  • https://the.example.com/foo/

हालांकि, यह इनसे मेल नहीं खाता:

  • https://my.example.com/foo/bar
  • https://example.com/foo/
  • https://www.example.com/foo

यह एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को https://www.nytimes.com/arts/index.html और https://www.nytimes.com/jobs/index.htm* में इंजेक्ट करता है, लेकिन https://www.nytimes.com/sports/index.html में नहीं:

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "include_globs": ["*nytimes.com/???s/*"],
      "js": ["contentScript.js"]
    }
  ],
  ...
}

यह एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को https://history.nytimes.com और https://.nytimes.com/history में इंजेक्ट करता है, लेकिन https://science.nytimes.com या https://www.nytimes.com/science में नहीं:

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "exclude_globs": ["*science*"],
      "js": ["contentScript.js"]
    }
  ],
  ...
}

सही दायरा तय करने के लिए, इनमें से कोई एक, सभी या कुछ को शामिल किया जा सकता है.

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "exclude_matches": ["*://*/*business*"],
      "include_globs": ["*nytimes.com/???s/*"],
      "exclude_globs": ["*science*"],
      "js": ["contentScript.js"]
    }
  ],
  ...
}

रनटाइम

run_at फ़ील्ड से यह कंट्रोल किया जाता है कि वेब पेज में JavaScript फ़ाइलें कब इंजेक्ट की जाएं. पसंदीदा और डिफ़ॉल्ट वैल्यू "document_idle" है. अन्य संभावित वैल्यू के लिए, RunAt टाइप देखें.

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "run_at": "document_idle",
      "js": ["contentScript.js"]
    }
  ],
  ...
}

service-worker.js

chrome.scripting.registerContentScripts([{
  id : "test",
  matches : [ "https://*.nytimes.com/*" ],
  runAt : "document_idle",
  js : [ "contentScript.js" ],
}]);
नाम टाइप ब्यौरा
document_idle स्ट्रिंग ज़्यादा पसंद आया. जब भी हो सके, "document_idle" का इस्तेमाल करें.

ब्राउज़र, स्क्रिप्ट को "document_end" और window.onload इवेंट ट्रिगर होने के तुरंत बाद, किसी समय पर इंजेक्ट करता है. इंजेक्शन का सटीक समय इस बात पर निर्भर करता है कि दस्तावेज़ कितना जटिल है और उसे लोड होने में कितना समय लग रहा है. साथ ही, इसे पेज लोड होने की स्पीड के लिए ऑप्टिमाइज़ किया जाता है.

"document_idle" पर चल रही कॉन्टेंट स्क्रिप्ट को window.onload इवेंट के लिए सुनने की ज़रूरत नहीं होती. यह पक्का है कि वे DOM पूरा होने के बाद चलेंगी. अगर किसी स्क्रिप्ट को window.onload के बाद ज़रूर चलाना है, तो एक्सटेंशन यह देख सकता है कि document.readyState प्रॉपर्टी का इस्तेमाल करके, onload पहले से ट्रिगर हो चुका है या नहीं.
document_start स्ट्रिंग स्क्रिप्ट को css की किसी भी फ़ाइल के बाद इंजेक्ट किया जाता है. हालांकि, किसी भी अन्य डीओएम को बनाने या किसी अन्य स्क्रिप्ट को चलाने से पहले ऐसा किया जाता है.
document_end स्ट्रिंग स्क्रिप्ट, DOM पूरा होने के तुरंत बाद इंजेक्ट की जाती हैं. हालांकि, इमेज और फ़्रेम जैसे सब-रिसॉर्स लोड होने से पहले ऐसा किया जाता है.

फ़्रेम तय करना

मेनिफ़ेस्ट में बताई गई, एलान वाली कॉन्टेंट स्क्रिप्ट के लिए, "all_frames" फ़ील्ड की मदद से एक्सटेंशन यह तय कर सकता है कि JavaScript और सीएसएस फ़ाइलों को, यूआरएल की बताई गई ज़रूरी शर्तों से मैच करने वाले सभी फ़्रेम में इंजेक्ट किया जाए या सिर्फ़ टैब में सबसे ऊपर मौजूद फ़्रेम में:

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.nytimes.com/*"],
      "all_frames": true,
      "js": ["contentScript.js"]
    }
  ],
  ...
}

chrome.scripting.registerContentScripts(...) का इस्तेमाल करके, प्रोग्राम के हिसाब से कॉन्टेंट स्क्रिप्ट रजिस्टर करते समय, allFrames पैरामीटर का इस्तेमाल करके यह तय किया जा सकता है कि कॉन्टेंट स्क्रिप्ट को, यूआरएल की तय की गई ज़रूरी शर्तों से मैच करने वाले सभी फ़्रेम में इंजेक्ट किया जाए या सिर्फ़ टैब के सबसे ऊपर वाले फ़्रेम में. इसका इस्तेमाल सिर्फ़ tabId के साथ किया जा सकता है. अगर frameIds या documentIds तय किए गए हैं, तो इसका इस्तेमाल नहीं किया जा सकता:

service-worker.js

chrome.scripting.registerContentScripts([{
  id: "test",
  matches : [ "https://*.nytimes.com/*" ],
  allFrames : true,
  js : [ "contentScript.js" ],
}]);

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

ऐसा तब होता है, जब कोई एक्सटेंशन उन यूआरएल वाले फ़्रेम में इंजेक्ट करना चाहता है जिनमें about:, data:, blob:, और filesystem: स्कीम हों. इन मामलों में, यूआरएल, कॉन्टेंट स्क्रिप्ट के पैटर्न से मेल नहीं खाएगा. साथ ही, about: और data: के मामले में, यूआरएल में पैरंट यूआरएल या ऑरिजिन को शामिल न करें, जैसा कि about:blank या data:text/html,<html>Hello, World!</html> में किया गया है. हालांकि, इन फ़्रेम को अब भी बनाने वाले फ़्रेम से जोड़ा जा सकता है.

इन फ़्रेम में इंजेक्ट करने के लिए, एक्सटेंशन, मैनिफ़ेस्ट में कॉन्टेंट स्क्रिप्ट स्पेसिफ़िकेशन पर "match_origin_as_fallback" प्रॉपर्टी तय कर सकते हैं.

manifest.json

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "matches": ["https://*.google.com/*"],
      "match_origin_as_fallback": true,
      "js": ["contentScript.js"]
    }
  ],
  ...
}

अगर इसकी वैल्यू true पर सेट की गई है, तो Chrome फ़्रेम के यूआरएल के बजाय, फ़्रेम को शुरू करने वाले सोर्स को देखेगा. इससे यह पता चलेगा कि फ़्रेम मैच करता है या नहीं. ध्यान दें कि यह टारगेट फ़्रेम के ऑरिजिन से भी अलग हो सकता है (उदाहरण के लिए, data: यूआरएल का ऑरिजिन शून्य है).

फ़्रेम को शुरू करने वाला वह फ़्रेम होता है जिसने टारगेट फ़्रेम को बनाया या उस पर नेविगेट किया. आम तौर पर, यह सीधे पैरंट या ओपनर होता है. हालांकि, ऐसा ज़रूरी नहीं है (जैसे कि iframe में मौजूद iframe पर नेविगेट करने वाले फ़्रेम के मामले में).

यह, शुरू करने वाले फ़्रेम के ऑरिजिन की तुलना करता है. इसलिए, शुरू करने वाला फ़्रेम उस ऑरिजिन के किसी भी पाथ पर हो सकता है. इस बात को साफ़ तौर पर बताने के लिए, Chrome को "match_origin_as_fallback" के साथ बताई गई किसी भी कॉन्टेंट स्क्रिप्ट के लिए, true पर सेट करने के साथ-साथ * का पाथ भी बताना ज़रूरी है.

अगर "match_origin_as_fallback" और "match_about_blank", दोनों टैग का इस्तेमाल किया जाता है, तो "match_origin_as_fallback" टैग को प्राथमिकता मिलती है.

एम्बेड किए गए पेज से बातचीत

हालांकि, कॉन्टेंट स्क्रिप्ट और उन्हें होस्ट करने वाले पेजों के लागू होने के माहौल एक-दूसरे से अलग होते हैं, लेकिन वे पेज के डीओएम का ऐक्सेस शेयर करते हैं. अगर पेज को कॉन्टेंट स्क्रिप्ट या कॉन्टेंट स्क्रिप्ट के ज़रिए एक्सटेंशन से संपर्क करना है, तो उसे शेयर किए गए DOM के ज़रिए ऐसा करना होगा.

window.postMessage() का इस्तेमाल करके, उदाहरण के तौर पर ऐसा किया जा सकता है:

content-script.js

var port = chrome.runtime.connect();

window.addEventListener("message", (event) => {
  // We only accept messages from ourselves
  if (event.source !== window) {
    return;
  }

  if (event.data.type && (event.data.type === "FROM_PAGE")) {
    console.log("Content script received: " + event.data.text);
    port.postMessage(event.data.text);
  }
}, false);

example.js

document.getElementById("theButton").addEventListener("click", () => {
  window.postMessage(
      {type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);

एक्सटेंशन वाला पेज, example.html, खुद को मैसेज पोस्ट करता है. इस मैसेज को कॉन्टेंट स्क्रिप्ट रोकती है और उसकी जांच करती है. इसके बाद, उसे एक्सटेंशन प्रोसेस में पोस्ट किया जाता है. इस तरह, पेज, एक्सटेंशन की प्रोसेस के लिए संपर्क की लाइन बनाता है. इसी तरह, इसे वापस भी लाया जा सकता है.

एक्सटेंशन फ़ाइलें ऐक्सेस करना

किसी कॉन्टेंट स्क्रिप्ट से एक्सटेंशन फ़ाइल को ऐक्सेस करने के लिए, अपनी एक्सटेंशन एसेट का एब्सोल्यूट यूआरएल पाने के लिए, chrome.runtime.getURL() को कॉल किया जा सकता है. इसका उदाहरण (content.js) यहां दिया गया है:

content-script.js

let image = chrome.runtime.getURL("images/my_image.png")

किसी सीएसएस फ़ाइल में फ़ॉन्ट या इमेज इस्तेमाल करने के लिए, @@extension_id का इस्तेमाल करके यूआरएल बनाया जा सकता है. इसका उदाहरण यहां दिया गया है (content.css):

content.css

body {
 background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');
}

@font-face {
 font-family: 'Stint Ultra Expanded';
 font-style: normal;
 font-weight: 400;
 src: url('chrome-extension://__MSG_@@extension_id__/fonts/Stint Ultra Expanded.woff') format('woff');
}

सभी ऐसेट को manifest.json फ़ाइल में वेब से ऐक्सेस किए जा सकने वाले संसाधन के तौर पर दिखाया जाना चाहिए:

manifest.json

{
 ...
 "web_accessible_resources": [
   {
     "resources": [ "images/*.png" ],
     "matches": [ "https://example.com/*" ]
   },
   {
     "resources": [ "fonts/*.woff" ],
     "matches": [ "https://example.com/*" ]
   }
 ],
 ...
}

खाता सुरक्षित रखना

अलग-अलग वर्ल्ड, सुरक्षा की एक लेयर देते हैं. हालांकि, कॉन्टेंट स्क्रिप्ट का इस्तेमाल करने से, एक्सटेंशन और वेब पेज में कमज़ोरियां पैदा हो सकती हैं. अगर कॉन्टेंट स्क्रिप्ट को किसी दूसरी वेबसाइट से कॉन्टेंट मिलता है, जैसे कि fetch() को कॉल करके, तो उसे इंजेक्ट करने से पहले, क्रॉस-साइट स्क्रिप्टिंग अटैक से बचाने के लिए कॉन्टेंट को फ़िल्टर करें. "man-in-the-middle" हमलों से बचने के लिए, सिर्फ़ एचटीटीपीएस पर कम्यूनिकेट करें.

नुकसान पहुंचाने वाले वेब पेजों को फ़िल्टर करना न भूलें. उदाहरण के लिए, ये पैटर्न खतरनाक हैं और मेनिफ़ेस्ट V3 में इनका इस्तेमाल करने की अनुमति नहीं है:

यह न करें

content-script.js

const data = document.getElementById("json-data");
// WARNING! Might be evaluating an evil script!
const parsed = eval("(" + data + ")");
यह न करें

content-script.js

const elmt_id = ...
// WARNING! elmt_id might be '); ... evil script ... //'!
window.setTimeout("animate(" + elmt_id + ")", 200);

इसके बजाय, ऐसे सुरक्षित एपीआई इस्तेमाल करें जो स्क्रिप्ट नहीं चलाते:

यह करें

content-script.js

const data = document.getElementById("json-data")
// JSON.parse does not evaluate the attacker's scripts.
const parsed = JSON.parse(data);
यह करें

content-script.js

const elmt_id = ...
// The closure form of setTimeout does not evaluate scripts.
window.setTimeout(() => animate(elmt_id), 200);