إضافات Chrome: توسيع واجهة برمجة التطبيقات لإتاحة التنقل الفوري

Dave Tapuska
Dave Tapuska

النصّ المختصر (TL;DR): تم تحديث واجهة برمجة تطبيقات الإضافات لإتاحة استخدام ميزة "التخزين المؤقت للصفحات" وعمليات التحميل المُسبقة. يُرجى الاطّلاع على التفاصيل أدناه.

يعمل Chrome بجد لجعل التنقل سريعًا. وتعمل تقنيات "التنقل الفوري" مثل ذاكرة التخزين المؤقت للخلف/إعادة التوجيه (يتم الشحن عليها على الكمبيوتر المكتبي في Chrome 96) وقواعد التوقُّع (يتم الشحن في Chrome 103) على تحسين تجربة الرجوع والمضي قدمًا. وسنستكشف في هذه المشاركة التحديثات التي أجريناها على واجهات برمجة تطبيقات إضافات المتصفحات لاستيعاب عمليات سير العمل الجديدة هذه.

فهم أنواع الصفحات

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

إخلاء الصفحة النشطة
إخلاء الصفحة النشطة:

فعند استخدام ميزة "التخزين المؤقت للصفحات" والعرض المسبق، لم تعد هناك علاقة بين علامات التبويب والصفحات. الآن، تقوم كل علامة تبويب بالفعل بتخزين العديد من الصفحات والصفحات التي تنتقل بين الحالات بدلاً من إتلافها وإعادة بنائها.

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

أنواع الصفحات
أنواع الصفحات:

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

ما الذي سيتغيّر بالنسبة إلى مطوّري الإضافات؟

رقم تعريف الإطار == 0

في Chromium، نشير إلى الإطار العلوي/الرئيسي باعتباره الإطار الأبعد.

قد يواجه مؤلفو الإضافات الذين يفترضون أن قيمة frameId للإطار الخارجي 0 (إحدى أفضل الممارسات السابقة). وبما أنّ علامة التبويب يمكن أن تحتوي الآن على عدة إطارات خارجية (الصفحات المعروضة مسبقًا والصفحات المخزّنة مؤقتًا)، يكون الافتراض المتمثل في وجود إطار خارجي واحد لعلامة التبويب غير صحيح. وسيظل frameId == 0 يمثّل الإطار الخارجي للصفحة النشطة، ولكن الإطارات الخارجية للصفحات الأخرى في علامة التبويب نفسها ستكون بقيمة غير صفرية. تمت إضافة حقل جديد frameType لحل هذه المشكلة. راجِع قسم "كيف أحدد ما إذا كان الإطار هو الإطار الخارجي؟" في هذه المشاركة.

دورة حياة الإطارات مقابل المستندات

هناك مفهوم آخر يتسبب في حدوث مشاكل في الإضافات وهو دورة حياة الإطار. يستضيف إطار المستند مستندًا (مرتبطًا بعنوان URL ملتزم). يمكن تغيير المستند (من خلال التنقل مثلاً) ولكن لن يتغير frameId، ولذلك من الصعب ربط ما حدث في مستند معين بـ frameId فقط. نحن نقدِّم مفهومًا للسمة documentId، وهو معرّف فريد لكل مستند. إذا تم التنقل في إطار وفتح مستند جديد، فسوف يتغير المعرف. يفيد هذا الحقل في تحديد الحالات التي تغيّر فيها الصفحات حالة دورة حياتها (بين العرض المسبق/النشطة/المخزنة مؤقتًا) لأنها تظل كما هي.

أحداث التنقّل على الويب

يمكن أن يتم تنشيط الأحداث في مساحة الاسم chrome.webNavigation عدة مرات على الصفحة نفسها بناءً على دورة حياتها. راجِع القسمَين "كيف يمكنني معرفة دورة حياة الصفحة؟" و"كيف أحدد وقت نقل الصفحة؟".

كيف يمكنني معرفة دورة حياة الصفحة؟

