कॉन्टेंट स्क्रिप्ट, वे फ़ाइलें होती हैं जो वेब पेजों के संदर्भ में चलती हैं. स्टैंडर्ड डॉक्यूमेंट ऑब्जेक्ट मॉडल (DOM) का इस्तेमाल करके, वे ब्राउज़र पर विज़िट किए गए वेब पेजों की जानकारी पढ़ सकते हैं, उनमें बदलाव कर सकते हैं, और अपने पैरंट एक्सटेंशन को जानकारी भेज सकते हैं.
कॉन्टेंट स्क्रिप्ट की सुविधाओं के बारे में जानकारी
कॉन्टेंट स्क्रिप्ट, अपने पैरंट एक्सटेंशन के इस्तेमाल किए गए Chrome API को ऐक्सेस कर सकती हैं. इसके लिए, उन्हें एक्सटेंशन के साथ मैसेज भेजने होंगे. वे chrome.runtime.getURL()
के साथ किसी एक्सटेंशन फ़ाइल के यूआरएल को भी ऐक्सेस कर सकते हैं और नतीजे का इस्तेमाल अन्य यूआरएल की तरह कर सकते हैं.
// Code for displaying EXTENSION_DIR/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
इसके अलावा, कॉन्टेंट स्क्रिप्ट इन Chrome API को सीधे तौर पर ऐक्सेस कर सकती है:
कॉन्टेंट स्क्रिप्ट, सीधे तौर पर दूसरे एपीआई को ऐक्सेस नहीं कर सकतीं.
अलग-अलग वर्ल्ड में काम करना
कॉन्टेंट स्क्रिप्ट अलग-अलग काम करती हैं. इससे कॉन्टेंट स्क्रिप्ट, पेज या अन्य कॉन्टेंट स्क्रिप्ट से कोई टकराव किए बिना, अपने JavaScript एनवायरमेंट में बदलाव कर सकती है.
कोई एक्सटेंशन, नीचे दिए गए उदाहरण जैसे कोड वाले वेब पेज में चल सकता है.
<html>
<button id="mybutton">click me</button>
<script>
var greeting = "hello, ";
var button = document.getElementById("mybutton");
button.person_name = "Bob";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
</script>
</html>
वह एक्सटेंशन, यहां दी गई कॉन्टेंट स्क्रिप्ट को इंजेक्ट कर सकता है.
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener("click", function() {
alert(greeting + button.person_name + ".");
}, false);
बटन दबाने पर, दोनों चेतावनियां दिखेंगी.
अलग-अलग वर्ल्ड में, कॉन्टेंट स्क्रिप्ट, एक्सटेंशन, और वेब पेज को दूसरों के बनाए गए किसी भी वैरिएबल या फ़ंक्शन को ऐक्सेस करने की अनुमति नहीं है. इससे कॉन्टेंट स्क्रिप्ट को ऐसी सुविधाएं चालू करने की सुविधा भी मिलती है जो वेब पेज के लिए उपलब्ध नहीं होनी चाहिए.
स्क्रिप्ट इंजेक्ट करना
कॉन्टेंट स्क्रिप्ट को प्रोग्राम के ज़रिए या एलान करके इंजेक्ट किया जा सकता है.
प्रोग्राम के हिसाब से इंजेक्ट करना
प्रोग्रामैटिक इंजेक्शन का इस्तेमाल उन कॉन्टेंट स्क्रिप्ट के लिए करें जिन्हें खास मौकों पर चलाना है.
प्रोग्राम के हिसाब से कॉन्टेंट दिखाने वाली स्क्रिप्ट इंजेक्ट करने के लिए, मेनिफ़ेस्ट में activeTab की अनुमति दें. इससे, चालू साइट के होस्ट को सुरक्षित ऐक्सेस मिलता है. साथ ही, टैब की अनुमति को कुछ समय के लिए ऐक्सेस किया जा सकता है. इससे, कॉन्टेंट स्क्रिप्ट को मौजूदा चालू टैब पर चलाया जा सकता है. इसके लिए, क्रॉस-ऑरिजिन अनुमतियों की जानकारी देने की ज़रूरत नहीं होती.
{
"name": "My extension",
...
"permissions": [
"activeTab"
],
...
}
कॉन्टेंट स्क्रिप्ट को कोड के तौर पर इंजेक्ट किया जा सकता है.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "changeColor"){
chrome.tabs.executeScript({
code: 'document.body.style.backgroundColor="orange"'
});
}
});
इसके अलावा, पूरी फ़ाइल को इंजेक्ट किया जा सकता है.
chrome.runtime.onMessage.addListener(
function(message, callback) {
if (message == "runContentScript"){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
}
});
एनोटेशन के ज़रिए इंजेक्ट करना
उन कॉन्टेंट स्क्रिप्ट के लिए, डिक्लेरेटिव इंजेक्शन का इस्तेमाल करें जिन्हें खास पेजों पर अपने-आप चलाया जाना चाहिए.
एलान करके इंजेक्ट की गई स्क्रिप्ट, मेनिफ़ेस्ट में "content_scripts"
फ़ील्ड में रजिस्टर की जाती हैं.
इनमें JavaScript फ़ाइलें, सीएसएस फ़ाइलें या दोनों शामिल हो सकती हैं. अपने-आप चलने वाली सभी कॉन्टेंट स्क्रिप्ट में, मैच पैटर्न की जानकारी होनी चाहिए.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"css": ["myStyles.css"],
"js": ["contentScript.js"]
}
],
...
}
नाम | टाइप | ब्यौरा |
---|---|---|
matches {: #matches } |
ज़रूरी है. इससे यह तय होता है कि इस कॉन्टेंट स्क्रिप्ट को किन पेजों में इंजेक्ट किया जाएगा. इन स्ट्रिंग के सिंटैक्स के बारे में ज़्यादा जानकारी के लिए, मैच पैटर्न देखें. साथ ही, यूआरएल को बाहर रखने के तरीके के बारे में जानने के लिए, मैच पैटर्न और ग्लोब देखें. | |
css {: #css } |
ज़रूरी नहीं. मैच होने वाले पेजों में इंजेक्ट की जाने वाली सीएसएस फ़ाइलों की सूची. ये इस क्रम में इंजेक्ट किए जाते हैं जिस क्रम में वे इस कलेक्शन में दिखते हैं. ऐसा, पेज के लिए कोई डीओएम बनाने या दिखाने से पहले किया जाता है. | |
js {: #js } |
ज़रूरी नहीं. मैच करने वाले पेजों में इंजेक्ट की जाने वाली JavaScript फ़ाइलों की सूची. इन्हें उसी क्रम में इंजेक्ट किया जाता है जिस क्रम में वे इस कलेक्शन में दिखते हैं. | |
match_about_blank {: #match_about_blank } |
बूलियन | ज़रूरी नहीं. क्या स्क्रिप्ट को about:blank फ़्रेम में इंजेक्ट करना चाहिए, जहां पैरंट या ओपनर फ़्रेम, matches में बताए गए किसी पैटर्न से मेल खाता हो. डिफ़ॉल्ट रूप से, यह false पर सेट होती है. |
मैच और ग्लोब को बाहर रखना
मैनिफ़ेस्ट रजिस्ट्रेशन में ये फ़ील्ड शामिल करके, पेज मैचिंग की सुविधा को पसंद के मुताबिक बनाया जा सकता है.
नाम | टाइप | ब्यौरा |
---|---|---|
exclude_matches {: #exclude_matches } |
ज़रूरी नहीं. उन पेजों को बाहर रखता है जिनमें इस कॉन्टेंट स्क्रिप्ट को इंजेक्ट किया जाना चाहिए. इन स्ट्रिंग के सिंटैक्स के बारे में ज़्यादा जानकारी के लिए, मैच पैटर्न देखें. | |
include_globs {: #include_globs } |
ज़रूरी नहीं. matches के बाद लागू किया जाता है, ताकि सिर्फ़ वे यूआरएल शामिल किए जा सकें जो इस ग्लोब से भी मैच करते हैं. @include Greasemonkey कीवर्ड को एमुलेट करने के लिए बनाया गया. |
|
exclude_globs {: #exclude_globs } |
ज़रूरी नहीं. इस ग्लोब से मैच होने वाले यूआरएल को बाहर रखने के लिए, matches के बाद लागू किया जाता है. @exclude Greasemonkey कीवर्ड को एमुलेट करने के लिए बनाया गया. |
कॉन्टेंट स्क्रिप्ट को किसी पेज में इंजेक्ट किया जाएगा, अगर उसका यूआरएल किसी matches
पैटर्न और किसी
include_globs
पैटर्न से मैच करता है. हालांकि, ऐसा तब ही होगा, जब यूआरएल exclude_matches
या
exclude_globs
पैटर्न से भी मैच न करता हो.
matches
प्रॉपर्टी ज़रूरी है. इसलिए, exclude_matches
, include_globs
, और exclude_globs
का इस्तेमाल सिर्फ़ यह तय करने के लिए किया जा सकता है कि किन पेजों पर असर पड़ेगा.
नीचे दिया गया एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को http://www.nytimes.com/ health में इंजेक्ट करेगा, लेकिन http://www.nytimes.com/ business में नहीं .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"js": ["contentScript.js"]
}
],
...
}
ग्लोब प्रॉपर्टी, मैच पैटर्न के मुकाबले अलग और ज़्यादा सुविधाजनक सिंटैक्स का इस्तेमाल करती हैं. स्वीकार की जाने वाली ग्लोब स्ट्रिंग, ऐसे यूआरएल होते हैं जिनमें "वाइल्डकार्ड" तारे के निशान और सवाल के निशान हो सकते हैं. तारे का निशान *, किसी भी लंबाई की किसी भी स्ट्रिंग से मैच करता है. इसमें खाली स्ट्रिंग भी शामिल है. वहीं, सवाल का निशान ? किसी भी एक वर्ण से मेल खाता है.
उदाहरण के लिए, ग्लोब http:// ??? .example.com/foo/ * इनमें से किसी भी चीज़ से मेल खाता है:
- http:// www .example.com/foo /bar
- http:// the .example.com/foo /
हालांकि, यह इनसे मेल नहीं खाता:
- http:// my .example.com/foo/bar
- http:// example .com/foo/
- http://www.example.com/foo
यह एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को http:/www.nytimes.com/ arts /index.html और http://www.nytimes.com/ jobs /index.html में इंजेक्ट करेगा, लेकिन http://www.nytimes.com/ sports /index.html में नहीं.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"include_globs": ["*nytimes.com/???s/*"],
"js": ["contentScript.js"]
}
],
...
}
यह एक्सटेंशन, कॉन्टेंट स्क्रिप्ट को http:// history .nytimes.com और http://.nytimes.com/ history में इंजेक्ट करेगा, लेकिन http:// science .nytimes.com या http://www.nytimes.com/ science में नहीं .
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
सही दायरा तय करने के लिए, इनमें से कोई एक, सभी या कुछ को शामिल किया जा सकता है.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"exclude_matches": ["*://*/*business*"],
"include_globs": ["*nytimes.com/???s/*"],
"exclude_globs": ["*science*"],
"js": ["contentScript.js"]
}
],
...
}
रनटाइम
run_at
फ़ील्ड से यह कंट्रोल किया जाता है कि वेब पेज में JavaScript फ़ाइलें कब इंजेक्ट की जाएं. "document_idle"
, पसंदीदा और डिफ़ॉल्ट फ़ील्ड है. हालांकि, ज़रूरत पड़ने पर इसे "document_start"
या
"document_end"
के तौर पर भी सेट किया जा सकता है.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
नाम | टाइप | ब्यौरा |
---|---|---|
document_idle {: #document_idle } |
स्ट्रिंग | ज़्यादा पसंद आया. जब भी हो सके, "document_idle" का इस्तेमाल करें.ब्राउज़र, "document_end" और windowonload इवेंट के ट्रिगर होने के तुरंत बाद, स्क्रिप्ट इंजेक्ट करने के लिए समय चुनता है. इंजेक्शन का सटीक समय इस बात पर निर्भर करता है कि दस्तावेज़ कितना जटिल है और उसे लोड होने में कितना समय लग रहा है. साथ ही, इसे पेज लोड होने की स्पीड के लिए ऑप्टिमाइज़ किया जाता है."document_idle" पर चल रही कॉन्टेंट स्क्रिप्ट को window.onload इवेंट के लिए सुनने की ज़रूरत नहीं है. यह गारंटी है कि वे डीओएम पूरा होने के बाद चलेंगी. अगर किसी स्क्रिप्ट को window.onload के बाद ज़रूर चलाना है, तो एक्सटेंशन यह देख सकता है कि document.readyState प्रॉपर्टी का इस्तेमाल करके, onload पहले से ट्रिगर हो चुका है या नहीं. |
document_start {: #document_start } |
स्ट्रिंग | स्क्रिप्ट, css की किसी भी फ़ाइल के बाद इंजेक्ट की जाती हैं. हालांकि, किसी भी अन्य डीओएम के बनने या किसी अन्य स्क्रिप्ट के चलने से पहले ऐसा किया जाता है. |
document_end {: #document_end } |
स्ट्रिंग | स्क्रिप्ट, DOM के पूरा होने के तुरंत बाद इंजेक्ट की जाती हैं. हालांकि, इमेज और फ़्रेम जैसे सब-रिसॉर्स लोड होने से पहले ऐसा किया जाता है. |
फ़्रेम तय करना
"all_frames"
फ़ील्ड की मदद से, एक्सटेंशन यह तय कर सकता है कि JavaScript और सीएसएस फ़ाइलों को, यूआरएल की तय की गई ज़रूरी शर्तों से मैच करने वाले सभी फ़्रेम में इंजेक्ट किया जाए या सिर्फ़ टैब के सबसे ऊपर वाले फ़्रेम में.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
...
}
नाम | टाइप | ब्यौरा |
---|---|---|
all_frames {: #all_frames } |
बूलियन | ज़रूरी नहीं. डिफ़ॉल्ट रूप से false पर सेट होता है. इसका मतलब है कि सिर्फ़ सबसे ऊपर वाले फ़्रेम से मैच किया जाएगा.true तय करने पर, यह सभी फ़्रेम में इंजेक्ट हो जाएगा. भले ही, फ़्रेम टैब में सबसे ऊपर न हो. हर फ़्रेम की जांच, यूआरएल की ज़रूरी शर्तों के हिसाब से अलग से की जाती है. अगर यूआरएल की ज़रूरी शर्तें पूरी नहीं होती हैं, तो इसे चाइल्ड फ़्रेम में इंजेक्ट नहीं किया जाएगा. |
एम्बेड किए गए पेज से बातचीत
हालांकि, कॉन्टेंट स्क्रिप्ट और उन्हें होस्ट करने वाले पेजों के लागू होने के माहौल एक-दूसरे से अलग होते हैं, लेकिन वे पेज के डीओएम का ऐक्सेस शेयर करते हैं. अगर पेज को कॉन्टेंट स्क्रिप्ट या कॉन्टेंट स्क्रिप्ट के ज़रिए एक्सटेंशन से बातचीत करनी है, तो उसे शेयर किए गए DOM के ज़रिए ऐसा करना होगा.
उदाहरण के लिए, window.postMessage
का इस्तेमाल करके:
var port = chrome.runtime.connect();
window.addEventListener("message", function(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);
document.getElementById("theButton").addEventListener("click",
function() {
window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*");
}, false);
एक्सटेंशन वाला पेज, example.html, खुद को मैसेज पोस्ट करता है. इस मैसेज को कॉन्टेंट स्क्रिप्ट रोकती है और उसकी जांच करती है. इसके बाद, उसे एक्सटेंशन प्रोसेस में पोस्ट किया जाता है. इस तरह, पेज, एक्सटेंशन की प्रोसेस के लिए संपर्क की लाइन बनाता है. इसी तरह, इसे वापस भी लाया जा सकता है.
खाता सुरक्षित रखना
अलग-अलग वर्ल्ड, सुरक्षा की एक लेयर देते हैं. हालांकि, कॉन्टेंट स्क्रिप्ट का इस्तेमाल करने से, एक्सटेंशन और वेब पेज में कमज़ोरियां पैदा हो सकती हैं. अगर कॉन्टेंट स्क्रिप्ट को किसी दूसरी वेबसाइट से कॉन्टेंट मिलता है, जैसे कि XMLHttpRequest बनाना, तो उसे इंजेक्ट करने से पहले, कॉन्टेंट क्रॉस-साइट स्क्रिप्टिंग अटैक को फ़िल्टर करने में सावधानी बरतें. "man-in-the-middle" हमलों से बचने के लिए, सिर्फ़ एचटीटीपीएस पर कम्यूनिकेट करें.
नुकसान पहुंचाने वाले वेब पेजों को फ़िल्टर करना न भूलें. उदाहरण के लिए, ये पैटर्न खतरनाक हैं:
var data = document.getElementById("json-data")
// WARNING! Might be evaluating an evil script!
var parsed = eval("(" + data + ")")
var elmt_id = ...
// WARNING! elmt_id might be "); ... evil script ... //"!
window.setTimeout("animate(" + elmt_id + ")", 200);
इसके बजाय, ऐसे सुरक्षित एपीआई इस्तेमाल करें जो स्क्रिप्ट नहीं चलाते:
var data = document.getElementById("json-data")
// JSON.parse does not evaluate the attacker's scripts.
var parsed = JSON.parse(data);
var elmt_id = ...
// The closure form of setTimeout does not evaluate scripts.
window.setTimeout(function() {
animate(elmt_id);
}, 200);