Chrome एक्सटेंशन में eval का इस्तेमाल करना

Chrome का एक्सटेंशन सिस्टम, डिफ़ॉल्ट रूप से काफ़ी सख्त डिफ़ॉल्ट कॉन्टेंट की सुरक्षा के बारे में नीति (सीएसपी) लागू करता है. नीति की पाबंदियां आसान हैं: स्क्रिप्ट को लाइन से बाहर की ओर करके, addEventListener का इस्तेमाल करने के लिए JavaScript फ़ाइलों, इनलाइन इवेंट हैंडलर को बदलना ज़रूरी है, और eval() बंद किया गया. Chrome ऐप्स की नीति और भी सख्त नीति है और हम सुरक्षा से काफ़ी खुश हैं प्रॉपर्टी, जो इन नीतियों से मिलती हैं.

हालांकि, हम जानते हैं कि परफ़ॉर्मेंस को ऑप्टिमाइज़ करने और आसानी से एक्सप्रेशन बनाने के लिए, कई लाइब्रेरी eval() और eval जैसे कंस्ट्रक्ट का इस्तेमाल करती हैं. जैसे, new Function(). टेंप्लेट बनाने वाली लाइब्रेरी ख़ास तौर पर इस स्टाइल के लागू होने की संभावना ज़्यादा होती है. कुछ फ़्रेमवर्क (जैसे, Angular.js) में सीएसपी पहले से काम करता है. हालांकि, कई लोकप्रिय फ़्रेमवर्क को अब तक ऐसे तरीके के साथ अपडेट नहीं किया गया है जो एक्सटेंशन के eval-लेस वर्ल्ड के साथ काम करता हो. इसलिए, इस फ़ंक्शन के लिए सहायता टीम को हटाने से यह ज़्यादा साबित हुआ है ज़्यादा समस्याएं होती हैं.

इस दस्तावेज़ में, सैंडबॉक्सिंग को सुरक्षित तरीके के तौर पर पेश किया गया है. इससे, सुरक्षा से समझौता किए बिना, इन लाइब्रेरी को अपने प्रोजेक्ट में शामिल किया जा सकता है. संक्षिप्तता के लिए, हम शुरू से अंत तक एक्सटेंशन शब्द का उपयोग करेंगे, लेकिन यह सिद्धांत समान रूप से ऐप्लिकेशन पर लागू होता है.

सैंडबॉक्स क्यों?

एक्सटेंशन के अंदर eval खतरनाक है, क्योंकि इसे लागू करने वाले कोड के पास एक्सटेंशन में मौजूद सभी चीज़ों का ऐक्सेस होता है एक्सटेंशन की उच्च-अनुमति एनवायरमेंट है. ऐसे कई दमदार chrome.* API उपलब्ध हैं जो उपयोगकर्ता की सुरक्षा और निजता पर गंभीर असर डाल सकता है; डेटा को आसानी से बाहर निकाला जाना हमारी सबसे कम चिंता है. हमारा समाधान एक सैंडबॉक्स की तरह है. इसमें eval, एक्सटेंशन का डेटा या एक्सटेंशन के ज़्यादा वैल्यू वाले एपीआई का इस्तेमाल करते हैं. कोई डेटा नहीं, कोई एपीआई नहीं, कोई समस्या नहीं.

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

सैंडबॉक्स बनाना और उसका इस्तेमाल करना.

यदि आप सीधे कोड में जाना चाहते हैं, तो कृपया सैंडबॉक्सिंग नमूना एक्सटेंशन लें और बंद है. यह हैंडलबार के ऊपर बने छोटे से मैसेजिंग एपीआई का उदाहरण है आपको एक लाइब्रेरी बनानी होगी. इसमें आपको काम शुरू करने से जुड़ी हर चीज़ मिल जाएगी. उन लोगों के लिए जिन्हें आइए, उस सैंपल के बारे में यहाँ जानते हैं.

मेनिफ़ेस्ट में फ़ाइलों की सूची

जिस फ़ाइल को सैंडबॉक्स में चलाना है उसे एक्सटेंशन मेनिफ़ेस्ट में एक sandbox प्रॉपर्टी. यह एक ज़रूरी चरण है और इसे भूलना आसान है. इसलिए, कृपया दोबारा आपकी सैंडबॉक्स फ़ाइल, मेनिफ़ेस्ट में मौजूद होती है. इस सैंपल में, हम सही तरीके से फ़ाइल को सैंडबॉक्स कर रहे हैं "sandbox.html" नाम दिया गया है. मेनिफ़ेस्ट एंट्री इस तरह दिखती है:

{
  ...,
  "sandbox": {
     "pages": ["sandbox.html"]
  },
  ...
}

सैंडबॉक्स की गई फ़ाइल लोड करना

