أدوات استشعار الويب

يمكنك استخدام واجهة برمجة التطبيقات عامة لجهاز الاستشعار للوصول إلى أدوات الاستشعار على الجهاز، مثل مقاييس التسارع والجيروسكوب وأجهزة قياس المغناطيسية.

واليوم، تُستخدم بيانات جهاز الاستشعار في العديد من التطبيقات الخاصة بالأنظمة الأساسية لإتاحة حالات الاستخدام، مثل المتعة الغامرة وتتبُّع اللياقة البدنية والواقع المعزّز أو الافتراضي ألن يكون من الرائع جسرك الفجوة بين تطبيقات النظام الأساسي وتطبيقات الويب؟ أدخِل واجهة برمجة تطبيقات الاستشعار العامة، على الويب

ما هي واجهة برمجة تطبيقات أداة الاستشعار العامة؟

واجهة برمجة تطبيقات أداة الاستشعار العامة هي مجموعة من الواجهات التي تعرض أجهزة الاستشعار إلى منصة الويب. وتتكون واجهة برمجة التطبيقات من الأساسيات Sensor ومجموعة من الأدوات وفئات أجهزة الاستشعار المضمنة في الأعلى. تبسيط عملية التنفيذ والمواصفات من خلال استخدام واجهة أساسية لفئات أجهزة استشعار الخرسانة. على سبيل المثال، ألقِ نظرة على صف واحد (Gyroscope). إنها صغيرة للغاية! تشير رسالة الأشكال البيانية يتم تحديد الوظيفة الأساسية من خلال الواجهة الأساسية، ولا يكتفي Gyroscope بتوسيع نطاقها من خلال إضافة ثلاث السمات التي تمثل السرعة الزاويّة.

تتفاعل بعض فئات المستشعرات مع أجهزة استشعار الأجهزة الفعلية مثل مقياس التسارع أو بدروس الجيروسكوب. ويُشار إلى هذه الأجهزة باسم أدوات الاستشعار المنخفضة المستوى. أدوات استشعار أخرى يُشار إليها باسم مستشعرات الدمج، سندمج البيانات من عدة أجهزة استشعار منخفضة المستوى أجهزة الاستشعار للكشف عن المعلومات التي قد يحتاج النص البرمجي إلى حسابها. على سبيل المثال، أداة استشعار AbsoluteOrientation توفر مصفوفة دوران جاهزة للاستخدام مؤلفة من أربعة في أربعة استنادًا إلى البيانات التي تم الحصول عليها من مثل مقياس التسارع والجيروسكوب ومقياس المغناطيسية.

قد تعتقد أنّ منصة الويب توفّر بيانات حول أجهزة الاستشعار، وأنت على صواب. بالنسبة على سبيل المثال، DeviceMotion و DeviceOrientation تعرض الأحداث بيانات جهاز استشعار الحركة. لماذا نحتاج إلى واجهة برمجة تطبيقات جديدة؟

مقارنةً بالواجهات الحالية، توفّر واجهة برمجة التطبيقات General Sensor API عددًا كبيرًا من المزايا:

  • واجهة برمجة التطبيقات لأجهزة الاستشعار العامة هي إطار عمل لأداة استشعار يمكن توسيعها بسهولة من خلال إضافة فئات جديدة من أدوات الاستشعار ستحتفظ كل فئة من هذه الفئات بالواجهة العامة. رمز العميل المكتوب لنوع واحد من أجهزة الاستشعار ويمكن إعادة استخدامه لتغيير آخر مع إجراء عدد قليل جدًا من التعديلات!
  • يمكنك ضبط جهاز الاستشعار. على سبيل المثال، يمكنك تعيين معدل تكرار أخذ العينات المناسب التطبيقات المختلفة.
  • يمكنك معرفة ما إذا كان هناك جهاز استشعار متاح على المنصة.
  • تتميّز قراءات أجهزة الاستشعار بطوابع زمنية عالية الدقة، ما يؤدي إلى مزامنة أفضل مع الطوابع الزمنية الأنشطة في تطبيقك.
  • يتم تحديد نماذج بيانات أجهزة الاستشعار وأنظمة التنسيق بوضوح، ما يسمح لمورّدي المتصفّحات بما يلي: وتنفيذ حلول قابلة للتشغيل التفاعلي.
  • الواجهات المستندة إلى أداة الاستشعار العامة غير مرتبطة بنموذج DOM (أي أنّها ليست navigator) أو window)، وهذا يفتح فرصًا مستقبلية لاستخدام واجهة برمجة التطبيقات ضمن الخدمة العاملين أو تنفيذها في بيئات تشغيل JavaScript بلا واجهة مستخدم رسومية، مثل الأجهزة.
  • جوانب الأمان والخصوصية هي أولوية قصوى في جهاز الاستشعار العام. وتوفر مستوى أمان أفضل بكثير من واجهات برمجة التطبيقات لأجهزة الاستشعار القديمة. يوجد تكامل مع واجهة برمجة التطبيقات Permissions API
  • يتم تفعيل المزامنة التلقائية مع إحداثيات الشاشة متوفّر لـ Accelerometer وGyroscope وLinearAccelerationSensor AbsoluteOrientationSensor وRelativeOrientationSensor وMagnetometer

