نمای کلی معماری

افزونه‌ها بسته‌های فشرده‌ای از HTML، CSS، جاوا اسکریپت، تصاویر و سایر فایل‌های مورد استفاده در پلتفرم وب هستند که تجربه مرور گوگل کروم را سفارشی می‌کنند. افزونه‌ها با استفاده از فناوری وب ساخته شده‌اند و می‌توانند از همان APIهایی که مرورگر برای وب باز ارائه می‌دهد، استفاده کنند.

افزونه‌ها طیف گسترده‌ای از امکانات عملکردی را ارائه می‌دهند. آن‌ها می‌توانند محتوای وب را که کاربران می‌بینند و با آن تعامل دارند تغییر دهند یا رفتار خود مرورگر را گسترش داده و تغییر دهند.

افزونه‌ها را به عنوان دروازه‌ای برای تبدیل مرورگر کروم به شخصی‌ترین مرورگر در نظر بگیرید.

فایل‌های افزونه

افزونه‌ها از نظر نوع فایل‌ها و تعداد دایرکتوری‌ها متفاوت هستند، اما همه آنها ملزم به داشتن یک [manifest][docs-manifest] هستند. برخی از افزونه‌های اساسی اما مفید ممکن است فقط شامل manifest و آیکون نوار ابزار آن باشند.

فایل مانیفست با عنوان manifest.json ، اطلاعاتی در مورد افزونه، مانند مهم‌ترین فایل‌ها و قابلیت‌هایی که افزونه ممکن است استفاده کند، به مرورگر می‌دهد.

{
  "name": "My Extension",
  "version": "2.1",
  "description": "Gets information from Google.",
  "icons": {
    "128": "icon_16.png",
    "128": "icon_32.png",
    "128": "icon_48.png",
    "128": "icon_128.png"
  },
  "background": {
    "persistent": false,
    "scripts": ["background_script.js"]
  },
  "permissions": ["https://*.google.com/", "activeTab"],
  "browser_action": {
    "default_icon": "icon_16.png",
    "default_popup": "popup.html"
  }
}

افزونه‌ها باید یک آیکون داشته باشند که در نوار ابزار مرورگر قرار گیرد. آیکون‌های نوار ابزار امکان دسترسی آسان را فراهم می‌کنند و کاربران را از افزونه‌های نصب شده مطلع نگه می‌دارند. اکثر کاربران با کلیک روی آیکون، با افزونه‌ای که از یک پنجره بازشو استفاده می‌کند، تعامل خواهند داشت.

این افزونه‌ی بررسی ایمیل گوگل از یک اکشن مرورگر استفاده می‌کند:

تصویری از افزونه‌ی بررسی ایمیل گوگل

این افزونه‌ی Mappy از یک اسکریپت اکشن و محتوای صفحه استفاده می‌کند:

تصویری از افزونه Mappy

ارجاع به فایل‌ها

درست مانند فایل‌های یک صفحه HTML معمولی، می‌توان با استفاده از یک URL نسبی به فایل‌های یک افزونه اشاره کرد.

<img src="images/my_image.png">

علاوه بر این، هر فایل را می‌توان با استفاده از یک URL مطلق نیز مشاهده کرد.

chrome-extension://EXTENSION_ID/PATH_TO_FILE

در URL مطلق، EXTENSION_ID یک شناسه منحصر به فرد است که سیستم افزونه‌ها برای هر افزونه تولید می‌کند. شناسه‌های همه افزونه‌های بارگذاری شده را می‌توان با رفتن به URL chrome://extensions مشاهده کرد. PATH_TO_FILE محل فایل در پوشه بالایی افزونه است؛ که با URL نسبی مطابقت دارد.

هنگام کار بر روی یک افزونه‌ی باز نشده، شناسه‌ی افزونه می‌تواند تغییر کند. به طور خاص، شناسه‌ی یک افزونه‌ی باز شده در صورت بارگذاری افزونه از یک دایرکتوری متفاوت تغییر خواهد کرد؛ شناسه هنگام بسته‌بندی افزونه دوباره تغییر خواهد کرد. اگر کد یک افزونه به یک URL مطلق متکی باشد، می‌تواند از متد chrome.runtime.getURL() برای جلوگیری از کدگذاری سخت شناسه در طول توسعه استفاده کند.

معماری

معماری یک افزونه به عملکرد آن بستگی دارد، اما بسیاری از افزونه‌های قوی شامل چندین مؤلفه هستند:

اسکریپت پس‌زمینه

اسکریپت پس‌زمینه ، کنترل‌کننده‌ی رویداد افزونه است؛ این اسکریپت شامل شنونده‌هایی برای رویدادهای مرورگر است که برای افزونه مهم هستند. این اسکریپت تا زمانی که رویدادی اجرا نشود، غیرفعال می‌ماند و سپس منطق دستور داده شده را اجرا می‌کند. یک اسکریپت پس‌زمینه‌ی مؤثر فقط زمانی که مورد نیاز است بارگذاری می‌شود و زمانی که غیرفعال می‌شود، بارگذاری نمی‌شود.

