آموزش: مهاجرت به Manifest V2

نسخه ۱ مانیفست در کروم ۱۸ منسوخ شد و پشتیبانی از آن طبق برنامه پشتیبانی مانیفست نسخه ۱ به تدریج متوقف خواهد شد. تغییرات از نسخه ۱ به نسخه ۲ در دو دسته کلی قرار می‌گیرند: تغییرات API و تغییرات امنیتی.

این سند چک‌لیست‌هایی برای انتقال افزونه‌های کروم شما از نسخه ۱ مانیفست به نسخه ۲ ارائه می‌دهد و پس از آن خلاصه‌های دقیق‌تری از معنای این تغییرات و دلیل ایجاد آنها ارائه می‌دهد.

چک لیست تغییرات API

  • آیا از ویژگی browser_actions استفاده می‌کنید یا از API chrome.browserActions ؟

  • browser_actions با ویژگی مفرد browser_action جایگزین کنید.

  • chrome.browserActions را با chrome.browserAction جایگزین کنید.

  • ویژگی icons را با default_icon جایگزین کنید.

  • ویژگی name را با default_title جایگزین کنید.

  • ویژگی popup را با default_popup جایگزین کنید (و اکنون باید یک رشته باشد).

  • آیا از ویژگی page_actions استفاده می‌کنید یا از API chrome.pageActions ؟

  • page_actions با page_action جایگزین کنید.

  • chrome.pageActions را با chrome.pageAction جایگزین کنید.

  • ویژگی icons را با default_icon جایگزین کنید.

  • ویژگی name را با default_title جایگزین کنید.

  • ویژگی popup را با default_popup جایگزین کنید (و اکنون باید یک رشته باشد).

  • آیا از ویژگی chrome.self استفاده می‌کنید؟

  • با chrome.extension جایگزین کنید.

  • آیا از ویژگی Port.tab استفاده می‌کنید؟

  • با Port.sender جایگزین کنید.

  • آیا از APIهای chrome.extension.getTabContentses() یا chrome.extension.getExtensionTabs() استفاده می‌کنید؟

  • با chrome.extension.getViews( { "type" : "tab" } ) جایگزین کنید.

  • آیا افزونه شما از صفحه پس‌زمینه استفاده می‌کند؟

  • ویژگی background_page را با یک ویژگی background جایگزین کنید.

  • یک scripts یا ویژگی page که شامل کد صفحه است اضافه کنید.

  • یک ویژگی persistent اضافه کنید و آن را روی false تنظیم کنید تا صفحه پس‌زمینه شما به یک صفحه رویداد تبدیل شود.

چک لیست تغییرات امنیتی

  • آیا از بلوک‌های اسکریپت درون‌خطی در صفحات HTML استفاده می‌کنید؟

  • کد JS موجود در تگ‌های <script> را حذف کرده و آن را در یک فایل JS خارجی قرار دهید.

  • آیا از کنترل‌کننده‌های رویداد درون‌خطی (مثل onclick و غیره) استفاده می‌کنید؟

  • آنها را از کد HTML حذف کنید، به یک فایل JS خارجی منتقل کنید و به جای آن addEventListener() استفاده کنید.

  • آیا افزونه شما اسکریپت‌های محتوایی را به صفحات وب تزریق می‌کند که نیاز به دسترسی به منابعی (مانند تصاویر و اسکریپت‌ها) دارند که در بسته افزونه موجود است؟

  • ویژگی web_accessible_resources را تعریف کنید و منابع (و در صورت تمایل یک سیاست امنیتی محتوای جداگانه برای آن منابع) را فهرست کنید.

  • آیا افزونه شما صفحات وب خارجی را جاسازی می‌کند؟

  • ویژگی sandbox را تعریف کنید.

  • آیا کد یا کتابخانه شما از eval() ، new Function() ، innerHTML ، setTimeout() استفاده می‌کند یا رشته‌هایی از کد JS را که به صورت پویا ارزیابی می‌شوند، ارسال می‌کند؟

  • اگر کد JSON را به یک شیء تبدیل می‌کنید، از JSON.parse() استفاده کنید.

  • از یک کتابخانه سازگار با CSP، مثلاً AngularJS ، استفاده کنید.

  • یک ورودی sandbox در مانیفست خود ایجاد کنید و کد آسیب‌دیده را در sandbox اجرا کنید و با استفاده از postMessage() با صفحه sandbox شده ارتباط برقرار کنید.

  • آیا کد خارجی مانند jQuery یا Google Analytics را بارگذاری می‌کنید؟

  • دانلود کتابخانه و بسته‌بندی آن در افزونه‌تان و سپس بارگذاری آن از بسته محلی را در نظر بگیرید.

  • دامنه HTTPS که منبع را ارائه می‌دهد، در بخش "content_security_policy" از مانیفست خود، در لیست مجاز قرار دهید.