واجهات برمجة التطبيقات العامة المتوفّرة لأدوات الاستشعار العامة

في وقت كتابة هذه المقالة، هناك العديد من أدوات الاستشعار التي يمكنك تجربتها.

أجهزة استشعار الحركة:

  • Accelerometer
  • Gyroscope
  • LinearAccelerationSensor
  • AbsoluteOrientationSensor
  • RelativeOrientationSensor
  • GravitySensor

أجهزة الاستشعار البيئية:

  • AmbientLightSensor (خلف علامة #enable-generic-sensor-extra-classes في Chromium)
  • Magnetometer (خلف علامة #enable-generic-sensor-extra-classes في Chromium)

رصد الميزات

يُعد اكتشاف الميزات لواجهات برمجة تطبيقات الأجهزة أمرًا معقدًا، نظرًا لأنك تحتاج إلى اكتشاف كلٍ من ما إذا كان المستعرض يتوافق مع الواجهة المعنيّة وما إذا كان الجهاز يحتوي على أداة الاستشعار المقابلة. جارٍ التحقّق ما إذا كان المتصفح يدعم الواجهة أمرًا سهلاً أم لا. (استبدِل Accelerometer بأيٍّ من الواجهات الأخرى المذكورة أعلاه).

if ('Accelerometer' in window) {
  // The `Accelerometer` interface is supported by the browser.
  // Does the device have an accelerometer, though?
}

للحصول على نتيجة مفيدة لرصد الميزات، عليك محاولة الاتصال بأداة الاستشعار أيضًا. يوضح هذا المثال كيفية القيام بذلك.

let accelerometer = null;
try {
  accelerometer = new Accelerometer({ frequency: 10 });
  accelerometer.onerror = (event) => {
    // Handle runtime errors.
    if (event.error.name === 'NotAllowedError') {
      console.log('Permission to access sensor was denied.');
    } else if (event.error.name === 'NotReadableError') {
      console.log('Cannot connect to the sensor.');
    }
  };
  accelerometer.onreading = (e) => {
    console.log(e);
  };
  accelerometer.start();
} catch (error) {
  // Handle construction errors.
  if (error.name === 'SecurityError') {
    console.log('Sensor construction was blocked by the Permissions Policy.');
  } else if (error.name === 'ReferenceError') {
    console.log('Sensor is not supported by the User Agent.');
  } else {
    throw error;
  }
}

الملء التلقائي

بالنسبة إلى المتصفّحات التي لا تتيح استخدام واجهة برمجة تطبيقات أداة الاستشعار العامة، polyfill. يتيح لك polyfill تحميل أجهزة الاستشعار ذات الصلة فقط وعمليات التنفيذ.

// Import the objects you need.
import { Gyroscope, AbsoluteOrientationSensor } from './src/motion-sensors.js';

// And they're ready for use!
const gyroscope = new Gyroscope({ frequency: 15 });
const orientation = new AbsoluteOrientationSensor({ frequency: 60 });

ما هي كل أدوات الاستشعار هذه؟ كيف يمكنني استخدامها؟

قد تحتاج إلى مقدمة موجزة عن أجهزة الاستشعار. إذا كنت على دراية بأجهزة الاستشعار، يمكنك انتقِل مباشرةً إلى قسم الترميز العملي. وإلا، دعونا نلقي نظرة على كل منها جهاز الاستشعار بالتفصيل.

مقياس التسارع وجهاز استشعار التسارع الخطّي

قياسات أداة استشعار مقياس التسارع

جهاز استشعار Accelerometer يقيس تسارع الجهاز الذي يستضيف أداة الاستشعار على ثلاثة محاور (X وY وZ). أداة الاستشعار هذه هي وهو ما يعني أنه عندما يكون الجهاز في وضع السقوط الحر الخطي، فإن إجمالي سيكون التسارع 0 م/ث2، وعندما يرقد الجهاز بشكل مستوٍ على الطاولة، فإن التسارع في الاتجاه لأعلى (المحور Z) يساوي جاذبية الأرض، أي g ≈ +9.8 م/ث2 يقيس قوة الطاولة التي تدفع الجهاز إلى الأعلى. إذا دفعت الجهاز إلى لليمين، سيكون التسارع على المحور س موجبًا أو سالبًا إذا تم تسريع الجهاز من اليمين باتجاه اليسار.

يمكن استخدام مقاييس التسارع لتنفيذ إجراءات مثل: حساب عدد الخطوات أو أداة استشعار الحركة أو استخدام جهاز بسيط. توجهك. في كثير من الأحيان، يتم دمج قياسات مقياس التسارع مع بيانات من مصادر أخرى إنشاء أجهزة استشعار اندماج، مثل مستشعرات الاتجاه.

تشير رسالة الأشكال البيانية LinearAccelerationSensor يقيس التسارع المطبَّق على الجهاز الذي يستضيف أداة الاستشعار، باستثناء المساهمة للجاذبية. عندما يكون الجهاز غير نشط، على سبيل المثال، في وضع مستوٍ على الطاولة، ستقيس أداة الاستشعار ≈ 0 م/ث2 تسارع على ثلاثة محاور.

أداة استشعار الجاذبية

بإمكان المستخدمين استنتاج القيم القريبة من أجهزة استشعار الجاذبية يدويًا من خلال فحص قراءات Accelerometer وLinearAccelerometer يدويًا، ولكن قد يكون هذا مرهقًا وتعتمد على دقة القيم التي تقدمها أجهزة الاستشعار هذه. يمكن لأنظمة أساسية مثل Android توفير قراءات الجاذبية كجزء من نظام التشغيل، والتي من المفترض أن تكون أرخص من حيث والحوسبة، وتوفر قيمًا أكثر دقة اعتمادًا على أجهزة المستخدم، وأن تكون أسهل في الاستخدام في مجالات بيئة واجهة برمجة التطبيقات. تشير رسالة الأشكال البيانية تعرض GravitySensor التأثير من التسارع على طول المحاور "س" و"ص" و"ع" في الجهاز من خلال الجاذبية.

الجيروسكوب

قياسات أجهزة استشعار الجيروسكوب

تقيس أداة استشعار Gyroscope السرعة الزاويّة بوحدات الراديان في الثانية حول المحور المحلي "س" و"ص" و"ع" للجهاز. معظم المستهلكين تحتوي الأجهزة على ميكانيكية (MEMS) الجيروسكوب، وهي أدوات استشعار بالقصور الذاتي تقيس معدل الدوران بناءً على قوة كوريوليس غير المنتظمة الجيروسكوب (MEMS) عرضة الانحراف الناتج عن حساسية الجاذبية لجهاز الاستشعار التي تتشوّه نظام ميكانيكي داخلي. تتأرجح الجيروسكوب عند ترددات عالية نسبيًا، مثل 10 كيلوهرتز وبالتالي، قد تستهلك المزيد من الطاقة مقارنةً بالمستشعرات الأخرى.

أدوات استشعار الاتجاه

قياسات أداة استشعار الاتجاه المطلق

تشير رسالة الأشكال البيانية AbsoluteOrientationSensor هو جهاز استشعار اندماج يقيس دوران أي جهاز بالنسبة إلى نظام الإحداثيات للأرض، في حين أن RelativeOrientationSensor توفّر البيانات التي تمثّل دوران جهاز يستضيف أجهزة استشعار الحركة في ما يتعلّق بجهاز ثابت. نظام الإحداثيات المرجعية

جميع أطر عمل JavaScript الثلاثية الأبعاد الحديثة توفّر الأرقام الرباعية. ومصفوفات التدوير لتمثيل الدوران؛ ولكن، إذا كنت تستخدم WebGL بشكل مباشر، فإن OrientationSensor تحتوي على كلٍ من موقع واحد (quaternion) و طريقة واحدة (populateMatrix()) في ما يلي بعض المقتطفات:

three.js

let torusGeometry = new THREE.TorusGeometry(7, 1.6, 4, 3, 6.3);
let material = new THREE.MeshBasicMaterial({ color: 0x0071c5 });
let torus = new THREE.Mesh(torusGeometry, material);
scene.add(torus);

// Update mesh rotation using quaternion.
const sensorAbs = new AbsoluteOrientationSensor();
sensorAbs.onreading = () => torus.quaternion.fromArray(sensorAbs.quaternion);
sensorAbs.start();

// Update mesh rotation using rotation matrix.
const sensorRel = new RelativeOrientationSensor();
let rotationMatrix = new Float32Array(16);
sensor_rel.onreading = () => {
  sensorRel.populateMatrix(rotationMatrix);
  torus.matrix.fromArray(rotationMatrix);
};
sensorRel.start();

BABYLON

const mesh = new BABYLON.Mesh.CreateCylinder('mesh', 0.9, 0.3, 0.6, 9, 1, scene);
const sensorRel = new RelativeOrientationSensor({ frequency: 30 });
sensorRel.onreading = () => mesh.rotationQuaternion.FromArray(sensorRel.quaternion);
sensorRel.start();

WebGL

// Initialize sensor and update model matrix when new reading is available.
let modMatrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const sensorAbs = new AbsoluteOrientationSensor({ frequency: 60 });
sensorAbs.onreading = () => sensorAbs.populateMatrix(modMatrix);
sensorAbs.start();

// Somewhere in rendering code, update vertex shader attribute for the model
gl.uniformMatrix4fv(modMatrixAttr, false, modMatrix);

تتيح أدوات استشعار الاتجاه حالات استخدام متنوعة، مثل الألعاب الغامرة، والألعاب المعززة والافتراضية. الواقع.

للحصول على مزيد من المعلومات حول أجهزة استشعار الحركة وحالات الاستخدام المتقدّمة والمتطلبات، يمكنك الاطّلاع على مستند توضيحي حول أجهزة استشعار الحركة.

المزامنة مع إحداثيات الشاشة

يتم تلقائيًا التعامل مع قراءات أجهزة الاستشعار المكانية. في نظام إحداثي محلي مرتبط بالجهاز ولا يأخذ اتجاه الشاشة إلى الحساب.

نظام إحداثيات الجهاز
نظام الإحداثيات للجهاز

ومع ذلك، تتطلب العديد من حالات الاستخدام مثل الألعاب أو الواقع المعزز والواقع الافتراضي أن تكون قراءات جهاز الاستشعار في نظام إحداثي مرتبط باتجاه الشاشة بدلاً من ذلك.

نظام إحداثيات الشاشة
نظام تنسيق الشاشة

في السابق، كان يتطلّب استخدام JavaScript لإعادة تخصيص قراءات أجهزة الاستشعار مع إحداثيات الشاشة. هذه الطريقة غير فعالة كما أنها تزيد إلى حد كبير من تعقيد الويب رمز التطبيق يجب على تطبيق الويب مشاهدة التغييرات في اتجاه الشاشة وإجراء الإحداثيات التحويلات في قراءات المستشعر، وهو أمر ليس تافهًا ينبغي القيام به بالنسبة إلى زوايا أولر الرباعية.

توفّر واجهة برمجة تطبيقات أداة الاستشعار العامة حلاً أبسط وموثوقًا به! نظام الإحداثيات المحلي هو قابلة للضبط لكل فئات أدوات الاستشعار المكاني المحدّدة: Accelerometer وGyroscope LinearAccelerationSensor وAbsoluteOrientationSensor وRelativeOrientationSensor Magnetometer وبتمرير الخيار referenceFrame إلى الدالة الإنشائية لكائن أداة الاستشعار، يتخطّى المستخدم ما إذا كان سيتم حل القراءات التي تم إرجاعها الجهاز أو إحداثيات الشاشة.

// Sensor readings are resolved in the Device coordinate system by default.
// Alternatively, could be RelativeOrientationSensor({referenceFrame: "device"}).
const sensorRelDevice = new RelativeOrientationSensor();

// Sensor readings are resolved in the Screen coordinate system. No manual remapping is required!
const sensorRelScreen = new RelativeOrientationSensor({ referenceFrame: 'screen' });

لنقم بالترميز!

واجهة برمجة تطبيقات جهاز الاستشعار العامة بسيطة جدًا وسهلة الاستخدام. تحتوي واجهة المستشعر على start() و stop() طرق للتحكّم في حالة أداة الاستشعار وعدة طرق معالِجات الأحداث لتلقّي إشعارات حول تفعيل أداة الاستشعار والأخطاء والمعلومات المتوفرة حديثًا القراءات. تضيف فئات المستشعرات الخرسانية عادةً سمات القراءة الخاصة بها إلى القاعدة الصف.

بيئة التطوير

أثناء تطوير الجهاز، سيكون بإمكانك استخدام أدوات الاستشعار من خلال "localhost". إذا كنت تقوم بتطوير أجهزة الجوّال، إعداد إعادة توجيه المنفذ للخادم المحلي، وأنت على استعداد لتحسينها!

عندما يكون الرمز جاهزًا، انشره على خادم يتوافق مع HTTPS. يتم عرض صفحات GitHub عبر HTTPS، مما يجعلها مكانًا رائعًا لمشاركة عروضك التوضيحية.

تدوير النموذج الثلاثي الأبعاد

في هذا المثال البسيط، نستخدم البيانات من أداة استشعار الاتجاه المطلق لتعديل الدوران المربع الرباعي لنموذج ثلاثي الأبعاد. model هو ملف three.js مثيل الفئة Object3D الذي يحتوي على الموقع quaternion تشير رسالة الأشكال البيانية باتباع مقتطف الرمز من الهاتف التوجيهي عرض توضيحي، كيف يمكن استخدام مستشعر الاتجاه المطلق لتدوير نموذج ثلاثي الأبعاد.

function initSensor() {
  sensor = new AbsoluteOrientationSensor({ frequency: 60 });
  sensor.onreading = () => model.quaternion.fromArray(sensor.quaternion);
  sensor.onerror = (event) => {
    if (event.error.name == 'NotReadableError') {
      console.log('Sensor is not available.');
    }
  };
  sensor.start();
}

سيظهر اتجاه الجهاز من خلال دوران model ثلاثي الأبعاد في مشهد WebGL.

أداة الاستشعار تعدِّل اتجاه التصميم الثلاثي الأبعاد
يعدّل جهاز الاستشعار اتجاه التصميم الثلاثي الأبعاد

جهاز قياس اللكمات

تم استخراج مقتطف الرمز التالي من المقياس التجريبي، لتوضيح كيف يمكن استخدام مستشعر التسارع الخطي لحساب السرعة القصوى الجهاز على افتراض أنه يظل ثابتًا في البداية.

this.maxSpeed = 0;
this.vx = 0;
this.ax = 0;
this.t = 0;

/* … */

this.accel.onreading = () => {
  let dt = (this.accel.timestamp - this.t) * 0.001; // In seconds.
  this.vx += ((this.accel.x + this.ax) / 2) * dt;

  let speed = Math.abs(this.vx);

  if (this.maxSpeed < speed) {
    this.maxSpeed = speed;
  }

  this.t = this.accel.timestamp;
  this.ax = this.accel.x;
};

ويتم حساب السرعة الحالية كتقريب إلى التكامل مع دالة التسارع.

عرض توضيحي لتطبيق الويب لقياس السرعة المثقوبة
قياس سرعة اللكم

تصحيح الأخطاء وتجاوز أداة الاستشعار باستخدام "أدوات مطوري البرامج في Chrome"

في بعض الحالات، لست بحاجة إلى جهاز فعلي لتشغيل واجهة برمجة التطبيقات عامة لجهاز الاستشعار. أدوات مطوري البرامج في Chrome دعم كبير محاكاة اتجاه الجهاز.

&quot;أدوات مطوري البرامج في Chrome&quot; المستخدمة لإلغاء بيانات الاتجاه المخصّص لهاتف افتراضي
محاكاة اتجاه الجهاز باستخدام "أدوات مطوري البرامج في Chrome"

الخصوصية والأمان

قراءات أجهزة الاستشعار هي بيانات حساسة يمكن أن تتعرض لهجمات متنوعة من صفحات الويب الضارة. يؤدي تنفيذ واجهات برمجة التطبيقات لأداة الاستشعار العامة إلى فرض بعض القيود للحدّ من مستوى الأمان المحتمل. مخاطر الخصوصية. يجب أن يضع المطوّرون الذين يريدون استخدام لنذكرها بإيجاز.

HTTPS فقط

بما أنّ واجهة برمجة التطبيقات General Sensor API هي ميزة فعّالة، لا يتيح المتصفِّح استخدامها إلا في السياقات الآمنة. ضِمن والممارسة تعني أنّه لاستخدام واجهة برمجة التطبيقات العامة الخاصة بجهاز الاستشعار، عليك الوصول إلى صفحتك من خلال بروتوكول HTTPS. أثناء التطوير، يمكنك إجراء ذلك عبر http://localhost، ولكن عليك إجراء ذلك تحتاج إلى بروتوكول HTTPS على خادمك. يمكنك الاطّلاع على مجموعة الأمان والسلامة للتعرّف على أفضل الممارسات. والإرشادات.

دمج سياسة الأذونات

دمج سياسة الأذونات في الإعدادات العامة تتحكّم واجهة برمجة التطبيقات لجهاز الاستشعار في الوصول إلى بيانات أدوات الاستشعار لأحد الإطارات.

لا يمكن تلقائيًا إنشاء عناصر Sensor إلا داخل إطار رئيسي أو إطارات فرعية ذات أصل واحد، وبالتالي منع إطارات iframe المتعددة المصادر من قراءة بيانات أداة الاستشعار بشكل غير مصرَّح به. هذا السلوك التلقائي عن طريق التمكين الصريح أو تعطيل الخدمات الميزات التي تتحكم فيها السياسة.

يوضِّح المقتطف أدناه منح إذن الوصول إلى بيانات مقياس التسارع إلى إطار iframe من مصادر متعددة، ما يعني أصبح بالإمكان الآن إنشاء عناصر Accelerometer أو LinearAccelerationSensor هناك.

<iframe src="https://third-party.com" allow="accelerometer" />

يمكن تعليق إرسال قراءات المستشعر

لا يمكن الوصول إلى قراءات أجهزة الاستشعار إلا من خلال صفحة ويب مرئية، أي عندما يكون المستخدم مبتدئًا للتفاعل معه. علاوة على ذلك، لن يتم تقديم بيانات جهاز الاستشعار إلى الإطار الأصلي إذا كان المستخدم التركيز على التغييرات إلى إطار فرعي من مصادر متعددة. ويؤدي ذلك إلى منع الإطار الرئيسي من استنتاج البيانات التي أدخلها المستخدم.

ما هي الخطوات التالية؟

هناك مجموعة من فئات أجهزة الاستشعار المحدّدة مسبقًا سيتم تنفيذها في المستقبل القريب، مثل أداة استشعار الضوء المحيط أو أداة استشعار التقارب مع ذلك، بفضل قابلية التوسع الكبيرة يمكننا توقع ظهور المزيد من الفئات الجديدة التي تمثل العديد من أجهزة الاستشعار العامة، أنواع أجهزة الاستشعار.

هناك مجال آخر مهم للعمل في المستقبل وهو تحسين واجهة برمجة تطبيقات أداة الاستشعار العامة نفسها، تندرج مواصفات أجهزة الاستشعار حاليًا ضمن اقتراح المرشّحين، ما يعني أنّه لا يزال هناك وقت كافٍ. لإصلاح المشاكل وتقديم الوظائف الجديدة التي يحتاجها المطوّرون.

يمكنك المساعدة

مواصفات أداة الاستشعار التي تم الوصول إليها اقتراح المرشحين مستوى النضج، وبالتالي، تحظى ملاحظات مطوّري البرامج على الويب والمتصفحات بتقدير كبير. اسمح لنا معرفة الميزات التي سيكون من الرائع إضافتها أو ما إذا كان هناك شيء تريد تعديله في واجهة برمجة التطبيقات الحالية.

يُرجى عدم التردد في تقديم المشاكل المتعلقة بالمواصفات أيضًا. كأخطاء في تنفيذ Chrome.

الموارد

شكر وتقدير

تمت مراجعة هذه المقالة بواسطة جو ميدلي و كايس باسك. صورة رئيسية بواسطة Misko عبر ويكيميديا كومنز