কন্টেন্ট স্ক্রিপ্ট হলো এমন ফাইল যা ওয়েব পেজের প্রেক্ষাপটে চলে। স্ট্যান্ডার্ড ডকুমেন্ট অবজেক্ট মডেল (DOM) ব্যবহার করে, এগুলি ব্রাউজার দ্বারা পরিদর্শিত ওয়েব পেজগুলির বিবরণ পড়তে, সেগুলিতে পরিবর্তন আনতে এবং তাদের প্যারেন্ট এক্সটেনশনে তথ্য পাঠাতে সক্ষম হয়।
কন্টেন্ট স্ক্রিপ্টের সক্ষমতা বুঝুন
কন্টেন্ট স্ক্রিপ্টগুলো সরাসরি নিম্নলিখিত এক্সটেনশন এপিআইগুলো অ্যাক্সেস করতে পারে:
-
dom -
i18n -
storage -
runtime.connect() -
runtime.getManifest() -
runtime.getURL() -
runtime.id -
runtime.onConnect -
runtime.onMessage -
runtime.sendMessage()
কন্টেন্ট স্ক্রিপ্টগুলো সরাসরি অন্য এপিআই অ্যাক্সেস করতে পারে না। কিন্তু আপনার এক্সটেনশনের অন্যান্য অংশের সাথে বার্তা আদান-প্রদানের মাধ্যমে তারা পরোক্ষভাবে সেগুলো অ্যাক্সেস করতে পারে।
আপনি fetch() এর মতো API ব্যবহার করে একটি কন্টেন্ট স্ক্রিপ্ট থেকে আপনার এক্সটেনশনের অন্যান্য ফাইলও অ্যাক্সেস করতে পারেন। এটি করার জন্য, আপনাকে সেগুলোকে ওয়েব-অ্যাক্সেসযোগ্য রিসোর্স হিসেবে ঘোষণা করতে হবে। মনে রাখবেন যে, এর ফলে একই সাইটে চলমান যেকোনো ফার্স্ট-পার্টি বা থার্ড-পার্টি স্ক্রিপ্টের কাছেও রিসোর্সগুলো উন্মুক্ত হয়ে যায়।
বিচ্ছিন্ন বিশ্বে কাজ করুন
কন্টেন্ট স্ক্রিপ্টগুলো একটি বিচ্ছিন্ন জগতে অবস্থান করে, যার ফলে এটি পেজ বা অন্যান্য এক্সটেনশনের কন্টেন্ট স্ক্রিপ্টের সাথে কোনো সংঘাত ছাড়াই তার জাভাস্ক্রিপ্ট পরিবেশে পরিবর্তন আনতে পারে।
একটি এক্সটেনশন কোনো ওয়েব পেজে নিম্নলিখিত উদাহরণের মতো কোড ব্যবহার করে চালানো যেতে পারে।
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>
ওই এক্সটেনশনটি ' স্ক্রিপ্ট ইনজেক্ট করুন' বিভাগে বর্ণিত কৌশলগুলোর মধ্যে একটি ব্যবহার করে নিম্নলিখিত কন্টেন্ট স্ক্রিপ্টটি ইনজেক্ট করতে পারে।
কন্টেন্ট-স্ক্রিপ্ট.জেএস
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" কী-এর অধীনে রেজিস্টার করা হয়। এগুলোতে জাভাস্ক্রিপ্ট ফাইল, সিএসএস ফাইল অথবা উভয়ই অন্তর্ভুক্ত থাকতে পারে। স্বয়ংক্রিয়ভাবে চালু হওয়া সমস্ত কন্টেন্ট স্ক্রিপ্টে অবশ্যই ম্যাচ প্যাটার্ন উল্লেখ করতে হবে।
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"css": ["my-styles.css"],
"js": ["content-script.js"]
}
],
...
}
| নাম | প্রকার | বর্ণনা |
|---|---|---|
matches | স্ট্রিংগুলির অ্যারে | আবশ্যক। এটি নির্দিষ্ট করে যে এই কন্টেন্ট স্ক্রিপ্টটি কোন কোন পেজে যুক্ত করা হবে। এই স্ট্রিংগুলির সিনট্যাক্স সম্পর্কে বিস্তারিত জানতে ‘ম্যাচ প্যাটার্নস’ দেখুন এবং কীভাবে ইউআরএল বাদ দিতে হয় সে সম্পর্কে তথ্যের জন্য ‘ম্যাচ প্যাটার্নস অ্যান্ড গ্লোবস’ দেখুন। |
css | স্ট্রিংগুলির অ্যারে | ঐচ্ছিক। সংশ্লিষ্ট পেজগুলিতে ইনজেক্ট করার জন্য CSS ফাইলগুলির তালিকা। পেজের জন্য কোনো DOM তৈরি বা প্রদর্শিত হওয়ার আগে, এই অ্যারেতে ফাইলগুলি যে ক্রমে রয়েছে, সেই ক্রমেই ইনজেক্ট করা হয়। |
js | | ঐচ্ছিক। সংশ্লিষ্ট পেজগুলিতে ইনজেক্ট করার জন্য জাভাস্ক্রিপ্ট ফাইলগুলির তালিকা। ফাইলগুলি এই অ্যারেতে যে ক্রমে রয়েছে, সেই ক্রমেই ইনজেক্ট করা হয়। এই তালিকার প্রতিটি স্ট্রিং-এ অবশ্যই এক্সটেনশনের রুট ডিরেক্টরিতে থাকা কোনো রিসোর্সের একটি রিলেটিভ পাথ থাকতে হবে। শুরুর স্ল্যাশ (`/`) স্বয়ংক্রিয়ভাবে বাদ দেওয়া হয়। |
run_at | রানঅ্যাট | ঐচ্ছিক। স্ক্রিপ্টটি কখন পৃষ্ঠায় যুক্ত করা হবে তা নির্দিষ্ট করে। ডিফল্ট মান হলো document_idle । |
match_about_blank | বুলিয়ান | ঐচ্ছিক। স্ক্রিপ্টটি এমন একটি about:blank ফ্রেমে ইনজেক্ট করবে কিনা, যেখানে প্যারেন্ট বা ওপেনার ফ্রেমটি matches এ ঘোষিত প্যাটার্নগুলোর কোনো একটির সাথে মেলে। ডিফল্ট মান false। |
match_origin_as_fallback | বুলিয়ান | ঐচ্ছিক। স্ক্রিপ্টটি এমন ফ্রেমে ইনজেক্ট করবে কিনা, যেগুলো একটি মিলে যাওয়া অরিজিন দ্বারা তৈরি হয়েছে, কিন্তু যাদের URL বা অরিজিন সরাসরি প্যাটার্নের সাথে নাও মিলতে পারে। এর মধ্যে বিভিন্ন স্কিমের ফ্রেম অন্তর্ভুক্ত, যেমন about: , data: , blob: , এবং filesystem: । আরও দেখুন সম্পর্কিত ফ্রেমে ইনজেক্ট করা । |
world | এক্সিকিউশনওয়ার্ল্ড | ঐচ্ছিক। কোনো স্ক্রিপ্ট যে জাভাস্ক্রিপ্ট জগতের মধ্যে নির্বাহ হবে। ডিফল্ট হিসেবে এটি ISOLATED । আরও দেখুন: বিচ্ছিন্ন জগতে কাজ করা । |
ডকুমেন্ট লাইফসাইকেলের একটি নির্দিষ্ট পর্যায়ে , ম্যানিফেস্টে স্ট্যাটিক্যালি ঘোষিত কন্টেন্ট স্ক্রিপ্টগুলোই সর্বপ্রথম ইনজেক্ট করা হয়, অন্য কোনোভাবে রেজিস্টার করা কন্টেন্ট স্ক্রিপ্টগুলোর আগে। ম্যানিফেস্টে যে ক্রমে এগুলো নির্দিষ্ট করা থাকে, সেই ক্রমেই এগুলো ইনজেক্ট করা হয়।
ডাইনামিক ডিক্লারেশন দিয়ে ইনজেক্ট করুন
ডাইনামিক কন্টেন্ট স্ক্রিপ্ট তখন উপযোগী হয়, যখন কন্টেন্ট স্ক্রিপ্টের ম্যাচ প্যাটার্নগুলো সুপরিচিত না থাকে অথবা যখন কন্টেন্ট স্ক্রিপ্টগুলো সবসময় পরিচিত হোস্টগুলোতে ইনজেক্ট করার প্রয়োজন হয় না।
ক্রোম ৯৬-এ প্রবর্তিত ডাইনামিক ডিক্লারেশনগুলো স্ট্যাটিক ডিক্লারেশনের মতোই, তবে এক্ষেত্রে কন্টেন্ট স্ক্রিপ্ট অবজেক্টটি manifest.json- এর পরিবর্তে chrome.scripting নেমস্পেসের মেথড ব্যবহার করে ক্রোমের সাথে রেজিস্টার করা হয়। স্ক্রিপ্টিং এপিআই এক্সটেনশন ডেভেলপারদেরকে আরও যেসব কাজ করার সুযোগ দেয়, সেগুলো হলো:
- কন্টেন্ট স্ক্রিপ্ট নিবন্ধন করুন ।
- নিবন্ধিত কন্টেন্ট স্ক্রিপ্টগুলোর একটি তালিকা পান ।
- নিবন্ধিত কন্টেন্ট স্ক্রিপ্টগুলোর তালিকা হালনাগাদ করুন ।
- নিবন্ধিত কন্টেন্ট স্ক্রিপ্টগুলো মুছে ফেলুন ।
স্ট্যাটিক ডিক্লারেশনের মতোই, ডাইনামিক ডিক্লারেশনেও জাভাস্ক্রিপ্ট ফাইল, সিএসএস ফাইল বা উভয়ই অন্তর্ভুক্ত থাকতে পারে।
সার্ভিস-ওয়ার্কার.জেএস
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))
সার্ভিস-ওয়ার্কার.জেএস
chrome.scripting
.updateContentScripts([{
id: "session-script",
excludeMatches: ["*://admin.example.com/*"],
}])
.then(() => console.log("registration updated"));
সার্ভিস-ওয়ার্কার.জেএস
chrome.scripting
.getRegisteredContentScripts()
.then(scripts => console.log("registered content scripts", scripts));
সার্ভিস-ওয়ার্কার.জেএস
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"
}
}
কন্টেন্ট স্ক্রিপ্টগুলো ফাইল হিসেবে ইনজেক্ট করা যেতে পারে।
কন্টেন্ট-স্ক্রিপ্ট.জেএস
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 থ্রো করবে।
ফাংশন হিসেবে ইনজেক্ট করার সময়, আপনি ফাংশনে আর্গুমেন্টও পাস করতে পারেন।
সার্ভিস-ওয়ার্কার.জেএস
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 পর এটি প্রয়োগ করা হয়, যাতে শুধুমাত্র সেইসব URL অন্তর্ভুক্ত হয় যেগুলো এই গ্লোবটির সাথেও মেলে। এর উদ্দেশ্য হলো Greasemonkey-এর @include কীওয়ার্ডটির অনুকরণ করা। |
exclude_globs | স্ট্রিং এর অ্যারে | ঐচ্ছিক। এই গ্লোবের সাথে মেলে এমন URL বাদ দেওয়ার জন্য matches পরে এটি প্রয়োগ করা হয়। এর উদ্দেশ্য হলো Greasemonkey-এর @exclude কীওয়ার্ডটির অনুকরণ করা। |
নিম্নলিখিত উভয় শর্তই সত্য হলে কন্টেন্ট স্ক্রিপ্টটি একটি পেজে যুক্ত করা হবে:
- এর URL যেকোনো
matchesপ্যাটার্ন এবং যেকোনোinclude_globsপ্যাটার্নের সাথে মেলে। - URL-টি
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"]
}
],
...
}
সার্ভিস-ওয়ার্কার.জেএস
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 ফিল্ডটি নিয়ন্ত্রণ করে কখন জাভাস্ক্রিপ্ট ফাইলগুলো ওয়েব পেজে যুক্ত হবে। এর পছন্দের এবং ডিফল্ট মান হলো "document_idle" । অন্যান্য সম্ভাব্য মানের জন্য `RunAt` টাইপটি দেখুন।
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.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 এর যেকোনো ফাইলের পরে, কিন্তু অন্য কোনো DOM তৈরি হওয়ার বা অন্য কোনো স্ক্রিপ্ট চলার আগে ইনজেক্ট করা হয়। |
document_end | স্ট্রিং | DOM সম্পূর্ণ হওয়ার ঠিক পরেই, কিন্তু ছবি এবং ফ্রেমের মতো সাবরিসোর্সগুলো লোড হওয়ার আগে স্ক্রিপ্টগুলো ইনজেক্ট করা হয়। |
ফ্রেম নির্দিষ্ট করুন
ম্যানিফেস্টে নির্দিষ্ট করা ডিক্লারেটিভ কন্টেন্ট স্ক্রিপ্টগুলির জন্য, "all_frames" ফিল্ডটি এক্সটেনশনকে এটি নির্দিষ্ট করার সুযোগ দেয় যে, জাভাস্ক্রিপ্ট এবং সিএসএস ফাইলগুলি নির্দিষ্ট URL-এর শর্ত পূরণকারী সমস্ত ফ্রেমে ইনজেক্ট করা হবে, নাকি শুধুমাত্র একটি ট্যাবের সর্ববৃহৎ ফ্রেমে ইনজেক্ট করা হবে।
manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
chrome.scripting.registerContentScripts(...) ব্যবহার করে প্রোগ্রাম্যাটিকভাবে কন্টেন্ট স্ক্রিপ্ট রেজিস্টার করার সময়, allFrames প্যারামিটারটি ব্যবহার করে নির্দিষ্ট করা যায় যে কন্টেন্ট স্ক্রিপ্টটি নির্দিষ্ট URL-এর শর্ত পূরণকারী সমস্ত ফ্রেমে ইনজেক্ট করা হবে, নাকি শুধুমাত্র একটি ট্যাবের সবচেয়ে উপরের ফ্রেমে। এটি শুধুমাত্র tabId-এর সাথেই ব্যবহার করা যায় এবং frameIds বা documentIds নির্দিষ্ট করা থাকলে ব্যবহার করা যায় না।
সার্ভিস-ওয়ার্কার.জেএস
chrome.scripting.registerContentScripts([{
id: "test",
matches : [ "https://*.nytimes.com/*" ],
allFrames : true,
js : [ "contentScript.js" ],
}]);
সম্পর্কিত ফ্রেমে ইনজেক্ট করুন
এক্সটেনশনগুলো এমন ফ্রেমে স্ক্রিপ্ট চালাতে চাইতে পারে যা একটি মিলে যাওয়া ফ্রেমের সাথে সম্পর্কিত, কিন্তু ফ্রেমগুলো নিজেরা মিলে যায় না। এর একটি সাধারণ উদাহরণ হলো এমন ফ্রেম, যার ইউআরএলগুলো একটি মিলে যাওয়া ফ্রেম দ্বারা তৈরি হয়েছে, কিন্তু সেই ইউআরএলগুলো নিজেরা স্ক্রিপ্টের নির্দিষ্ট প্যাটার্নের সাথে মেলে না।
এটি তখন ঘটে যখন কোনো এক্সটেনশন about: , data: , blob: , এবং filesystem: স্কিমযুক্ত URL সহ ফ্রেমে ইনজেক্ট করতে চায়। এই ক্ষেত্রে, URL-টি কন্টেন্ট স্ক্রিপ্টের প্যাটার্নের সাথে মিলবে না (এবং, about: ও data: এর ক্ষেত্রে, URL-এ প্যারেন্ট URL বা অরিজিন একেবারেই অন্তর্ভুক্ত করবে না, যেমন 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 ফ্রেমটি মেলে কিনা তা নির্ধারণ করতে ফ্রেমটির নিজস্ব URL-এর পরিবর্তে, ফ্রেমটির সূচনাকারীর অরিজিন দেখবে। উল্লেখ্য যে, এটি টার্গেট ফ্রেমের অরিজিন থেকেও ভিন্ন হতে পারে (যেমন, ' data: URL-গুলোর অরিজিন 'null' হয়)।
ফ্রেমটির সূচনাকারী হলো সেই ফ্রেম যা লক্ষ্য ফ্রেমটি তৈরি করেছে বা সেটিতে নেভিগেট করেছে। যদিও এটি সাধারণত সরাসরি প্যারেন্ট বা ওপেনার হয়ে থাকে, তবে তা নাও হতে পারে (যেমন একটি ফ্রেম যখন একটি আইফ্রেমের ভেতরে থাকা আরেকটি আইফ্রেমে নেভিগেট করে)।
যেহেতু এটি ইনিশিয়েটর ফ্রেমের অরিজিন তুলনা করে, তাই ইনিশিয়েটর ফ্রেমটি সেই অরিজিন থেকে যেকোনো পাথে চালু থাকতে পারে। এই বিষয়টি স্পষ্ট করার জন্য, Chrome-এর প্রয়োজন হয় যে, "match_origin_as_fallback" true সেট করা যেকোনো কন্টেন্ট স্ক্রিপ্টেও যেন * পাথটি নির্দিষ্ট করা থাকে।
যখন "match_origin_as_fallback" এবং "match_about_blank" উভয়ই নির্দিষ্ট করা থাকে, তখন "match_origin_as_fallback" অগ্রাধিকার পায়।
এম্বেডিং পৃষ্ঠার সাথে যোগাযোগ
যদিও কন্টেন্ট স্ক্রিপ্টের এক্সিকিউশন এনভায়রনমেন্ট এবং যে পেজগুলো সেগুলোকে হোস্ট করে, সেগুলো একে অপরের থেকে বিচ্ছিন্ন থাকে, তবুও তারা পেজের DOM-এ অ্যাক্সেস শেয়ার করে। যদি পেজটি কন্টেন্ট স্ক্রিপ্টের সাথে, অথবা কন্টেন্ট স্ক্রিপ্টের মাধ্যমে এক্সটেনশনের সাথে যোগাযোগ করতে চায়, তবে তাকে অবশ্যই শেয়ার করা DOM-এর মাধ্যমেই তা করতে হবে।
window.postMessage() ব্যবহার করে একটি উদাহরণ সম্পন্ন করা যেতে পারে:
কন্টেন্ট-স্ক্রিপ্ট.জেএস
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() কল করে আপনার এক্সটেনশন অ্যাসেটের অ্যাবসোলিউট URL পেতে পারেন, যেমনটি নিচের উদাহরণে ( content.js ) দেখানো হয়েছে:
কন্টেন্ট-স্ক্রিপ্ট.জেএস
let image = chrome.runtime.getURL("images/my_image.png")
CSS ফাইলে ফন্ট বা ছবি ব্যবহার করতে, আপনি @@extension_id ব্যবহার করে একটি URL তৈরি করতে পারেন, যেমনটি নিচের উদাহরণে ( 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/*" ]
}
],
...
}
বিষয়বস্তু নিরাপত্তা নীতি
বিচ্ছিন্ন বিশ্বে চলমান কন্টেন্ট স্ক্রিপ্টগুলির নিম্নলিখিত কন্টেন্ট সুরক্ষা নীতি (CSP) রয়েছে:
script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' chrome-extension://abcdefghijklmopqrstuvwxyz/; object-src 'self';
অন্যান্য এক্সটেনশন কনটেক্সটের উপর আরোপিত বিধিনিষেধের মতোই, এটি eval() এর ব্যবহার এবং বাহ্যিক স্ক্রিপ্ট লোড করাকে বাধা দেয়।
আনপ্যাক করা এক্সটেনশনগুলির জন্য, CSP-তে লোকালহোস্টও অন্তর্ভুক্ত থাকে:
script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:* chrome-extension://abcdefghijklmopqrstuvwxyz/; object-src 'self';
যখন মূল অংশে কোনো কন্টেন্ট স্ক্রিপ্ট যুক্ত করা হয়, তখন পেজটির CSP (কন্টেন্ট স্ক্রিপ্ট পলিসি) প্রযোজ্য হয়।
সুরক্ষিত থাকুন
যদিও আইসোলেটেড ওয়ার্ল্ড এক ধরনের সুরক্ষা প্রদান করে, কন্টেন্ট স্ক্রিপ্ট ব্যবহার করলে একটি এক্সটেনশন এবং ওয়েব পেজ উভয়ের মধ্যেই দুর্বলতা তৈরি হতে পারে। যদি কন্টেন্ট স্ক্রিপ্ট কোনো আলাদা ওয়েবসাইট থেকে কন্টেন্ট গ্রহণ করে, যেমন fetch() কল করার মাধ্যমে, তবে তা ইনজেক্ট করার আগে ক্রস-সাইট স্ক্রিপ্টিং অ্যাটাকের বিরুদ্ধে কন্টেন্ট ফিল্টার করে নিতে সতর্ক থাকুন। "ম্যান-ইন-দ্য-মিডল" অ্যাটাক এড়ানোর জন্য শুধুমাত্র HTTPS-এর মাধ্যমেই যোগাযোগ করুন।
ক্ষতিকারক ওয়েব পেজগুলো ফিল্টার করতে ভুলবেন না। উদাহরণস্বরূপ, নিম্নলিখিত প্যাটার্নগুলো বিপজ্জনক এবং ম্যানিফেস্ট ভি৩-তে নিষিদ্ধ:
কন্টেন্ট-স্ক্রিপ্ট.জেএস
const data = document.getElementById("json-data"); // WARNING! Might be evaluating an evil script! const parsed = eval("(" + data + ")");
কন্টেন্ট-স্ক্রিপ্ট.জেএস
const elmt_id = ... // WARNING! elmt_id might be '); ... evil script ... //'! window.setTimeout("animate(" + elmt_id + ")", 200);
এর পরিবর্তে, এমন নিরাপদ এপিআই ব্যবহার করুন যেগুলো স্ক্রিপ্ট চালায় না:
কন্টেন্ট-স্ক্রিপ্ট.জেএস
const data = document.getElementById("json-data") // JSON.parse does not evaluate the attacker's scripts. const parsed = JSON.parse(data);
কন্টেন্ট-স্ক্রিপ্ট.জেএস
const elmt_id = ... // The closure form of setTimeout does not evaluate scripts. window.setTimeout(() => animate(elmt_id), 200);