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

Mustaq Ahmed
Joe Medley
Joe Medley

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

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

वर्शन 72 में, Chrome ने 'यूज़र ऐक्टिवेशन' वर्शन 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);

उपयोगकर्ता ऐक्टिवेशन 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);
});

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

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