javascript - एक सामग्री स्क्रिप्ट का उपयोग कर पृष्ठ संदर्भ में कोड डालें




google-chrome google-chrome-extension (4)

एकमात्र वस्तु लापता पंक्ति डब्ल्यू के उत्कृष्ट उत्तर से छिपा हुआ यह है कि इंजेक्शन स्क्रिप्ट से सामग्री स्क्रिप्ट और इसके विपरीत (विशेष रूप से यदि आपके पास ऐसी वस्तुएं हैं जिन्हें स्ट्रिंग नहीं किया जा सकता है) से कॉल करना है।

इंजेक्शन या आपकी सामग्री स्क्रिप्ट में एक ईवेंट श्रोता जोड़ें:

document.addEventListener('yourCustomEvent', function (e)
{
  var data=e.detail;
  console.log("received "+data);
});

दूसरी ओर (सामग्री या इंजेक्शन स्क्रिप्ट) घटना को कॉल करें:

var data="anything";

// updated: this works with Chrome 30:
var evt=document.createEvent("CustomEvent");
evt.initCustomEvent("yourCustomEvent", true, true, data);
document.dispatchEvent(evt);

// the following stopped working in Chrome 30 (Windows), detail was 
// not received in the listener:
// document.dispatchEvent(new CustomEvent('yourCustomEvent', { detail: data }));

मैं सीख रहा हूं कि क्रोम एक्सटेंशन कैसे बनाएं। मैंने अभी YouTube घटनाओं को पकड़ने के लिए एक विकसित करना शुरू कर दिया है। मैं इसे यूट्यूब फ्लैश प्लेयर के साथ उपयोग करना चाहता हूं (बाद में मैं इसे एचटीएमएल 5 के साथ संगत बनाने की कोशिश करूंगा)।

manifest.json:

{
    "name": "MyExtension",
    "version": "1.0",
    "description": "Gotta catch Youtube events!",
    "permissions": ["tabs", "http://*/*"],
    "content_scripts" : [{
        "matches" : [ "www.youtube.com/*"],
        "js" : ["myScript.js"]
    }]
}

myScript.js:

function state() { console.log("State Changed!"); }
var player = document.getElementById("movie_player");
player.addEventListener("onStateChange", "state");
console.log("Started!");

समस्या यह है कि कंसोल मुझे "शुरू हुआ!" देता है , लेकिन कोई "राज्य बदल गया है!" जब मैं यूट्यूब वीडियो चलाता / रोकता हूं।

जब यह कोड कंसोल में रखा जाता है, तो यह काम करता है। मैं क्या गलत कर रहा हूं?


कंटेंट स्क्रिप्ट में, मैं हेडलर के अंदर 'ऑनमेसेज' हैंडलर को बांधता हूं, जो कोड को निष्पादित करने के लिए eval, सिर पर स्क्रिप्ट टैग जोड़ता है। बूथ सामग्री स्क्रिप्ट में मैं ऑनमेज हैंडलर का भी उपयोग करता हूं, इसलिए मुझे दो तरह का संचार मिलता है। क्रोम डॉक्स

//Content Script

var pmsgUrl = chrome.extension.getURL('pmListener.js');
$("head").first().append("<script src='"+pmsgUrl+"' type='text/javascript'></script>");


//Listening to messages from DOM
window.addEventListener("message", function(event) {
  console.log('CS :: message in from DOM', event);
  if(event.data.hasOwnProperty('cmdClient')) {
    var obj = JSON.parse(event.data.cmdClient);
    DoSomthingInContentScript(obj);
 }
});

pmListener.js एक पोस्ट संदेश यूआरएल श्रोता है

//pmListener.js

//Listen to messages from Content Script and Execute Them
window.addEventListener("message", function (msg) {
  console.log("im in REAL DOM");
  if (msg.data.cmnd) {
    eval(msg.data.cmnd);
  }
});

console.log("injected To Real Dom");

इस तरह, मैं सीएस से रियल डोम के बीच 2 तरह का संचार कर सकता हूं। उदाहरण के लिए यह बहुत उपयोगी है यदि आपको webscoket घटनाओं को सुनने की आवश्यकता है, या स्मृति चर या घटनाओं में से किसी को भी।