خلاصه تغییرات API

نسخه ۲ مانیفست چند تغییر در APIهای مربوط به اکشن مرورگر و اکشن صفحه ایجاد می‌کند و چند API قدیمی را با APIهای جدیدتر جایگزین می‌کند.

تغییرات در اقدامات مرورگر

API مربوط به اکشن‌های مرورگر، برخی تغییرات در نامگذاری را معرفی می‌کند:

  • ویژگی‌های browser_actions و chrome.browserActions با معادل‌های مفرد خود browser_action و chrome.browserAction جایگزین شده‌اند.
  • در زیر ویژگی قدیمی browser_actions ، ویژگی‌های icons ، name و popup وجود داشتند. این ویژگی‌ها با موارد زیر جایگزین شده‌اند:

  • default_icon برای آیکون نشان اکشن مرورگر

  • default_name برای متنی که هنگام قرار گرفتن نشانگر ماوس روی نشان، در راهنمای ابزار ظاهر می‌شود.

  • default_popup برای صفحه HTML که رابط کاربری را برای عملکرد مرورگر نشان می‌دهد (و این اکنون باید یک رشته باشد، نمی‌تواند یک شیء باشد)

تغییرات در اقدامات صفحه

مشابه تغییرات اعمال شده برای مرورگر، API اعمال صفحه نیز تغییر کرده است:

  • ویژگی‌های page_actions و chrome.pageActions با معادل‌های مفرد خود یعنی page_action و chrome.pageAction جایگزین شده‌اند.
  • در زیر ویژگی قدیمی page_actions ، ویژگی‌های icons ، name و popup وجود داشتند. این ویژگی‌ها با موارد زیر جایگزین شده‌اند:

  • default_icon برای آیکون نشان اکشن صفحه

  • default_name برای متنی که هنگام قرار گرفتن نشانگر ماوس روی نشان، در راهنمای ابزار ظاهر می‌شود.

  • default_popup برای صفحه HTML که رابط کاربری (UI) مربوط به اکشن صفحه را نشان می‌دهد (و این حالا باید یک رشته باشد، نمی‌تواند یک شیء باشد)

APIها حذف و تغییر داده شدند

چند API افزونه حذف و با نمونه‌های جدید جایگزین شده‌اند:

  • ویژگی background_page با background جایگزین شده است.
  • ویژگی chrome.self حذف شده است، از chrome.extension استفاده کنید.
  • ویژگی Port.tab با Port.sender جایگزین شده است.
  • رابط‌های برنامه‌نویسی chrome.extension.getTabContentses() و chrome.extension.getExtensionTabs() با chrome.extension.getViews( { "type" : "tab" } ) جایگزین شده‌اند.

خلاصه‌ای از تغییرات امنیتی

تعدادی تغییرات مرتبط با امنیت وجود دارد که با انتقال از نسخه ۱ مانیفست به نسخه ۲ همراه است. بسیاری از این تغییرات ناشی از پذیرش سیاست امنیت محتوا توسط کروم است؛ برای درک پیامدهای آن، باید درباره این سیاست بیشتر بخوانید.

اسکریپت‌های درون‌خطی و گرداننده‌های رویداد مجاز نیستند

به دلیل استفاده از سیاست امنیت محتوا ، دیگر نمی‌توانید از تگ‌های <script> که درون‌خطی با محتوای HTML هستند استفاده کنید. این تگ‌ها باید به فایل‌های JS خارجی منتقل شوند. علاوه بر این، کنترل‌کننده‌های رویداد درون‌خطی نیز پشتیبانی نمی‌شوند. برای مثال، فرض کنید کد زیر را در افزونه خود دارید:

<html>
<head>
  <script>
    function myFunc() { ... }
  </script>
</head>
</html>

این کد در زمان اجرا باعث خطا می‌شود. برای رفع این مشکل، محتویات تگ <script> را به فایل‌های خارجی منتقل کنید و با ویژگی src='path_to_file.js' به آنها ارجاع دهید.

به طور مشابه، کنترل‌کننده‌های رویداد درون‌خطی، که یک اتفاق رایج و ویژگی راحتی هستند که توسط بسیاری از توسعه‌دهندگان وب استفاده می‌شوند، اجرا نخواهند شد. برای مثال، موارد رایجی مانند موارد زیر را در نظر بگیرید:

<body onload="initialize()">
<button onclick="handleClick()" id="button1">

