सभी एपीआई में उपयोगकर्ता की गतिविधि को एक जैसा बनाना

Mustaq Ahmed
Joe Medley
Joe Medley

नुकसान पहुंचाने वाली स्क्रिप्ट को पॉप-अप, स्क्रीन पर पूरा विज्ञापन दिखाने की सुविधा वगैरह जैसे संवेदनशील एपीआई का गलत इस्तेमाल करने से रोकने के लिए, ब्राउज़र उपयोगकर्ता के ऐक्टिवेशन की मदद से उन एपीआई के ऐक्सेस को कंट्रोल करते हैं. उपयोगकर्ता चालू होने का मतलब, उपयोगकर्ता की कार्रवाइयों के हिसाब से ब्राउज़िंग सेशन की स्थिति से है: "चालू" स्थिति का मतलब आम तौर पर यह है कि उपयोगकर्ता फ़िलहाल पेज से इंटरैक्ट कर रहा है या पेज लोड होने के बाद से कोई इंटरैक्शन पूरा कर चुका है. उपयोगकर्ता के जेस्चर, एक ही आइडिया के लिए इस्तेमाल किया जाने वाला लोकप्रिय शब्द है. हालांकि, यह गलतफ़हमी पैदा करता है. उदाहरण के लिए, उपयोगकर्ता के स्वाइप या फ़्लिक करने से कोई पेज चालू नहीं होता. इसलिए, स्क्रिप्ट के हिसाब से, इसे उपयोगकर्ता ऐक्टिवेशन नहीं माना जाता.

फ़िलहाल, मुख्य ब्राउज़र में उपयोगकर्ता चालू करने की सुविधा, चालू करने की ज़रूरी शर्त वाले एपीआई को अलग-अलग तरीके से कंट्रोल करती है. Chrome में, इसे लागू करने के लिए टोकन पर आधारित मॉडल का इस्तेमाल किया गया था. हालांकि, यह मॉडल, ऐक्टिवेशन के लिए ज़रूरी शर्तें पूरी करने वाले सभी एपीआई के लिए एक जैसा व्यवहार तय करने के लिए बहुत जटिल था. उदाहरण के लिए, Chrome में postMessage() और setTimeout() कॉल के ज़रिए, ऐक्टिवेशन के लिए ज़रूरी शर्तें पूरी करने वाले एपीआई को पूरी तरह ऐक्सेस करने की अनुमति दी जा रही थी. साथ ही, Promises, XHR, गेमपैड इंटरैक्शन वगैरह के साथ उपयोगकर्ता ऐक्टिवेशन काम नहीं कर रहा था. ध्यान दें कि इनमें से कुछ गड़बड़ियां, लंबे समय से मौजूद हैं.

Chrome के वर्शन 72 में, उपयोगकर्ता चालू करने की सुविधा का वर्शन 2 उपलब्ध है. इससे, चालू करने की ज़रूरी शर्तें पूरी करने वाले सभी एपीआई के लिए, उपयोगकर्ता चालू करने की सुविधा पूरी तरह से उपलब्ध हो जाती है. इससे ऊपर बताई गई समस्याओं के साथ-साथ, MessageChannels जैसी कुछ और समस्याएं भी हल हो जाएंगी. हमें उम्मीद है कि इससे उपयोगकर्ता ऐक्टिवेशन के लिए वेब डेवलपमेंट आसान हो जाएगा. इसके अलावा, नए तरीके से लागू करने पर, नए स्पेसिफ़िकेशन के लिए रेफ़रंस लागू करने का विकल्प मिलता है. इसका मकसद, लंबे समय में सभी ब्राउज़र को एक साथ लाना है.

उपयोगकर्ता चालू करने की सुविधा का दूसरा वर्शन कैसे काम करता है?

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

ध्यान दें कि उपयोगकर्ता के ऐक्टिवेशन पर आधारित अलग-अलग एपीआई, उपयोगकर्ता के ऐक्टिवेशन पर अलग-अलग तरीकों से काम करते हैं. नया एपीआई, एपीआई के हिसाब से इनमें से किसी भी व्यवहार में बदलाव नहीं कर रहा है. उदाहरण के लिए, उपयोगकर्ता के हर ऐक्टिवेशन के लिए सिर्फ़ एक पॉप-अप दिखाने की अनुमति है, क्योंकि window.open(), उपयोगकर्ता ऐक्टिवेशन को पहले की तरह ही इस्तेमाल करता है. Navigator.prototype.vibrate() तब तक काम करता रहेगा, जब तक किसी फ़्रेम (या उसके किसी सबफ़्रेम) पर उपयोगकर्ता ऐक्शन हुआ हो वगैरह.