تمت إضافة النوع DocumentLifecycle إلى عدد من واجهات برمجة تطبيقات الإضافات حيث كان frameId متاحًا في السابق. إذا كان النوع DocumentLifecycle متاحًا في حدث (مثل onCommitted)، تكون قيمته هي الحالة التي تم فيها إنشاء الحدث. يمكنك في أي وقت طلب المعلومات من الطريقتَين WebNavigation getFrame() وgetAllFrames()، ولكن يُفضّل دائمًا استخدام القيمة من الحدث. وإذا استخدمت أيًّا من الطريقتين، عليك أن تكون على دراية بأن حالة الإطار قد تتغير بين وقت إنشاء الحدث ووقت حلّ الوعود التي تنطبق عليها كلتا الطريقتين.

تشمل السمة DocumentLifecycle القيم التالية:

  • "prerender" : لا يتم عرضها حاليًا للمستخدم، لكنّها تستعد لاحتمال عرضها للمستخدم.
  • "active": يتم عرضه حاليًا للمستخدم.
  • "cached": يتم تخزينها في ذاكرة التخزين المؤقت من خلال ميزة "التخزين المؤقت للصفحات".
  • "pending_deletion": يجري إتلاف المستند.

كيف أحدّد ما إذا كان الإطار هو الإطار الخارجي؟

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

للمساعدة في ذلك، قدّمنا نوعًا جديدًا يُسمى FrameType، لذا أصبح من السهل الآن تحديد ما إذا كان الإطار هو الإطار الخارجي. لـ FrameType القيم التالية:

  • "outermost_frame": يُشار إليه عادةً باسم الإطار العلوي. لاحظ أن هناك مضاعفات منها. على سبيل المثال، إذا كانت لديك صفحات معروضة مسبقًا ومخزّنة مؤقتًا، يكون لكل منها إطار خارجي يمكن أن يُطلق عليه اسم الإطار العلوي.
  • "fenced_frame": محجوزة للاستخدام في المستقبل
  • "sub_frame": إطار iframe عادةً

يمكننا الجمع بين DocumentLifecycle وFrameType وتحديد ما إذا كان الإطار هو الإطار الخارجي النشط. مثلاً: js tab.documentLifecycle == “active” && frameType == “outermost_frame”

كيف يمكنني حل مشاكل مدّة الاستخدام في الإطارات؟

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

لحلّ هذه المشكلة، طرحنا documentIdparentDocumentId). تجعل طريقة webNavigation.getFrame() الآن frameId اختيارية في حال توفير documentId. سيتغيّر documentId عند التنقّل في إطار.

كيف أحدِّد وقت انتقال الصفحة؟

هناك إشارات صريحة لتحديد وقت انتقال الصفحة بين الحالات.

لنلقِ نظرة على أحداث WebNavigation.

عند التنقّل لأول مرة في أي صفحة، ستظهر لك أربعة أحداث بالترتيب المدرَج أدناه. يُرجى العِلم أنّ هذه الأحداث الأربعة يمكن أن تحدث وتكون الحالة DocumentLifecycle إما "prerender" أو "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

ويمكنك توضيح ذلك في المخطَّط أدناه الذي يوضّح تغيير documentId إلى "xyz" عندما تصبح الصفحة المعروضة مُسبقًا هي الصفحة النشطة.

يتغير رقم تعريف المستند عندما تصبح الصفحة المعروضة مُسبقًا هي الصفحة النشطة.
تتغير documentId عندما تصبح الصفحة المعروضة مُسبقًا هي الصفحة النشطة.

عند انتقال صفحة من ذاكرة التخزين المؤقت للخلف/إعادة التوجيه أو العرض المُسبَق إلى حالة النشاط، سيكون هناك ثلاثة أحداث أخرى (ولكن يجب أن تكون القيمة DocumentLifecyle هي "active").

onBeforeNavigate
onCommitted
onCompleted

لن يطرأ أي تغيير على documentId كما هو الحال في الأحداث الأصلية. وقد تم توضيح ذلك أعلاه عندما يتم تفعيل documentId == xyz. ويُرجى العلم بأنّه يتم تنشيط أحداث التنقّل نفسها، باستثناء حدث onDOMContentLoaded لأنّه سبق أن تم تحميل الصفحة.

إذا كانت لديك أي تعليقات أو أسئلة، يُرجى طرحها علينا في مجموعة chromium-extensions.