إضافات 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.