क्या बदल रहा है?

  • उपयोगकर्ता ऐक्टिवेशन वर्शन 2, फ़्रेम की सीमाओं के बीच उपयोगकर्ता ऐक्टिवेशन की जानकारी को आधिकारिक तौर पर दिखाता है: किसी फ़्रेम के साथ उपयोगकर्ता के इंटरैक्शन से, अब उसमें मौजूद सभी फ़्रेम (और सिर्फ़ वे फ़्रेम) चालू हो जाएंगे. भले ही, वे किसी भी सोर्स से हों. (Chrome 72 में, हमने एक ही ऑरिजिन वाले सभी फ़्रेम के लिए, विज्ञापन दिखने की सुविधा को बढ़ाने के लिए कुछ समय के लिए एक तरीका अपनाया है. जब हमारे पास उप-फ़्रेम में उपयोगकर्ता के ऐक्टिवेशन को साफ़ तौर पर पास करने का तरीका होगा, तब हम इस तरीके को हटा देंगे.)
  • जब किसी चालू फ़्रेम से, ऐक्टिवेशन-गेट वाले एपीआई को किसी इवेंट हैंडलर कोड के बाहर से कॉल किया जाता है, तो यह तब तक काम करेगा, जब तक उपयोगकर्ता ऐक्टिवेशन की स्थिति "चालू" रहेगी. उदाहरण के लिए, जब उसकी समयसीमा खत्म न हुई हो और उसे इस्तेमाल न किया गया हो. उपयोगकर्ता ऐक्टिवेशन के वर्शन 2 से पहले, यह बिना किसी शर्त के काम नहीं करता था.
  • समयसीमा खत्म होने के अंतराल के दौरान, उपयोगकर्ता के कई ऐसे इंटरैक्शन जो इस्तेमाल नहीं किए गए हैं वे आखिरी इंटरैक्शन से जुड़े एक ही ऐक्टिवेशन में जुड़ जाते हैं.

ऐक्टिवेशन-गेट वाले एपीआई में एक जैसी सुविधाओं के उदाहरण

यहां पॉप-अप विंडो (window.open() का इस्तेमाल करके खोली गई) के दो उदाहरण दिए गए हैं. इनसे पता चलता है कि उपयोगकर्ता चालू करने की सुविधा के वर्शन 2 की मदद से, चालू करने की ज़रूरी शर्तों वाले एपीआई के व्यवहार को कैसे एक जैसा बनाया जाता है.

चेन किए गए setTimeout() कॉल

यह उदाहरण, हमारे setTimeout() डेमो से लिया गया है. अगर कोई click हैंडलर एक सेकंड के अंदर पॉप-अप खोलने की कोशिश करता है, तो उम्मीद है कि वह ऐसा कर पाएगा. भले ही, कोड में देरी को "कंपोज़" करने का तरीका कुछ भी हो. उपयोगकर्ता चालू करने की सुविधा का वर्शन 2, इस उम्मीद को पूरा करता है. इसलिए, यहां दिए गए हर इवेंट हैंडलर, click पर एक पॉप-अप खोलता है (100 मिलीसेकंड की देरी के साथ):

function popupAfter100ms() {
  setTimeout(callWindowOpen, 100);
}

function asyncPopupAfter100ms() {
  setTimeout(popupAfter100ms, 0);
}

someButton.addEventListener('click', popupAfter100ms);
someButton.addEventListener('click', asyncPopupAfter100ms);

User Activation v2 के बिना, दूसरा इवेंट हैंडलर उन सभी ब्राउज़र में काम नहीं करता जिनकी हमने जांच की है. (कुछ मामलों में पहला तरीका भी काम नहीं करता.)

क्रॉस-डोमेन postMessage() कॉल

यहां हमारे postMessage() डेमो का एक उदाहरण दिया गया है. मान लें कि किसी क्रॉस-ऑरिजिन सबफ़्रेम में मौजूद click हैंडलर, सीधे पैरंट फ़्रेम में दो मैसेज भेजता है. पैरंट फ़्रेम को इनमें से कोई एक मैसेज मिलने पर, पॉप-अप खोलना चाहिए (दोनों नहीं):

// Parent frame code
window.addEventListener('message', e => {
  if (e.data === 'open_popup' && e.origin === child_origin)
    window.open('about:blank');
});

// Child frame code:
someButton.addEventListener('click', () => {
  parent.postMessage('hi_there', parent_origin);
  parent.postMessage('open_popup', parent_origin);
});

उपयोगकर्ता सक्रियता के वर्शन 2 के बिना, पैरंट फ़्रेम दूसरा मैसेज मिलने पर पॉप-अप नहीं खोल सकता. अगर पहला मैसेज किसी दूसरे क्रॉस-ऑरिजिन फ़्रेम से "चेन" किया गया है, तो भी वह मैसेज नहीं भेजा जा सकेगा. दूसरे शब्दों में, अगर मैसेज पाने वाला पहला व्यक्ति उसे किसी दूसरे व्यक्ति को फ़ॉरवर्ड करता है, तो भी मैसेज नहीं भेजा जा सकेगा.

यह User Activation v2 के साथ काम करता है. यह मूल फ़ॉर्म और चेनिंग, दोनों के साथ काम करता है.