यदि आप टेक्स्ट की बजाय शुद्ध फ़ंक्शन इंजेक्ट करना चाहते हैं, तो आप इस विधि का उपयोग कर सकते हैं:

function inject(){
    document.body.style.backgroundColor = 'blue';
}

// this includes the function as text and the barentheses make it run itself.
var actualCode = "("+inject+")()"; 

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

और आप कार्यों में पैरामीटर (दुर्भाग्य से कोई ऑब्जेक्ट्स और सरणी को स्ट्रिंग किया जा सकता है) पास कर सकते हैं। इसे नंगे में जोड़ें, जैसे:

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

// this includes the function as text and the barentheses make it run itself.
var color = 'yellow';
var actualCode = "("+inject+")("+color+")"; 


सामग्री स्क्रिप्ट को "पृथक दुनिया" वातावरण में निष्पादित किया जाता है । आपको पृष्ठ में अपने state() विधि को इंजेक्ट करना होगा।

जब आप स्क्रिप्ट में एक chrome.* एपीआई का उपयोग करना चाहते हैं, तो आपको इस जवाब में वर्णित एक विशेष ईवेंट हैंडलर लागू करना होगा: क्रोम एक्सटेंशन - जीमेल के मूल संदेश को पुनः प्राप्त करना ।

अन्यथा, यदि आपको chrome.* का उपयोग नहीं करना है chrome.* एपीआई, मैं दृढ़ता से अनुशंसा करता हूं कि पेज में अपने सभी जेएस कोड को एक <script> टैग जोड़कर इंजेक्ट करें:

विषय - सूची

  • विधि 1: एक और फ़ाइल इंजेक्ट करें
  • विधि 2: एम्बेडेड कोड इंजेक्ट करें
  • विधि 2 बी: एक फ़ंक्शन का उपयोग करना
  • विधि 3: एक इनलाइन घटना का उपयोग करना
  • इंजेक्शन कोड में गतिशील मान

विधि 1: एक और फ़ाइल इंजेक्ट करें

आपके पास बहुत सी कोड होने पर यह सबसे आसान / सर्वोत्तम तरीका है। script.js कहें, अपने एक्सटेंशन में फ़ाइल में अपना वास्तविक जेएस कोड शामिल करें। फिर अपनी सामग्री स्क्रिप्ट को निम्नानुसार दें (यहां बताया गया है: Google Chome "एप्लिकेशन शॉर्टकट" कस्टम जावास्क्रिप्ट ):

var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

नोट: यदि आप इस विधि का उपयोग करते हैं, तो इंजेक्शन वाली script.js फ़ाइल को "web_accessible_resources" सेक्शन में जोड़ा जाना चाहिए ( example )। यदि आप नहीं करते हैं, तो क्रोम आपकी स्क्रिप्ट लोड करने से इनकार कर देगा और कंसोल में निम्न त्रुटि प्रदर्शित करेगा:

क्रोम-एक्सटेंशन का लोड अस्वीकार करना: // [EXTENSIONID] /script.js। विस्तार से बाहर पृष्ठों द्वारा लोड किए जाने के लिए संसाधनों को web_accessible_resources मेनिफेस्ट कुंजी में सूचीबद्ध होना चाहिए।

विधि 2: एम्बेडेड कोड इंजेक्ट करें

यह विधि तब उपयोगी होती है जब आप कोड का एक छोटा टुकड़ा जल्दी से चलाना चाहते हैं। (यह भी देखें: क्रोम एक्सटेंशन के साथ फेसबुक हॉटकी को कैसे अक्षम करें? )।

var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;

var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

नोट: टेम्पलेट अक्षर केवल क्रोम 41 और उसके बाद में समर्थित हैं। यदि आप क्रोम 40- में विस्तार करना चाहते हैं, तो इसका उपयोग करें:

var actualCode = ['/* Code here. Example: */' + 'alert(0);',
                  '// Beware! This array have to be joined',
                  '// using a newline. Otherwise, missing semicolons',
                  '// or single-line comments (//) will mess up your',
                  '// code ----->'].join('\n');

