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

Dave Tapuska
Dave Tapuska

النصّ المختصر: تم تعديل واجهة برمجة التطبيقات Extensions API لإتاحة ميزة "التخزين المؤقت للصفحات"، وتحميل التنقّلات مسبقًا. يُرجى الاطّلاع على التفاصيل أدناه.

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

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

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

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

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

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

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

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

ما هي التغييرات التي ستطرأ على مطوّري الإضافات؟

FrameId == 0

في Chromium، نشير إلى الإطار العلوي/الرئيسي باسم الإطار الخارجي.

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

دورة حياة الإطارات مقارنةً بالوثائق

هناك مفهوم آخر يتسبب في حدوث مشاكل في الإضافات، وهو دورة حياة الإطار. يستضيف الإطار مستندًا (يكون مرتبطًا بعنوان URL مُحدَّد). يمكن أن يتغيّر المستند (على سبيل المثال، من خلال التنقّل) ولكن لن يتغيّر معرّف_الإطار، وبالتالي فإنه يصعب ربط حدوث حدث في مستند معيّن باستخدام معرّفات_الإطار فقط. نقدّم لك مفهوم 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 وتحديد ما إذا كان الإطار هو الإطار الخارجي النشط. على سبيل المثال: 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 عندما تصبح الصفحة المعروضة مُسبقًا هي الصفحة النشطة.
يتغيّر الرمز documentId عندما تصبح الصفحة المعروضة مسبقًا الصفحة النشطة.

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

onBeforeNavigate
onCommitted
onCompleted

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

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