عناصر رابط کاربری

رابط کاربری یک افزونه باید هدفمند و مینیمال باشد. رابط کاربری باید بدون اینکه حواس کاربر را پرت کند، تجربه مرور را سفارشی یا بهبود بخشد. اکثر افزونه‌ها دارای یک اکشن مرورگر یا اکشن صفحه هستند، اما می‌توانند شامل اشکال دیگری از رابط کاربری مانند منوهای زمینه ، استفاده از omnibox یا ایجاد میانبر صفحه کلید باشند.

صفحات رابط کاربری افزونه، مانند یک پنجره بازشو ، می‌توانند شامل صفحات HTML معمولی با منطق جاوا اسکریپت باشند. افزونه‌ها همچنین می‌توانند tabs.create یا window.open() را برای نمایش فایل‌های HTML اضافی موجود در افزونه فراخوانی کنند.

یک افزونه که از یک اکشن صفحه و یک پنجره بازشو استفاده می‌کند، می‌تواند از API محتوای اعلانی برای تنظیم قوانین در اسکریپت پس‌زمینه برای زمان در دسترس بودن پنجره بازشو برای کاربران استفاده کند. هنگامی که شرایط برآورده شود، اسکریپت پس‌زمینه با پنجره بازشو ارتباط برقرار می‌کند تا آیکون آن برای کاربران قابل کلیک باشد.

یک پنجره مرورگر حاوی یک اقدام صفحه که یک پنجره بازشو را نمایش می‌دهد

اسکریپت‌های محتوا

افزونه‌هایی که صفحات وب را می‌خوانند یا در آن‌ها می‌نویسند، از یک اسکریپت محتوا (content script) استفاده می‌کنند. اسکریپت محتوا حاوی جاوا اسکریپتی است که در چارچوب صفحه‌ای که در مرورگر بارگذاری شده است، اجرا می‌شود. اسکریپت‌های محتوا، DOM صفحات وبی را که مرورگر بازدید می‌کند، می‌خوانند و تغییر می‌دهند.

یک پنجره مرورگر با یک اکشن صفحه و یک اسکریپت محتوا

اسکریپت‌های محتوا می‌توانند با استفاده از API ذخیره‌سازی، با افزونه‌ی والد خود از طریق تبادل پیام و ذخیره‌ی مقادیر، ارتباط برقرار کنند.

مسیر ارتباطی بین اسکریپت محتوا و افزونه‌ی والد را نشان می‌دهد.

صفحه گزینه‌ها

همانطور که افزونه‌ها به کاربران امکان سفارشی‌سازی مرورگر کروم را می‌دهند، صفحه گزینه‌ها نیز امکان سفارشی‌سازی افزونه را فراهم می‌کند. گزینه‌ها می‌توانند برای فعال کردن ویژگی‌ها استفاده شوند و به کاربران اجازه دهند انتخاب کنند که چه عملکردی با نیازهای آنها مرتبط است.

استفاده از API های کروم

افزونه‌ها علاوه بر دسترسی به APIهای مشابه صفحات وب، می‌توانند از APIهای مخصوص افزونه نیز استفاده کنند که باعث ایجاد یکپارچگی نزدیک با مرورگر می‌شود. افزونه‌ها و صفحات وب هر دو می‌توانند به متد استاندارد window.open() برای باز کردن یک URL دسترسی داشته باشند، اما افزونه‌ها می‌توانند با استفاده از متد tabs.create از API کروم، مشخص کنند که آن URL در کدام پنجره نمایش داده شود.

روش‌های ناهمگام در مقابل روش‌های همزمان

اکثر متدهای API کروم ناهمزمان هستند: آنها بلافاصله و بدون انتظار برای اتمام عملیات، نتیجه را برمی‌گردانند. اگر یک افزونه نیاز به دانستن نتیجه یک عملیات ناهمزمان داشته باشد، می‌تواند یک تابع فراخوانی (callback) را به متد ارسال کند. تابع فراخوانی بعداً، احتمالاً خیلی دیرتر، پس از بازگشت متد اجرا می‌شود.

اگر افزونه نیاز داشته باشد که تب انتخاب شده فعلی کاربر را به یک URL جدید هدایت کند، باید شناسه تب فعلی را دریافت کرده و سپس آدرس آن تب را به URL جدید به‌روزرسانی کند.

اگر متد tabs.query همگام (synchronous) بود، ممکن بود چیزی شبیه به زیر باشد.

//THIS CODE DOESN'T WORK
var tab = chrome.tabs.query({'active': true}); //WRONG!!!
chrome.tabs.update(tab.id, {url:newUrl});
someOtherFunction();