विधि 2 बी: एक फ़ंक्शन का उपयोग करना

कोड के एक बड़े हिस्से के लिए, स्ट्रिंग को उद्धृत करना संभव नहीं है। सरणी का उपयोग करने के बजाय, एक फ़ंक्शन का उपयोग किया जा सकता है, और स्ट्रिंग किया गया:

var actualCode = '(' + function() {
    // All code is executed in a local scope.
    // For example, the following does NOT overwrite the global `alert` method
    var alert = null;
    // To overwrite a global variable, prefix `window`:
    window.alert = null;
} + ')();';
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

यह विधि काम करती है, क्योंकि स्ट्रिंग्स और फ़ंक्शन पर + ऑपरेटर सभी ऑब्जेक्ट्स को स्ट्रिंग में परिवर्तित करता है। यदि आप कोड को एक से अधिक बार उपयोग करने का इरादा रखते हैं, तो कोड पुनरावृत्ति से बचने के लिए फ़ंक्शन बनाना बुद्धिमानी है। एक कार्यान्वयन इस तरह दिख सकता है:

function injectScript(func) {
    var actualCode = '(' + func + ')();'
    ...
}
injectScript(function() {
   alert("Injected script");
});

नोट: चूंकि फ़ंक्शन को क्रमबद्ध किया गया है, मूल दायरा, और सभी बाध्य गुण खो गए हैं!

var scriptToInject = function() {
    console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output:  "undefined"

विधि 3: एक इनलाइन घटना का उपयोग करना

कभी-कभी, आप तुरंत कुछ कोड चलाने के लिए चाहते हैं, उदाहरण के लिए <head> तत्व बनने से पहले कुछ कोड चलाने के लिए। यह textContent साथ <script> टैग डालने से किया जा सकता है (विधि textContent बी देखें)।

एक विकल्प, लेकिन अनुशंसित नहीं है इनलाइन घटनाओं का उपयोग करना। यह अनुशंसित नहीं है क्योंकि यदि पृष्ठ एक सामग्री सुरक्षा नीति को परिभाषित करता है जो इनलाइन स्क्रिप्ट को रोकता है, तो इनलाइन ईवेंट श्रोताओं को अवरुद्ध कर दिया जाता है। विस्तार से इंजेक्शन वाली इनलाइन स्क्रिप्ट, दूसरी तरफ, अभी भी चलती हैं। यदि आप अभी भी इनलाइन घटनाओं का उपयोग करना चाहते हैं, तो यह है कि:

var actualCode = '// Some code example \n' + 
                 'console.log(document.documentElement.outerHTML);';

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

नोट: यह विधि मानती है कि कोई अन्य वैश्विक ईवेंट श्रोताओं नहीं हैं जो reset ईवेंट को संभालते हैं। यदि ऐसा है, तो आप अन्य वैश्विक घटनाओं में से एक भी चुन सकते हैं। बस जावास्क्रिप्ट कंसोल (एफ 12) खोलें, document.documentElement.on टाइप document.documentElement.on , और उपलब्ध घटनाओं को चुनें।

इंजेक्शन कोड में गतिशील मान

कभी-कभी, आपको इंजेक्शन फ़ंक्शन में एक मनमाना चर पारित करने की आवश्यकता होती है। उदाहरण के लिए:

var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
    alert(GREETING + NAME);
};

इस कोड को इंजेक्ट करने के लिए, आपको चर के रूप में चर के रूप में चर के रूप में चर को पारित करने की आवश्यकता है। इसे सही ढंग से कार्यान्वित करना सुनिश्चित करें! निम्नलिखित काम नहीं करेंगे:

var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi I'm,Rob)";
//                                                 ^^^^^^ ^^^ No string literals!

समाधान तर्क पारित करने से पहले JSON.stringify का उपयोग करना है। उदाहरण:

var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';

यदि आपके पास कई चर हैं, तो पठनीयता में सुधार के लिए JSON.stringify का उपयोग करना JSON.stringify है:

...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';




content-script