این موارد در افزونه‌های مانیفست نسخه ۲ کار نمی‌کنند. کنترل‌کننده‌های رویداد درون‌خطی را حذف کنید، آن‌ها را در فایل JS خارجی خود قرار دهید و در عوض addEventListener() برای ثبت کنترل‌کننده‌های رویداد برای آن‌ها استفاده کنید. به عنوان مثال، در کد JS خود، از موارد زیر استفاده کنید:

window.addEventListener("load", initialize);
...
document.getElementById("button1").addEventListener("click",handleClick);

این یک روش بسیار تمیزتر برای جدا کردن رفتار افزونه شما از نشانه‌گذاری رابط کاربری آن است.

جاسازی محتوا

سناریوهایی وجود دارد که در آنها افزونه شما ممکن است محتوایی را جاسازی کند که می‌تواند به صورت خارجی استفاده شود یا از یک منبع خارجی آمده باشد.

محتوای افزونه در صفحات وب: اگر افزونه شما منابعی (مانند تصاویر، اسکریپت، استایل‌های CSS و غیره) را که در اسکریپت‌های محتوایی که به صفحات وب تزریق می‌شوند، استفاده می‌شوند، در خود جای می‌دهد، باید از ویژگی web_accessible_resources برای فهرست کردن این منابع استفاده کنید تا صفحات وب خارجی بتوانند از آنها استفاده کنند:

{
...
  "web_accessible_resources": [
    "images/image1.png",
    "script/myscript.js"
  ],
...
}

جاسازی محتوای خارجی: سیاست امنیت محتوا فقط اجازه می‌دهد اسکریپت‌ها و اشیاء محلی از بسته شما بارگیری شوند، که این امر مانع از معرفی کد ناشناخته توسط مهاجمان خارجی به افزونه شما می‌شود. با این حال، مواقعی وجود دارد که می‌خواهید منابع خارجی مانند کد jQuery یا Google Analytics را بارگیری کنید. دو راه برای انجام این کار وجود دارد:

  1. کتابخانه مربوطه را به صورت محلی (مانند jQuery) دانلود کنید و آن را با افزونه خود بسته‌بندی کنید.
  2. شما می‌توانید با مجاز کردن فهرست کردن مبداهای HTTPS در بخش "content_security_policy" در مانیفست خود، CSP را به طور محدود کاهش دهید. برای گنجاندن کتابخانه‌ای مانند Google Analytics، این رویکرد را باید در پیش بگیرید:

    {
      ...,
      "content_security_policy": "script-src 'self'
      https://ssl.google-analytics.com; object-src 'self'",
      ...
    }
    

استفاده از ارزیابی اسکریپت پویا

شاید یکی از بزرگترین تغییرات در طرح جدید مانیفست نسخه ۲ این باشد که افزونه‌ها دیگر نمی‌توانند از تکنیک‌های ارزیابی اسکریپت پویا مانند eval() یا new Function() استفاده کنند، یا رشته‌های کد JS را به توابعی که باعث استفاده از eval() می‌شوند، مانند setTimeout() ، منتقل کنند. علاوه بر این، برخی از کتابخانه‌های جاوا اسکریپت رایج، مانند Google Maps و برخی از کتابخانه‌های قالب‌بندی، از برخی از این تکنیک‌ها استفاده می‌کنند.

کروم یک محیط امن (sandbox) برای صفحاتی فراهم می‌کند که در مبدا خودشان اجرا می‌شوند، صفحاتی که دسترسی به کروم ندارند.* APIها. برای استفاده از eval() و موارد مشابه تحت سیاست جدید امنیت محتوا:

  1. یک ورودی sandbox در فایل manifest خود ایجاد کنید.
  2. در ورودی سندباکس، صفحاتی را که می‌خواهید در سندباکس اجرا شوند، فهرست کنید.
  3. برای ارتباط با صفحه‌ی سندباکس‌شده، از ارسال پیام از طریق postMessage() استفاده کنید.

برای جزئیات بیشتر در مورد نحوه انجام این کار، به مستندات Sandboxing Eval مراجعه کنید.

مطالعه بیشتر

تغییرات در نسخه ۲ مانیفست به گونه‌ای طراحی شده‌اند که توسعه‌دهندگان را به سمت ساخت افزونه‌ها و برنامه‌هایی با معماری امن‌تر و قوی‌تر هدایت کنند. برای مشاهده لیست کاملی از تغییرات از نسخه ۱ مانیفست به نسخه ۲، به مستندات فایل مانیفست مراجعه کنید. برای اطلاعات بیشتر در مورد استفاده از sandboxing برای جداسازی کد ناامن، مقاله sandboxing eval را بخوانید. می‌توانید با مراجعه به آموزش مرتبط با افزونه‌های ما و یک مقدمه خوب در HTML5Rocks ، درباره سیاست امنیت محتوا اطلاعات بیشتری کسب کنید.