این رویکرد به دلیل ناهمگام بودن query() با شکست مواجه خواهد شد. این متد بدون انتظار برای تکمیل کار، مقداری را برنمی‌گرداند. یک متد زمانی ناهمگام است که پارامتر فراخوانی در امضای آن موجود باشد.

// Signature for an asynchronous method
chrome.tabs.query(object queryInfo, function callback)

برای جستجوی صحیح یک تب و به‌روزرسانی URL آن، افزونه باید از پارامتر callback استفاده کند.

//THIS CODE WORKS
chrome.tabs.query({'active': true}, function(tabs) {
  chrome.tabs.update(tabs[0].id, {url: newUrl});
});
someOtherFunction();

در کد بالا، خطوط به ترتیب زیر اجرا می‌شوند: ۱، ۴، ۲. تابع فراخوانی مشخص شده برای query() فراخوانی شده و سپس خط ۲ را اجرا می‌کند، اما تنها پس از اینکه اطلاعات مربوط به تب انتخاب شده فعلی در دسترس قرار گرفت. این اتفاق مدتی پس از بازگشت query() رخ می‌دهد. اگرچه update() ناهمزمان است، اما کد از پارامتر فراخوانی استفاده نمی‌کند، زیرا افزونه هیچ کاری با نتایج به‌روزرسانی انجام نمی‌دهد.

// Synchronous methods have no callback option and returns a type of string
string chrome.runtime.getURL()

این متد به صورت همزمان URL را به صورت یک string برمی‌گرداند و هیچ کار غیرهمزمان دیگری انجام نمی‌دهد.

جزئیات بیشتر

برای اطلاعات بیشتر، مستندات مرجع API کروم را بررسی کنید و ویدیوی زیر را تماشا کنید.

ارتباط بین صفحات

اجزای مختلف در یک افزونه اغلب نیاز به ارتباط با یکدیگر دارند. صفحات HTML مختلف می‌توانند با استفاده از متدهای chrome.extension مانند getViews() و getBackgroundPage() یکدیگر را پیدا کنند. هنگامی که یک صفحه به صفحات افزونه دیگر ارجاع می‌دهد، اولین صفحه می‌تواند توابع موجود در صفحات دیگر را فراخوانی کرده و DOM های آنها را دستکاری کند. علاوه بر این، تمام اجزای افزونه می‌توانند به مقادیر ذخیره شده با استفاده از API ذخیره‌سازی دسترسی داشته باشند و از طریق ارسال پیام با یکدیگر ارتباط برقرار کنند.

ذخیره داده و حالت ناشناس

افزونه‌ها می‌توانند با استفاده از API ذخیره‌سازی ، API ذخیره‌سازی وب HTML5 یا با ارسال درخواست‌هایی از سرور که منجر به ذخیره داده‌ها می‌شوند، داده‌ها را ذخیره کنند. وقتی افزونه نیاز به ذخیره چیزی دارد، ابتدا بررسی کنید که آیا از یک پنجره ناشناس است یا خیر. به‌طور پیش‌فرض، افزونه‌ها در پنجره‌های ناشناس اجرا نمی‌شوند.

حالت ناشناس تضمین می‌کند که پنجره هیچ ردی از خود به جا نمی‌گذارد. هنگام کار با داده‌های پنجره‌های ناشناس، افزونه‌ها باید به این وعده عمل کنند. اگر یک افزونه معمولاً تاریخچه مرور را ذخیره می‌کند، تاریخچه پنجره‌های ناشناس را ذخیره نکنید. با این حال، افزونه‌ها می‌توانند تنظیمات برگزیده را از هر پنجره‌ای، چه در حالت ناشناس و چه غیر ناشناس، ذخیره کنند.

برای تشخیص اینکه آیا یک پنجره در حالت ناشناس است یا خیر، ویژگی incognito شیء tabs.Tab یا windows.Window مربوطه را بررسی کنید.

function saveTabData(tab) {
  if (tab.incognito) {
    return;
  } else {
    chrome.storage.local.set({data: tab.url});
  }
}

قدم بعدی را بردارید

پس از خواندن مرور کلی و تکمیل آموزش شروع به کار ، توسعه‌دهندگان باید آماده باشند تا نوشتن افزونه‌های خود را شروع کنند! با منابع زیر، عمیق‌تر به دنیای سفارشی‌سازی کروم وارد شوید.

  • در آموزش اشکال‌زدایی، درباره گزینه‌های موجود برای اشکال‌زدایی افزونه‌ها اطلاعات کسب کنید.
  • افزونه‌های کروم به APIهای قدرتمندی فراتر از آنچه در وب آزاد موجود است، دسترسی دارند. مستندات APIهای کروم* هر API را به طور کامل بررسی خواهد کرد.
  • نمای کلی توسعه افزونه، ده‌ها لینک اضافی به مستندات مربوط به ایجاد افزونه‌های پیشرفته دارد.