सैंडबॉक्स की गई फ़ाइल के साथ कुछ दिलचस्प करने के लिए, हमें उसे ऐसे कॉन्टेक्स्ट में लोड करना होगा जहां इसे एक्सटेंशन के कोड से ऐक्सेस किया जा सके. यहां sandbox.html लोड कर दिया गया है एक्सटेंशन का इवेंट पेज (eventpage.html) किसी iframe के ज़रिए. eventpage.js में ऐसा कोड होता है जो पेज पर iframe को ढूंढकर और उसके contentWindow पर postMessage तरीके को लागू करके, ब्राउज़र ऐक्शन पर क्लिक किए जाने पर सैंडबॉक्स में मैसेज भेजता है. मैसेज एक ऑब्जेक्ट है इसमें दो प्रॉपर्टी शामिल हैं: context और command. हम जल्द ही इन दोनों के बारे में बात करेंगे.

chrome.browserAction.onClicked.addListener(function() {
 var iframe = document.getElementById('theFrame');
 var message = {
   command: 'render',
   context: {thing: 'world'}
 };
 iframe.contentWindow.postMessage(message, '*');
});
postMessage एपीआई के बारे में सामान्य जानकारी के लिए, MDN पर postMessage दस्तावेज़ देखें. यह पूरी तरह से सही है और इसे पढ़ना ज़रूरी है. खास तौर पर, ध्यान दें कि डेटा को सिर्फ़ तब एक से दूसरी जगह भेजा जा सकता है, जब उसे सीरियल किया जा सकता हो. उदाहरण के लिए, फ़ंक्शन नहीं.

कुछ खतरनाक करना

sandbox.html के लोड होने पर, यह हैंडलबार लाइब्रेरी को लोड करता है और इनलाइन बनाता है और उसे कंपाइल करता है टेंप्लेट को हैंडलबार के सुझावों के तौर पर देखें:

<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>Hello, !</h1>
  </div>
</script>
<script>
  var templates = [];
  var source = document.getElementById('hello-world-template').innerHTML;
  templates['hello'] = Handlebars.compile(source);
</script>

यह काम करता है! भले ही Handlebars.compile, new Function का इस्तेमाल करना बंद कर देता है, लेकिन कुछ न करें जैसा कि उम्मीद है, और आखिर में हमें templates['hello'] में एक कंपाइल किया गया टेंप्लेट मिलता है.

नतीजा वापस भेजना

हम निर्देशों को स्वीकार करने वाला मैसेज लिसनर सेट अप करके, इस टेंप्लेट को इस्तेमाल के लिए उपलब्ध कराएंगे इवेंट पेज से. हम command का इस्तेमाल करके यह तय करेंगे कि क्या करना है. इसमें, सिर्फ़ रेंडर करने के अलावा, टेंप्लेट बनाने जैसे और भी काम किए जा सकते हैं. शायद उन्हें कुछ जगहों पर मैनेज किया जा रहा है तरीके से मेल खाना चाहिए?) और रेंडरिंग के लिए context को सीधे टेंप्लेट में पास कर दिया जाएगा. रेंडर किया गया एचटीएमएल, इवेंट पेज पर वापस भेज दिया जाएगा, ताकि एक्सटेंशन बाद में इसका इस्तेमाल कर सके:

<script>
  window.addEventListener('message', function(event) {
    var command = event.data.command;
    var name = event.data.name || 'hello';
    switch(command) {
      case 'render':
        event.source.postMessage({
          name: name,
          html: templates[name](event.data.context)
        }, event.origin);
        break;

      // case 'somethingElse':
      //   ...
    }
  });
</script>

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

इस तरीके से टेंप्लेट बनाने का तरीका आसान है. हालांकि, इसमें टेंप्लेट के अलावा और भी चीज़ें शामिल हो सकती हैं. कोई भी ऐसे कोड को सैंडबॉक्स किया जा सकता है जो कॉन्टेंट की सुरक्षा के बारे में सख्त नीति के तहत काम नहीं करता; इंच नहीं, यह आपके एक्सटेंशन के उन कॉम्पोनेंट को सैंडबॉक्स करना अक्सर मददगार होता है जो क्रम से सही तरीके से चलेंगे ताकि आपके प्रोग्राम के हर हिस्से को, उसके लिए ज़रूरी अधिकारों के सबसे छोटे सेट तक सीमित किया जा सके सही तरीके से एक्ज़ीक्यूट होता है. Google का राइटिंग वेब ऐप्लिकेशन और Chrome एक्सटेंशन प्रज़ेंटेशन I/O 2012 में, इन तकनीक के इस्तेमाल के कुछ अच्छे उदाहरण दिए गए हैं और यह आपके लिए समय.