diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
commit | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (patch) | |
tree | 0dd8b084480983cf9f9680e8aedb92782a921b13 /files/fa/mozilla/add-ons/webextensions | |
parent | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (diff) | |
download | translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.gz translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.bz2 translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.zip |
initial commit
Diffstat (limited to 'files/fa/mozilla/add-ons/webextensions')
6 files changed, 1253 insertions, 0 deletions
diff --git a/files/fa/mozilla/add-ons/webextensions/api/index.html b/files/fa/mozilla/add-ons/webextensions/api/index.html new file mode 100644 index 0000000000..724bf34516 --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/api/index.html @@ -0,0 +1,61 @@ +--- +title: JavaScript APIs +slug: Mozilla/Add-ons/WebExtensions/API +tags: + - NeedsTranslation + - TopicStub + - WebExtensions +translation_of: Mozilla/Add-ons/WebExtensions/API +--- +<div>{{AddonSidebar}}</div> + +<div> +<p>JavaScript APIs for WebExtensions can be used inside the extension's <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">background scripts</a> and in any other documents bundled with the extension, including <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_action">browser action</a> or <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Page_actions">page action</a> popups, <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Sidebars">sidebars</a>, <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Options_pages">options pages</a>, or <a href="/en-US/Add-ons/WebExtensions/manifest.json/chrome_url_overrides">new tab pages</a>. A few of these APIs can also be accessed by an extension's <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts">content scripts</a> (see the <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#WebExtension_APIs">list in the content script guide</a>).</p> + +<p>To use the more powerful APIs you need to <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/permissions">request permission</a> in your extension's <code>manifest.json</code>.</p> + +<p>You can access the APIs using the <code>browser</code> namespace:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">logTabs</span><span class="punctuation token">(</span>tabs<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>tabs<span class="punctuation token">)</span> +<span class="punctuation token">}</span> + +browser<span class="punctuation token">.</span>tabs<span class="punctuation token">.</span><span class="function token">query</span><span class="punctuation token">(</span><span class="punctuation token">{</span>currentWindow<span class="punctuation token">:</span> <span class="keyword token">true</span><span class="punctuation token">}</span><span class="punctuation token">,</span> logTabs<span class="punctuation token">)</span></code></pre> +</div> + +<div> +<p>Many of the APIs are asynchronous, returning a {{JSxRef("Promise")}}:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">logCookie</span><span class="punctuation token">(</span>c<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>c<span class="punctuation token">)</span> +<span class="punctuation token">}</span> + +<span class="keyword token">function</span> <span class="function token">logError</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">error</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> +<span class="punctuation token">}</span> + +<span class="keyword token">let</span> setCookie <span class="operator token">=</span> browser<span class="punctuation token">.</span>cookies<span class="punctuation token">.</span><span class="keyword token">set</span><span class="punctuation token">(</span> + <span class="punctuation token">{</span>url<span class="punctuation token">:</span> <span class="string token">"https://developer.mozilla.org/"</span><span class="punctuation token">}</span> +<span class="punctuation token">)</span><span class="punctuation token">;</span> +setCookie<span class="punctuation token">.</span><span class="function token">then</span><span class="punctuation token">(</span>logCookie<span class="punctuation token">,</span> logError<span class="punctuation token">)</span></code></pre> +</div> + +<div> +<p>Note that this is different from Google Chrome's extension system, which uses the <code>chrome</code> namespace instead of <code>browser</code>, and which uses callbacks instead of promises for asynchronous functions. As a porting aid, the Firefox implementation of WebExtensions APIs supports <code>chrome</code> and callbacks as well as <code>browser</code> and promises. Mozilla has also written a polyfill which enables code that uses <code>browser</code> and promises to work unchanged in Chrome: <a class="external external-icon" href="https://github.com/mozilla/webextension-polyfill">https://github.com/mozilla/webextension-polyfill</a>.</p> + +<p>Firefox also implements these APIs under the <code>chrome</code> namespace using callbacks. This allows code written for Chrome to run largely unchanged in Firefox for the APIs documented here.</p> + +<p>Microsoft Edge uses the <code>browser</code> namespace, but doesn't yet support promise-based asynchronous APIs. In Edge, for the time being, asynchronous APIs must use callbacks.</p> + +<p>Not all browsers support all the APIs: for the details, see <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">Browser support for JavaScript APIs</a>.</p> + +<p>Tip: Throughout the JavaScript API listings you will find short code examples that illustrate how the API is used. You can exercise these examples, without needing to create a web extension, using the console in the <a href="https://extensionworkshop.com/documentation/develop/debugging/#developer-tools-toolbox">Toolbox</a>. For example, here is the first code example on this page running in the Toolbox console in Firefox Developer Edition:</p> + +<p><img alt="Illustration of a snippet of web extension code run from the console in the Toolbox" src="https://mdn.mozillademos.org/files/17186/JavaScript_exercised_in_console.jpg" style="height: 347px; width: 680px;"></p> + +<h2 id="JavaScript_API_listing">JavaScript API listing</h2> + +<p>See below for a complete list of JavaScript APIs:</p> +</div> + +<div>{{LandingPageListSubpages}}</div> diff --git a/files/fa/mozilla/add-ons/webextensions/api/runtime/index.html b/files/fa/mozilla/add-ons/webextensions/api/runtime/index.html new file mode 100644 index 0000000000..62478e3457 --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/api/runtime/index.html @@ -0,0 +1,168 @@ +--- +title: runtime +slug: Mozilla/Add-ons/WebExtensions/API/runtime +tags: + - API + - Add-ons + - Extensions + - Interface + - NeedsTranslation + - Reference + - TopicStub + - WebExtensions + - runtime +translation_of: Mozilla/Add-ons/WebExtensions/API/runtime +--- +<div>{{AddonSidebar}}</div> + +<p><span class="seoSummary">This module provides information about your extension and the environment it's running in.</span></p> + +<p>It also provides messaging APIs enabling you to:</p> + +<ul> + <li>Communicate between different parts of your extension. For advice on choosing between the messaging options, see <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Choosing_between_one-off_messages_and_connection-based_messaging">Choosing between one-off messages and connection-based messaging</a>.</li> + <li>Communicate with other extensions.</li> + <li>Communicate with native applications.</li> +</ul> + +<h2 id="Types">Types</h2> + +<dl> + <dt>{{WebExtAPIRef("runtime.Port")}}</dt> + <dd>Represents one end of a connection between two specific contexts, which can be used to exchange messages.</dd> + <dt>{{WebExtAPIRef("runtime.MessageSender")}}</dt> + <dd> + <p>Contains information about the sender of a message or connection request.</p> + </dd> + <dt>{{WebExtAPIRef("runtime.PlatformOs")}}</dt> + <dd>Identifies the browser's operating system.</dd> + <dt>{{WebExtAPIRef("runtime.PlatformArch")}}</dt> + <dd>Identifies the browser's processor architecture.</dd> + <dt>{{WebExtAPIRef("runtime.PlatformInfo")}}</dt> + <dd>Contains information about the platform the browser is running on.</dd> + <dt>{{WebExtAPIRef("runtime.RequestUpdateCheckStatus")}}</dt> + <dd>Result of a call to {{WebExtAPIRef("runtime.requestUpdateCheck()")}}.</dd> + <dt>{{WebExtAPIRef("runtime.OnInstalledReason")}}</dt> + <dd>The reason that the {{WebExtAPIRef("runtime.onInstalled")}} event is being dispatched.</dd> + <dt>{{WebExtAPIRef("runtime.OnRestartRequiredReason")}}</dt> + <dd>The reason that the {{WebExtAPIRef("runtime.onRestartRequired")}} event is being dispatched.</dd> +</dl> + +<h2 id="Properties">Properties</h2> + +<dl> + <dt>{{WebExtAPIRef("runtime.lastError")}}</dt> + <dd>This value is set when an asynchronous function has an error condition that it needs to report to its caller.</dd> + <dt>{{WebExtAPIRef("runtime.id")}}</dt> + <dd>The ID of the extension.</dd> +</dl> + +<h2 id="Functions">Functions</h2> + +<dl> + <dt>{{WebExtAPIRef("runtime.getBackgroundPage()")}}</dt> + <dd>Retrieves the <a href="/en-US/docs/Web/API/Window">Window</a> object for the background page running inside the current extension.</dd> + <dt>{{WebExtAPIRef("runtime.openOptionsPage()")}}</dt> + <dd> + <p>Opens your extension's <a href="/en-US/Add-ons/WebExtensions/user_interface/Options_pages">options page</a>.</p> + </dd> + <dt>{{WebExtAPIRef("runtime.getManifest()")}}</dt> + <dd>Gets the complete <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> file, serialized as an object.</dd> + <dt>{{WebExtAPIRef("runtime.getURL()")}}</dt> + <dd>Given a relative path from the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> to a resource packaged with the extension, returns a fully-qualified URL.</dd> + <dt>{{WebExtAPIRef("runtime.setUninstallURL()")}}</dt> + <dd>Sets a URL to be visited when the extension is uninstalled.</dd> + <dt>{{WebExtAPIRef("runtime.reload()")}}</dt> + <dd>Reloads the extension.</dd> + <dt>{{WebExtAPIRef("runtime.requestUpdateCheck()")}}</dt> + <dd>Checks for updates to this extension.</dd> + <dt>{{WebExtAPIRef("runtime.connect()")}}</dt> + <dd>Establishes a connection from a content script to the main extension process, or from one extension to a different extension.</dd> + <dt>{{WebExtAPIRef("runtime.connectNative()")}}</dt> + <dd> + <div>Connects the extension to a native application on the user's computer.</div> + </dd> + <dt>{{WebExtAPIRef("runtime.sendMessage()")}}</dt> + <dd>Sends a single message to event listeners within your extension or a different extension. Similar to {{WebExtAPIRef('runtime.connect')}} but only sends a single message, with an optional response.</dd> + <dt>{{WebExtAPIRef("runtime.sendNativeMessage()")}}</dt> + <dd>Sends a single message from an extension to a native application.</dd> + <dt>{{WebExtAPIRef("runtime.getPlatformInfo()")}}</dt> + <dd>Returns information about the current platform.</dd> + <dt>{{WebExtAPIRef("runtime.getBrowserInfo()")}}</dt> + <dd>Returns information about the browser in which this extension is installed.</dd> + <dt>{{WebExtAPIRef("runtime.getPackageDirectoryEntry()")}}</dt> + <dd>Returns a DirectoryEntry for the package directory.</dd> +</dl> + +<h2 id="Events">Events</h2> + +<dl> + <dt>{{WebExtAPIRef("runtime.onStartup")}}</dt> + <dd>Fired when a profile that has this extension installed first starts up. This event is not fired when an incognito profile is started.</dd> + <dt>{{WebExtAPIRef("runtime.onInstalled")}}</dt> + <dd>Fired when the extension is first installed, when the extension is updated to a new version, and when the browser is updated to a new version.</dd> + <dt>{{WebExtAPIRef("runtime.onSuspend")}}</dt> + <dd>Sent to the event page just before the extension is unloaded. This gives the extension an opportunity to do some cleanup.</dd> + <dt>{{WebExtAPIRef("runtime.onSuspendCanceled")}}</dt> + <dd>Sent after {{WebExtAPIRef("runtime.onSuspend")}} to indicate that the extension won't be unloaded after all.</dd> + <dt>{{WebExtAPIRef("runtime.onUpdateAvailable")}}</dt> + <dd>Fired when an update is available, but isn't installed immediately because the extension is currently running.</dd> + <dt>{{WebExtAPIRef("runtime.onBrowserUpdateAvailable")}} {{deprecated_inline}}</dt> + <dd>Fired when an update for the browser is available, but isn't installed immediately because a browser restart is required.</dd> + <dt>{{WebExtAPIRef("runtime.onConnect")}}</dt> + <dd>Fired when a connection is made with either an extension process or a content script.</dd> + <dt>{{WebExtAPIRef("runtime.onConnectExternal")}}</dt> + <dd>Fired when a connection is made with another extension.</dd> + <dt>{{WebExtAPIRef("runtime.onMessage")}}</dt> + <dd>Fired when a message is sent from either an extension process or a content script.</dd> + <dt>{{WebExtAPIRef("runtime.onMessageExternal")}}</dt> + <dd>Fired when a message is sent from another extension. Cannot be used in a content script.</dd> + <dt>{{WebExtAPIRef("runtime.onRestartRequired")}}</dt> + <dd>Fired when the device needs to be restarted.</dd> +</dl> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("webextensions.api.runtime")}}</p> + +<div>{{WebExtExamples("h2")}}</div> + +<div class="note"><strong>Acknowledgements</strong> + +<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p> + +<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p> +</div> + +<div class="hidden"> +<pre>// Copyright 2015 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +</pre> +</div> diff --git a/files/fa/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html b/files/fa/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html new file mode 100644 index 0000000000..f58f2a5f8c --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html @@ -0,0 +1,317 @@ +--- +title: runtime.onMessage +slug: Mozilla/Add-ons/WebExtensions/API/runtime/onMessage +translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/onMessage +--- +<nav> +<p>{{AddonSidebar()}}</p> + +<p>از این رویداد برای گوش دادن به پیام های بخش دیگری از افزونه خود استفاده کنید.</p> +</nav> + +<p>برخی از موارد مورد استفاده برای مثال:</p> + +<ul> + <li>در یک content script ، برای گوش دادن به پیام های background script.</li> + <li>در یک background script ، برای گوش دادن به پیام های content script</li> + <li><strong>در یک صفحه <a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Options_pages">options page</a> یا <a href="/en-US/Add-ons/WebExtensions/User_interface_components#Popups">popup</a> script</strong>, برای گوش دادن به پیام هایbackground script.</li> + <li><strong>در یک background script</strong>, برای گوش دادن به پیام های options page یا popup script.</li> +</ul> + +<p>برای ارسال پیام که توسط <code>onMessage()</code> listener, از {{WebExtAPIRef("runtime.sendMessage()")}} یا (برای ارسال پیام به یک content script) {{WebExtAPIRef("tabs.sendMessage()")}}.</p> + +<div class="blockIndicator note"> +<p>از ایجاد چندین <code>onMessage()</code> listeners برای همان نوع پیام خودداری کنید, زیرا نظم چندین listeners will fire تضمین نمی شود.</p> + +<p>اگر می خواهید تحویل پیام به یک نقطه پایان خاص را تضمین کنید, از روش <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Connection-based_messaging">مبتنی بر اتصال برای پیام استفاده کنید</a>.</p> +</div> + +<p>همراه با message خود, به listener منتقل می شود:</p> + +<ul> + <li>یک شیء <code>فرستنده</code> که جزئیاتی درباره فرستنده پیام می دهد.</li> + <li>یک تابع <code>()sendResponse</code> که می تواند برای ارسال پاسخ به فرستنده استفاده شود.</li> +</ul> + +<p>شما می توانید با فراخوانی تابع <code>()sendResponse</code> در listener خود. <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_a_synchronous_response">مثالی را ببینید</a>.</p> + +<p>برای ارسال response ناهمزمان, دو گزینه وجود دارد:</p> + +<ul> + <li>رویداد listener را <code>true</code> برگردانید. این کار باعث می شود تابع <code>()sendResponse</code> پس از بازگشت listener معتبر باشد, بنابراین میتوانید بعدأ آن را صدا بزنید. <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_an_asynchronous_response_using_sendResponse">مثالی را ببینید</a>.</li> + <li>return a <code>Promise</code> from the event listener, and resolve when you have the response (or reject it in case of an error). <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_an_asynchronous_response_using_a_Promise">See an example</a>.</li> +</ul> + +<div class="warning"> +<p>بازگشت یک <code>Promise</code> در حال حاضر ترجیح داده می شود, زیرا <code>sendResponse()</code> <a href="https://github.com/mozilla/webextension-polyfill/issues/16#issuecomment-296693219">از مشخصات W3C حذف می شود</a>.</p> + +<p>کتابخانه محبوب <a href="https://github.com/mozilla/webextension-polyfill">webextension-polyfill</a> قبلا تابع <code>()sendResponse</code> را از اجزای آن حذف کرده است.</p> +</div> + +<div class="blockIndicator note"> +<p>شما همچنین می توانید از یک روش <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Connection-based_messaging">مبتنی بر اتصال برای تبادل پیام استفاده کنید</a>.</p> +</div> + +<h2 id="Syntax">Syntax</h2> + +<pre class="syntaxbox brush:js">browser.runtime.onMessage.addListener(<var>listener</var>) +browser.runtime.onMessage.removeListener(<var>listener</var>) +browser.runtime.onMessage.hasListener(<var>listener</var>) +</pre> + +<p>رویکردها سه تابع دارند:</p> + +<dl> + <dt><code>addListener(<var>listener</var>)</code></dt> + <dd>به این رویداد یک listener اضلفه می کند.</dd> + <dt><code>removeListener(<var>listener</var>)</code></dt> + <dd>listening به این رویداد را متوقف می کند. یک <code><var>listener</var></code> دلیلی است برای حذف listener.</dd> + <dt><code>hasListener(<var>listener</var>)</code></dt> + <dd>بررسی می کند که حداقل یک listener برای این رویداد ثبت شده باشد. اگر listening وجود داشت <code>true</code> برمیگرداند, در غیر این صورت <code>false</code> را بر میگرداند.</dd> +</dl> + +<h2 id="addListener_syntax">addListener syntax</h2> + +<h3 id="پارامترها">پارامترها</h3> + +<dl> + <dt><code><var>listener</var></code></dt> + <dd> + <p>یک تابع برگشتی که هنگام وقوع این رویداد فراخوانی می شود. به دلایل زیر این تابع پاس داده می شود:</p> + + <dl class="reference-values"> + <dt><code><var>message</var></code></dt> + <dd><code>object</code>. خود پیام است. این یک شیء با قابلیت JSON-ifiable است.</dd> + <dt><code><var>sender</var></code></dt> + <dd>یک {{WebExtAPIRef('runtime.MessageSender')}} شیء به نمایندگی از فرستنده پیام.</dd> + <dt><code><var>sendResponse</var></code></dt> + <dd> + <p>یک تابع برای صدا زدن, حداکثر یک بار, برای ارسال پاسخ به <code><var>پیام</var></code>. این تابع یک آرگومان واحد را شامل می شود, که ممکن است هر شیء با قابلیت JSON باشد. این آرگومان به فرستنده پیام ارسال می شود.</p> + + <p>اگر بیش از یک شنونده <code>onMessage()</code> در همان سند دارید, پس فقط ممکن است یک نفر پاسخی ارسال کند.</p> + + <p>برای ارسال پاسخ همزمان, قبل از بازگشت تابع listener با <code>sendResponse()</code> تماس بگیرید.</p> + + <p>برای ارسال پاسخ به صورت ناهمزمان:</p> + + <ul> + <li>یا یک رفرنس برای آرگومان <code>()sendResponse</code> نگه دارید و مقدار <code>true</code> را برای تابع listener برگردانید. شما می توانید پس از بازگشت تابع listener، با <code>()sendResponse</code> تماس بگیرید.</li> + <li>یا یک {{jsxref("Promise")}} را از تابع listener برگردانید و promise را در صورت آماده بودن پاسخ حل کنید. این یک روش ترجیحی است.</li> + </ul> + </dd> + </dl> + + <p>تابع <code><var>listener</var></code> می تواند مقدار Boolean یا {{jsxref("Promise")}} را برگرداند.</p> + + <div class="blockIndicator note"> + <p><strong>مهم:</strong> با استفاده از تابع <code>async</code> با <code>()addListener</code> تماس نگیرید:</p> + + <pre class="brush: js example-bad">// don't do this +browser.runtime.onMessage.addListener( + async (data, sender) => { + if (data.type === 'handle_me') { return 'done'; } + } +); +</pre> + + <p>این امر باعث می شود شنونده هر پیامی را که دریافت می کند, به طور موثر همه شنوندگان دیگر را از دریافت و پردازش پیام مسدود می کند.</p> + + <p>اگر می خواهید رویکردی ناهمزمان داشته باشید, به جای این کار از یک Promise استفاده کنید, مانند مثال زیر:</p> + + <pre class="brush: js example-good">browser.runtime.onMessage.addListener( + (data, sender) => { + if (data.type === 'handle_me') { + return Promise.resolve('done'); + } + } +); +</pre> + </div> + </dd> +</dl> + +<h2 id="سازگاری_مرورگر">سازگاری مرورگر</h2> + +<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> + +<p>{{Compat("webextensions.api.runtime.onMessage()")}}</p> + +<h2 id="Examples">Examples</h2> + +<h3 id="Simple_example">Simple example</h3> + +<p>This content script listens for click events on the web page. If the click was on a link, it messages the background page with the target URL:</p> + +<pre class="brush: js">// content-script.js + +window.addEventListener("click", notifyExtension); + +function notifyExtension(e) { + if (e.target.tagName != "A") { + return; + } + browser.runtime.sendMessage({"url": e.target.href}); +} +</pre> + +<p>The background script listens for these messages and displays a notification using the <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications">notifications</a></code> API:</p> + +<pre class="brush: js">// background-script.js + +browser.runtime.onMessage.addListener(notify); + +function notify(message) { + browser.notifications.create({ + "type": "basic", + "iconUrl": browser.extension.getURL("link.png"), + "title": "You clicked a link!", + "message": message.url + }); +} +</pre> + +<h3 id="Sending_a_synchronous_response">Sending a synchronous response</h3> + +<p>This content script sends a message to the background script when the user clicks on the page. It also logs any response sent by the background script:</p> + +<pre class="brush: js">// content-script.js + +function handleResponse(message) { + console.log(`background script sent a response: ${message.response}`); +} + +function handleError(error) { + console.log(`Error: ${error}`); +} + +function sendMessage(e) { + const sending = browser.runtime.sendMessage({content: "message from the content script"}); + sending.then(handleResponse, handleError); +} + +window.addEventListener("click", sendMessage);</pre> + +<p>Here is a version of the corresponding background script, that sends a response synchronously, from inside in the listener:</p> + +<pre class="brush: js">// background-script.js + +function handleMessage(request, sender, sendResponse) { + console.log(`content script sent a message: ${request.content}`); + sendResponse({response: "response from background script"}); +} + +browser.runtime.onMessage.addListener(handleMessage);</pre> + +<p>And here is another version which uses {{jsxref("Promise.resolve()")}}:</p> + +<pre class="brush: js">// background-script.js + +function handleMessage(request, sender, sendResponse) { + console.log(`content script sent a message: ${request.content}`); + return Promise.resolve({response: "response from background script"}); +} + +browser.runtime.onMessage.addListener(handleMessage);</pre> + +<h3 id="Sending_an_asynchronous_response_using_sendResponse">Sending an asynchronous response using sendResponse</h3> + +<p>Here is an alternative version of the background script from the previous example. It sends a response asynchronously after the listener has returned. Note <code>return true;</code> in the listener: this tells the browser that you intend to use the <code>sendResponse</code> argument after the listener has returned.</p> + +<pre class="brush: js">// background-script.js + +function handleMessage(request, sender, sendResponse) { + console.log(`content script sent a message: ${request.content}`); + setTimeout(() => { + sendResponse({response: "async response from background script"}); + }, 1000); + return true; +} + +browser.runtime.onMessage.addListener(handleMessage); +</pre> + +<h3 id="Sending_an_asynchronous_response_using_a_Promise">Sending an asynchronous response using a Promise</h3> + +<p>This content script gets the first <code><a></code> link on the page and sends a message asking if the link's location is bookmarked. It expects to get a Boolean response (<code>true</code> if the location is bookmarked, <code>false</code> otherwise):</p> + +<pre class="brush: js">// content-script.js + +const firstLink = document.querySelector("a"); + +function handleResponse(isBookmarked) { + if (isBookmarked) { + firstLink.classList.add("bookmarked"); + } +} + +browser.runtime.sendMessage({ + url: firstLink.href +}).then(handleResponse);</pre> + +<p>Here is the background script. It uses <code>{{WebExtAPIRef("bookmarks.search()")}}</code> to see if the link is bookmarked, which returns a {{jsxref("Promise")}}:</p> + +<pre class="brush: js">// background-script.js + +function isBookmarked(message, sender, response) { + return browser.bookmarks.search({ + url: message.url + }).then(function(results) { + return results.length > 0; + }); +} + +browser.runtime.onMessage.addListener(isBookmarked);</pre> + +<p>If the asynchronous handler doesn't return a Promise, you can explicitly construct a promise. This rather contrived example sends a response after a 1-second delay, using <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">Window.setTimeout()</a></code>:</p> + +<pre class="brush: js">// background-script.js + +function handleMessage(request, sender, sendResponse) { + return new Promise(resolve => { + setTimeout( () => { + resolve({response: "async response from background script"}); + }, 1000); + }); +} + +browser.runtime.onMessage.addListener(handleMessage);</pre> + +<p>{{WebExtExamples}}</p> + +<div class="note"><strong>Acknowledgements</strong> + +<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#event-onMessage"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p> + +<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p> +</div> + +<div class="hidden"> +<pre class="brush: js">// Copyright 2015 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +</pre> +</div> diff --git a/files/fa/mozilla/add-ons/webextensions/index.html b/files/fa/mozilla/add-ons/webextensions/index.html new file mode 100644 index 0000000000..49530e6d87 --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/index.html @@ -0,0 +1,97 @@ +--- +title: WebExtensions +slug: Mozilla/Add-ons/WebExtensions +tags: + - افزونه + - افزونه_فایرفاکس + - برنامه_نویسی + - توسعه +translation_of: Mozilla/Add-ons/WebExtensions +--- +<div dir="rtl">{{AddonSidebar}}</div> + +<div dir="rtl"><strong>افزونه ها</strong> قادر به بسط و تغییر قابلیت یک مرورگر می باشند. افزونه ها، برای فایرفاکس، با به کارگیری </div> + +<div dir="rtl">وب-گستر API، که یک سیستم مرورگر-متقابل جهت توسعه افزونه هاست، ساخته می شود. برای یک گسترش بزرگ، سیستم با افزونه API یا <a class="external-icon external" href="https://developer.chrome.com/extensions">extension API</a> مورد پشتیبانی گوگل و اوپرا و <a href="https://browserext.github.io/browserext/">W3C Draft Community Group</a> سازگار می باشد. افزونه های نوشته شده برای این مرورگرها، اغلب بیشتر مواقع در فایرفاکس یا <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/extensions/">Microsoft Edge</a> ، تنها با اندکی تغییر، اجرا خواهند شد. همچنین این API دارای سازگاری کامل با <a href="https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox">multiprocess Firefox</a> است.</div> + +<div dir="rtl">اگر شما ایده ها یا پرسش هایی داشته، یا برای رها شدن از افزونه های وراثتی، جهت به کارگیری وب-افزونه ها، نیازمند کمک باشید،می توانید در <a href="https://mail.mozilla.org/listinfo/dev-addons">dev-addons mailing list</a> یا <a href="irc://irc.mozilla.org/webextensions">#webextensions</a> در <a href="https://wiki.mozilla.org/IRC">IRC</a> به تنیجه برسید.</div> + +<p dir="rtl"> </p> + +<div class="row topicpage-table" dir="rtl"> +<div class="section"> +<h3 id="آغاز_کار">آغاز کار</h3> + +<ul> + <li><a href="/en-US/Add-ons/WebExtensions/What_are_WebExtensions"> افزونه چیست ؟</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Your_first_WebExtension">اولین افزونه شما</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Your_second_WebExtension">دومین افزونه شما</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension">تشریح یک افزونه</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Examples">افزونه های نمونه </a></li> +</ul> + +<h3 id="چگونه">چگونه</h3> + +<ul> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests">جلوگیری از ترافیک HTTP</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Modify_a_web_page">تغییر محتوای وب</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Add_a_button_to_the_toolbar">اضافه کردن دکمه در منوی ابزار</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Implement_a_settings_page">پیاده سازی صفحه تنظیمات</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard">کارکدن با کلیپ بورد</a></li> + <li><a href="/fa/docs/">دستکاری کردن برگه های مرورگر</a></li> + <li><a href="/fa/docs/">دسترسی و تغییر لیست علاقه مندی ها</a></li> + <li><a href="/fa/docs/">دسترسی و تغییر کوکی ها</a></li> +</ul> + +<h3 id="مفاهیم">مفاهیم</h3> + +<ul> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API">بررسی اجمالی JavaScript API</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/User_interface_components">کامپوننت رابط کاربری</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Content_scripts">Content scripts</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Match_patterns">تطابق الگوها</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization">بین المللی کردن</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy">راهبرد امنیت محتوا</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging">بومی سازی پیام ها</a></li> +</ul> + +<h3 id="انتقال">انتقال</h3> + +<ul> + <li><a href="/en-US/Add-ons/WebExtensions/Porting_from_Google_Chrome">اتقال افزونه گوگل کروم</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Porting_a_legacy_Firefox_add-on">انتقال یک افزونه قدیمی فایرفاکس</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Embedded_WebExtensions">جا نمایی افزونه</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Comparison_with_the_Add-on_SDK">مقایسه به Add-on SDK</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Comparison_with_XUL_XPCOM_extensions">مقایسه با افزونه های XUL/XPCOM</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities">ناسازگاری ها با Chrome</a></li> +</ul> + +<h3 id="نحوه_کار_فایرفاکس">نحوه کار فایرفاکس</h3> + +<ul> + <li><a href="/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">نصب</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Debugging">اشکال زدایی</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Getting_started_with_web-ext">شروع کار با web-ext</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/web-ext_command_reference">منابع کامند web-ext</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">WebExtensionها و آی دی Add-on</a></li> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Publishing_your_WebExtension">انتشار WebExtension شما</a></li> +</ul> +</div> + +<div class="section"> +<h3 id="منابع">منابع</h3> + +<ul> + <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API">بررسی اجمالی JavaScript API</a></li> + <li><a href="/en-US/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">جدول سازگاری مرورگرهای وب برای JavaScript API</a></li> +</ul> + +<h4 id="JavaScript_APIs">JavaScript APIs</h4> + +<div class="twocolumns">{{ ListSubpages ("/en-US/Add-ons/WebExtensions/API") }}</div> + +<h4 id="Manifest_keys">Manifest keys</h4> + +<div class="twocolumns">{{ ListSubpages ("/en-US/Add-ons/WebExtensions/manifest.json") }}</div> +</div> +</div> diff --git a/files/fa/mozilla/add-ons/webextensions/your_first_webextension/index.html b/files/fa/mozilla/add-ons/webextensions/your_first_webextension/index.html new file mode 100644 index 0000000000..b3fcdaaa40 --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/your_first_webextension/index.html @@ -0,0 +1,152 @@ +--- +title: اولین extension شما +slug: Mozilla/Add-ons/WebExtensions/Your_first_WebExtension +translation_of: Mozilla/Add-ons/WebExtensions/Your_first_WebExtension +--- +<div>{{AddonSidebar}}</div> + +<p dir="rtl">در این مقاله ما از ابتدا تا انتهای ساخت یک افزونه برای فایر فاکس را با هم مرور میکنیم. این <span id="result_box" lang="fa"><span>افزونه فقط یک </span></span> border <span lang="fa"><span> قرمز را به هر صفحه ای که از «mozilla.org» یا هر کدام از زیر دامنه های آن فراخوانی شده باشد را اضافه میکند .</span></span></p> + +<p>منبع کد این مثال بر روی گیت هاب: <a href="https://github.com/mdn/webextensions-examples/tree/master/borderify">https://github.com/mdn/webextensions-examples/tree/master/borderify</a>.</p> + +<p dir="rtl">در ابتدا شما به فایرفاکس نسخه 45 یا بالاتر نیاز دارید.</p> + +<h2 id="نوشتن_extension">نوشتن extension</h2> + +<p>یک فولدر جدید ایجاد کنید و به آن بروید. به عنوان مثال ، در خط فرمان / ترمینال خود را اینگونه انجام می دهید:</p> + +<pre class="brush: bash">mkdir borderify +cd borderify</pre> + +<h3 id="manifest.json">manifest.json</h3> + +<p><font>اکنون یک فایل جدید با نام "manifest.json" را مستقیماً در فولدر </font> "borderify" <font> ایجاد کنید.<span> </span>مطالب زیر را به آن بدهید:</font></p> + +<pre class="brush: json">{ + + "manifest_version": 2, + "name": "Borderify", + "version": "1.0", + + "description": "Adds a red border to all webpages matching mozilla.org.", + + "icons": { + "48": "icons/border-48.png" + }, + + "content_scripts": [ + { + "matches": ["*://*.mozilla.org/*"], + "js": ["borderify.js"] + } + ] + +}</pre> + +<ul> + <li style="margin: 0px 0px 6px; padding: 0px; border: 0px;"><font><font>سه کلید اول:<span> </span></font></font><code style='margin: 0px; padding: 0px 2px; border: 0px; font-style: inherit; font-weight: inherit; background-color: rgba(220, 220, 220, 0.5); border-radius: 2px; font-family: consolas, "Liberation Mono", courier, monospace;'><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/manifest_version" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">manifest_version</a></code><font><font>،<span> </span></font></font><code style='margin: 0px; padding: 0px 2px; border: 0px; font-style: inherit; font-weight: inherit; background-color: rgba(220, 220, 220, 0.5); border-radius: 2px; font-family: consolas, "Liberation Mono", courier, monospace;'><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/name" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">name</a></code><font><font>، و<span> </span></font></font><code style='margin: 0px; padding: 0px 2px; border: 0px; font-style: inherit; font-weight: inherit; background-color: rgba(220, 220, 220, 0.5); border-radius: 2px; font-family: consolas, "Liberation Mono", courier, monospace;'><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/version" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">version</a></code><font><font>، اجباری است و شامل داده های اصلی برای </font></font> extension <font><font> است.</font></font></li> + <li style="margin: 0px 0px 6px; padding: 0px; border: 0px;"><code style='margin: 0px; padding: 0px 2px; border: 0px; font-style: inherit; font-weight: inherit; background-color: rgba(220, 220, 220, 0.5); border-radius: 2px; font-family: consolas, "Liberation Mono", courier, monospace;'><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/description" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">description</a></code><font><font><span> </span>اختیاری است ، اما توصیه می شود: در </font></font> Add-ons Manager <font><font> نمایش داده می شود.</font></font></li> + <li style="margin: 0px 0px 6px; padding: 0px; border: 0px;"><code style='margin: 0px; padding: 0px 2px; border: 0px; font-style: inherit; font-weight: inherit; background-color: rgba(220, 220, 220, 0.5); border-radius: 2px; font-family: consolas, "Liberation Mono", courier, monospace;'><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/icons" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">icons</a></code><font><font><span> </span>اختیاری است ، اما توصیه می شود: به شما امکان می دهد یک نماد را برای </font></font> extension <font><font>مشخص کنید ، که در </font></font> Add-ons Manager <font><font> نشان داده خواهد شد.</font></font></li> +</ul> + +<p><font><font>جالب ترین نکته اینجاست که<span> </span></font></font><code><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/content_scripts" style="margin: 0px; padding: 0px; border: 0px; color: rgb(40, 92, 118); text-decoration: none;">content_scripts</a></code><font><font> به Firefox می گوید یک اسکریپت را در صفحات وب بارگذاری کنید که URL آن با الگوی خاصی مطابقت دارد.<span> </span></font><font>در این حالت ، ما از Firefox می خواهیم یک اسکریپت با نام "borderify.js" را در تمام صفحات HTTP یا HTTPS که از "mozilla.org" یا هر یک از زیر دامنه های آن استفاده می شود بارگیری کند.</font></font></p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts"><font><font>در مورد اسکریپت های محتوا بیشتر بدانید.</font></font></a></li> + <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns"><font><font>درباره الگوهای مطابقت بیشتر بدانید</font></font></a><font><font><span> </span>.</font></font></li> +</ul> + +<div class="warning"> +<p><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID#When_do_you_need_an_Add-on_ID"><font><font>در بعضی مواقع باید یک ID برای extension خود تعیین کنید</font></font></a><font><font><span> </span>.<span> </span></font><font>اگر نیاز به </font></font> add-on ID <font><font> دارید</font></font> , کلید <code><a href="/en-US/Add-ons/WebExtensions/manifest.json/applications">برنامه ها</a></code> را در <code>manifest.json</code> قرار دهید و ویژگی <code>gecko.id</code> آن را تنظیم کنید:</p> + +<pre class="brush: json">"applications": { + "gecko": { + "id": "borderify@example.com" + } +}</pre> +</div> + +<h3 id="iconsborder-48.png">icons/border-48.png</h3> + +<p>extension<font> باید یک نماد داشته باشد.<span> تا در کنار لیست </span></font> extension ها در Add-ons Manager <font> نمایش داده شود.<span> </span>manifest.json ما قول داده است كه ما در "</font> icons/border<font>-48.png" نماد داشته باشيم.</font></p> + +<p><font><font>فولدر </font></font>"icons" <font><font> را مستقیماً در فولدر </font></font> "borderify" <font><font> ایجاد کنید.<span> </span></font><font>نمادی را در آنجا با نام "border-48.png" ذخیره کنید.<span> </span></font><font>می توانید<span> </span></font></font><a class="external" href="https://github.com/mdn/webextensions-examples/blob/master/borderify/icons/border-48.png" rel="noopener"><font><font>از نمونه</font></font></a><font><font><span> </span>این مورد که از نماد Google Material Design طراحی شده است و تحت شرایط<span> </span></font></font><a class="external" href="https://creativecommons.org/licenses/by-sa/3.0/" rel="noopener"><font><font>مجوز Creative Commons Attribution-ShareAlike</font></font></a><font><font><span> </span>استفاده می شود استفاده کنید.</font></font></p> + +<p><font><font>اگر می خواهید نماد خود را تهیه کنید ، باید 48x48 پیکسل باشد.<span> </span></font><font>شما همچنین می توانید یک نماد پیکسل 96x96 را برای نمایشگرهای با وضوح بالا تهیه کنید ، و اگر این کار را انجام دهید به عنوان<span> </span></font></font><code>96</code><font><font>خاصیت<span> </span></font></font><code>icons</code> object <font><font> در manifest.json مشخص می شود:</font></font></p> + +<pre class="brush: json">"icons": { + "48": "icons/border-48.png", + "96": "icons/border-96.png" +}</pre> + +<p><font>روش دیگر ، شما می توانید یک فایل SVG را در اینجا تهیه کنید ، و به درستی اندازه گیری می شود.<span> </span></font><font>(اگرچه: اگر از SVG استفاده می کنید و نماد شما متن را شامل می شود ، ممکن است بخواهید از ابزار "تبدیل به مسیر" ویرایشگر SVG خود برای صاف کردن متن استفاده کنید ، به طوری که با اندازه / موقعیت ثابت سازگار باشد.</font></p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/icons"><font><font>درباره مشخص کردن نمادها بیشتر بدانید.</font></font></a></li> +</ul> + +<h3 id="borderify.js">borderify.js</h3> + +<p><font>سرانجام ، فایلی به نام "borderify.js" را مستقیماً در فولدر "</font>borderify<font>" ایجاد کنید.<span> </span>این محتوا را به آن بدهید:</font></p> + +<pre class="brush: js">document.body.style.border = "5px solid red";</pre> + +<p><font><font>این اسکریپت در صفحات مطابقت با الگوی ارائه شده در<span> </span></font></font><code>content_scripts</code><font><font>کلید manifest.json<span> </span></font><font>بارگذاری می شود<span> </span></font><font>.<span> </span></font><font>درست مانند اسکریپت هایی که توسط خود صفحه بارگذاری شده است ، اسکریپت دسترسی مستقیم به اسناد دارد.</font></font></p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts"><font><font>در مورد اسکریپت های محتوا بیشتر بدانید.</font></font></a></li> +</ul> + +<h2 id="امتحان_کردن"><font><font>امتحان کردن</font></font></h2> + +<p><span>ابتدا بررسی کنید که فایل های مناسب را در فولدرهای مناسب دارید:</span></p> + +<pre>borderify/ + icons/ + border-48.png + borderify.js + manifest.json</pre> + +<h3 id="نصب">نصب</h3> + +<p> در فایرفاکس : صفحه <a href="https://wiki.developer.mozilla.org/en-US/docs/Tools/about:debugging">about:debugging</a> را باز کنید، روی "This Firefox" (در نسخه های جدیدتر فایرفاکس) کلیک کنید، روی "Load Temporary Add-on" کلیک کنید و یکی از فایل ها را از آدرس اصلی extension خود انتخاب کنید</p> + +<p>{{EmbedYouTube("cer9EUKegG4")}}</p> + +<p>extension اکنون نصب شده است و تا زمانی که فایرفاکس را مجدداً راه اندازی کنید ، باقی خواهد ماند.</p> + +<p><font><font>روش دیگر ، می توانید با استفاده از<span> </span></font><font>ابزار<span> </span></font></font><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Getting_started_with_web-ext"><font><font>web-ext</font></font></a><font><font><span> </span>، پسوند را از خط فرمان اجرا<span> </span></font><font>کنید.</font></font></p> + +<h3 id="آزمایش_کردن">آزمایش کردن</h3> + +<p><span>اکنون سعی کنید از صفحهای تحت "mozilla.org" بازدید کنید</span>، <span>و باید </span> border <span> قرمز را در صفحه مشاهده کنید:</span></p> + +<p>{{EmbedYouTube("rxBQl2Z9IBQ")}}</p> + +<div class="note"> +<p><font>هر چند آن را در addons.mozilla.org امتحان نکنید!<span> </span></font><font>اسکریپت های محتوا در حال حاضر در آن دامنه مسدود شده اند</font> .</p> +</div> + +<p><font>کمی آزمایش کنید.<span> </span></font><font>اسکریپت محتوا را تغییر دهید تا رنگ حاشیه تغییر کند ، یا کاری دیگر روی محتوای صفحه انجام دهید.<span> </span>اسکریپت محتوا را ذخیره کنید ، سپس فایل های </font> extension <font> را با کلیک کردن روی دکمه </font> "Reload" <font> در </font> about:debugging <font> بارگیری مجدد کنید.<span> </span>می توانید تغییرات را بلافاصله مشاهده کنید:</font></p> + +<p>{{EmbedYouTube("NuajE60jfGY")}}</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox"><font><font>درباره بارگیری برنامه های افزودنی بیشتر بدانید</font></font></a></li> +</ul> + +<h2 id="بسته_بندی_و_انتشار"><font><font>بسته بندی و انتشار</font></font></h2> + +<p><font><font>برای استفاده افراد دیگر از </font></font> extension <font><font> شما ، باید آن را بسته بندی کرده و برای امضا به موزیلا ارسال کنید.<span> </span></font><font>برای کسب اطلاعات بیشتر در مورد آن ، به<span> </span></font></font> <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Publishing_your_WebExtension">"Publishing your extension"</a><font><font><span> </span>مراجعه کنید.</font></font></p> + +<h2 id="بعدی_چیست؟">بعدی چیست؟</h2> + +<p><span>اکنون شما یک ایده از روند توسعه یک WebExtension برای Firefox دارید ، سعی کنید:</span></p> + +<ul> + <li> <a href="https://wiki.developer.mozilla.org/en-US/Add-ons/WebExtensions/Your_second_WebExtension"><font><font>یک extension پیچیده تر بنویسید</font></font></a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension"><font><font>در مورد آناتومی یک extension بیشتر بخوانید</font></font></a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Examples"><font><font>مثال های extension را کاوش کنید</font></font></a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_next_"><font><font>اطلاعاتی را برای توسعه، آزمایش و انتشار extension خود بیابید.</font></font></a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_next_#Continue_your_learning_experience">یادگیری خود را بیشتر کنید</a>.</li> +</ul> diff --git a/files/fa/mozilla/add-ons/webextensions/your_second_webextension/index.html b/files/fa/mozilla/add-ons/webextensions/your_second_webextension/index.html new file mode 100644 index 0000000000..aff7ba0259 --- /dev/null +++ b/files/fa/mozilla/add-ons/webextensions/your_second_webextension/index.html @@ -0,0 +1,458 @@ +--- +title: اکستنشن دوم شما +slug: Mozilla/Add-ons/WebExtensions/Your_second_WebExtension +translation_of: Mozilla/Add-ons/WebExtensions/Your_second_WebExtension +--- +<div> +<p>{{AddonSidebar}}</p> + +<p dir="rtl">اگر شما مقاله <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension">اولین اکستنشن خود</a> را خوانده اید، حالا ایده ای از چگونگی نوشتن یک اکستنشن به شما داده می شود. در این مقاله ما اکستنشن کمی پیچیده تری را که در ان از تعدادی از API ها استفاده شده، می نویسیم.</p> + +<p>The extension adds a new button to the Firefox toolbar. When the user clicks the button, we display a popup enabling them to choose an animal. Once they choose an animal, we'll replace the current page's content with a picture of the chosen animal.</p> + +<p>To implement this, we will:</p> + +<ul> + <li><strong>define a <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_action">browser action</a>, which is a button attached to the Firefox toolbar</strong>.<br> + For the button we'll supply: + <ul> + <li>an icon, called "beasts-32.png"</li> + <li>a popup to open when the button is pressed. The popup will include HTML, CSS, and JavaScript.</li> + </ul> + </li> + <li><strong>define an icon for the extension</strong>, called "beasts-48.png". This will be shown in the Add-ons Manager.</li> + <li><strong>write a content script, "beastify.js" that will be injected into web pages</strong>.<br> + This is the code that will actually modify the pages.</li> + <li><strong>package some images of the animals, to replace images in the web page</strong>.<br> + We'll make the images "web accessible resources" so the web page can refer to them.</li> +</ul> + +<p>You could visualise the overall structure of the extension like this:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13671/Untitled-1.png" style="display: block; height: 1200px; margin-left: auto; margin-right: auto; width: 860px;"></p> + +<p>It's a simple extension, but shows many of the basic concepts of the WebExtensions API:</p> + +<ul> + <li>adding a button to the toolbar</li> + <li>defining a popup panel using HTML, CSS, and JavaScript</li> + <li>injecting content scripts into web pages</li> + <li>communicating between content scripts and the rest of the extension</li> + <li>packaging resources with your extension that can be used by web pages</li> +</ul> + +<p>You can find <a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">complete source code for the extension on GitHub</a>.</p> + +<p>To write this extension, you'll need Firefox 45 or newer.</p> + +<h2 id="Writing_the_extension">Writing the extension</h2> + +<p>Create a new directory and navigate to it:</p> + +<pre class="brush: bash">mkdir beastify +cd beastify</pre> + +<h3 id="manifest.json">manifest.json</h3> + +<p>Now create a new file called "manifest.json", and give it the following contents:</p> + +<pre class="brush: json">{ + + "manifest_version": 2, + "name": "Beastify", + "version": "1.0", + + "description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify", + "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify", + "icons": { + "48": "icons/beasts-48.png" + }, + + "permissions": [ + "activeTab" + ], + + "browser_action": { + "default_icon": "icons/beasts-32.png", + "default_title": "Beastify", + "default_popup": "popup/choose_beast.html" + }, + + "web_accessible_resources": [ + "beasts/frog.jpg", + "beasts/turtle.jpg", + "beasts/snake.jpg" + ] + +} +</pre> + +<ul> + <li>The first three keys: <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/manifest_version">manifest_version</a></code>, <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/name">name</a></code>, and <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/version">version</a></code>, are mandatory and contain basic metadata for the extension.</li> + <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/description">description</a></code> and <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/homepage_url">homepage_url</a></code> are optional, but recommended: they provide useful information about the extension.</li> + <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/icons">icons</a></code> is optional, but recommended: it allows you to specify an icon for the extension, that will be shown in the Add-ons Manager.</li> + <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> lists permissions the extension needs. We're just asking for the <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>activeTab</code> permission</a> here.</li> + <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> specifies the toolbar button. We're supplying three pieces of information here: + <ul> + <li><code>default_icon</code> is mandatory, and points to the icon for the button</li> + <li><code>default_title</code> is optional, and will be shown in a tooltip</li> + <li><code>default_popup</code> is used if you want a popup to be shown when the user clicks the button. We do, so we've included this key and made it point to an HTML file included with the extension.</li> + </ul> + </li> + <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a></code> lists files that we want to make accessible to web pages. Since the extension replaces the content in the page with images we've packaged with the extension, we need to make these images accessible to the page.</li> +</ul> + +<p>Note that all paths given are relative to manifest.json itself.</p> + +<h3 id="The_icon">The icon</h3> + +<p>The extension should have an icon. This will be shown next to the extension's listing in the Add-ons Manager (you can open this by visiting the URL "about:addons"). Our manifest.json promised that we would have an icon for the toolbar at "icons/beasts-48.png".</p> + +<p>Create the "icons" directory and save an icon there named "beasts-48.png". You could use <a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-48.png">the one from our example</a>, which is taken from the <a href="https://www.iconfinder.com/iconsets/free-retina-icon-set">Aha-Soft’s Free Retina iconset</a>, and used under the terms of its <a href="http://www.aha-soft.com/free-icons/free-retina-icon-set/">license</a>.</p> + +<p>If you choose to supply your own icon, It should be 48x48 pixels. You could also supply a 96x96 pixel icon, for high-resolution displays, and if you do this it will be specified as the <code>96</code> property of the <code>icons</code> object in manifest.json:</p> + +<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"icons":</span> <span class="punctuation token">{</span> + <span class="key token">"48":</span> <span class="string token">"icons/beasts-48.png"</span><span class="punctuation token">,</span> + <span class="key token">"96":</span> <span class="string token">"icons/beasts-96.png"</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="The_toolbar_button">The toolbar button</h3> + +<p>The toolbar button also needs an icon, and our manifest.json promised that we would have an icon for the toolbar at "icons/beasts-32.png".</p> + +<p>Save an icon named "beasts-32.png" in the "icons" directory. You could use <a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-32.png">the one from our example</a>, which is taken from the <a href="http://www.iconbeast.com/free">IconBeast Lite icon set</a> and used under the terms of its <a href="http://www.iconbeast.com/faq/">license</a>.</p> + +<p>If you don't supply a popup, then a click event is dispatched to your extension when the user clicks the button. If you do supply a popup, the click event is not dispatched, but instead, the popup is opened. We want a popup, so let's create that next.</p> + +<h3 id="The_popup">The popup</h3> + +<p>The function of the popup is to enable the user to choose one of three beasts.</p> + +<p>Create a new directory called "popup" under the extension root. This is where we'll keep the code for the popup. The popup will consist of three files:</p> + +<ul> + <li><strong><code>choose_beast.html</code></strong> defines the content of the panel</li> + <li><strong><code>choose_beast.css</code></strong> styles the content</li> + <li><strong><code>choose_beast.js</code></strong> handles the user's choice by running a content script in the active tab</li> +</ul> + +<pre class="brush: bash">mkdir popup +cd popup +touch choose_beast.html choose_beast.css choose_beast.js +</pre> + +<h4 id="choose_beast.html">choose_beast.html</h4> + +<p>The HTML file looks like this:</p> + +<pre class="brush: html"><!DOCTYPE html> + +<html> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="choose_beast.css"/> + </head> + +<body> + <div id="popup-content"> + <div class="button beast">Frog</div> + <div class="button beast">Turtle</div> + <div class="button beast">Snake</div> + <div class="button reset">Reset</div> + </div> + <div id="error-content" class="hidden"> + <p>Can't beastify this web page.</p><p>Try a different page.</p> + </div> + <script src="choose_beast.js"></script> +</body> + +</html> +</pre> + +<p>We have a <code><a href="/en-US/docs/Web/HTML/Element/div"><div></a></code> element with an ID of <code>"popup-content"</code> that contains an element for each animal choice. We have another <code><div></code> with an ID of <code>"error-content"</code> and a class <code>"hidden"</code>. We'll use that in case there's a problem initializing the popup.</p> + +<p>Note that we include the CSS and JS files from this file, just like a web page.</p> + +<h4 id="choose_beast.css">choose_beast.css</h4> + +<p>The CSS fixes the size of the popup, ensures that the three choices fill the space, and gives them some basic styling. It also hides elements with <code>class="hidden"</code>: this means that our <code>"error-content"</code> <code><div></code> will be hidden by default.</p> + +<pre class="brush: css">html, body { + width: 100px; +} + +.hidden { + display: none; +} + +.button { + margin: 3% auto; + padding: 4px; + text-align: center; + font-size: 1.5em; + cursor: pointer; +} + +.beast:hover { + background-color: #CFF2F2; +} + +.beast { + background-color: #E5F2F2; +} + +.reset { + background-color: #FBFBC9; +} + +.reset:hover { + background-color: #EAEA9D; +} + +</pre> + +<h4 id="choose_beast.js">choose_beast.js</h4> + +<p>Here's the JavaScript for the popup:</p> + +<pre class="brush: js">/** + * CSS to hide everything on the page, + * except for elements that have the "beastify-image" class. + */ +const hidePage = `body > :not(.beastify-image) { + display: none; + }`; + +/** + * Listen for clicks on the buttons, and send the appropriate message to + * the content script in the page. + */ +function listenForClicks() { + document.addEventListener("click", (e) => { + + /** + * Given the name of a beast, get the URL to the corresponding image. + */ + function beastNameToURL(beastName) { + switch (beastName) { + case "Frog": + return browser.extension.getURL("beasts/frog.jpg"); + case "Snake": + return browser.extension.getURL("beasts/snake.jpg"); + case "Turtle": + return browser.extension.getURL("beasts/turtle.jpg"); + } + } + + /** + * Insert the page-hiding CSS into the active tab, + * then get the beast URL and + * send a "beastify" message to the content script in the active tab. + */ + function beastify(tabs) { + browser.tabs.insertCSS({code: hidePage}).then(() => { + let url = beastNameToURL(e.target.textContent); + browser.tabs.sendMessage(tabs[0].id, { + command: "beastify", + beastURL: url + }); + }); + } + + /** + * Remove the page-hiding CSS from the active tab, + * send a "reset" message to the content script in the active tab. + */ + function reset(tabs) { + browser.tabs.removeCSS({code: hidePage}).then(() => { + browser.tabs.sendMessage(tabs[0].id, { + command: "reset", + }); + }); + } + + /** + * Just log the error to the console. + */ + function reportError(error) { + console.error(`Could not beastify: ${error}`); + } + + /** + * Get the active tab, + * then call "beastify()" or "reset()" as appropriate. + */ + if (e.target.classList.contains("beast")) { + browser.tabs.query({active: true, currentWindow: true}) + .then(beastify) + .catch(reportError); + } + else if (e.target.classList.contains("reset")) { + browser.tabs.query({active: true, currentWindow: true}) + .then(reset) + .catch(reportError); + } + }); +} + +/** + * There was an error executing the script. + * Display the popup's error message, and hide the normal UI. + */ +function reportExecuteScriptError(error) { + document.querySelector("#popup-content").classList.add("hidden"); + document.querySelector("#error-content").classList.remove("hidden"); + console.error(`Failed to execute beastify content script: ${error.message}`); +} + +/** + * When the popup loads, inject a content script into the active tab, + * and add a click handler. + * If we couldn't inject the script, handle the error. + */ +browser.tabs.executeScript({file: "/content_scripts/beastify.js"}) +.then(listenForClicks) +.catch(reportExecuteScriptError); + +</pre> + +<p>The place to start here is line 96. The popup script executes a content script in the active tab as soon as the popup is loaded, using the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">browser.tabs.executeScript()</a></code> API. If executing the content script is successful, then the content script will stay loaded in the page until the tab is closed or the user navigates to a different page.</p> + +<p>A common reason the <code>browser.tabs.executeScript()</code> call might fail is that you can't execute content scripts in all pages. For example, you can't execute them in privileged browser pages like about:debugging, and you can't execute them on pages in the <a href="https://addons.mozilla.org/">addons.mozilla.org</a> domain. If it does fail, <code>reportExecuteScriptError()</code> will hide the <code>"popup-content"</code> <code><div></code>, show the <code>"error-content"</code> <code><div></code>, and log an error to the <a href="/en-US/Add-ons/WebExtensions/Debugging">console</a>.</p> + +<p>If executing the content script is successful, we call <code>listenForClicks()</code>. This listens for clicks on the popup.</p> + +<ul> + <li>If the click was on a button with <code>class="beast"</code>, then we call <code>beastify()</code>.</li> + <li>If the click was on a button with <code>class="reset"</code>, then we call <code>reset()</code>.</li> +</ul> + +<p>The <code>beastify()</code> function does three things:</p> + +<ul> + <li>map the button clicked to a URL pointing to an image of a particular beast</li> + <li>hide the page's whole content by injecting some CSS, using the <code><a href="/en-US/Add-ons/WebExtensions/API/tabs/insertCSS">browser.tabs.insertCSS()</a></code> API</li> + <li>send a "beastify" message to the content script using the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">browser.tabs.sendMessage()</a></code> API, asking it to beastify the page, and passing it the URL to the beast image.</li> +</ul> + +<p>The <code>reset()</code> function essentially undoes a beastify:</p> + +<ul> + <li>remove the CSS we added, using the <code><a href="/en-US/Add-ons/WebExtensions/API/tabs/removeCSS">browser.tabs.removeCSS()</a></code> API</li> + <li>send a "reset" message to the content script asking it to reset the page.</li> +</ul> + +<h3 id="The_content_script">The content script</h3> + +<p>Create a new directory, under the extension root, called "content_scripts" and create a new file in it called "beastify.js", with the following contents:</p> + +<pre class="brush: js">(function() { + /** + * Check and set a global guard variable. + * If this content script is injected into the same page again, + * it will do nothing next time. + */ + if (window.hasRun) { + return; + } + window.hasRun = true; + + /** + * Given a URL to a beast image, remove all existing beasts, then + * create and style an IMG node pointing to + * that image, then insert the node into the document. + */ + function insertBeast(beastURL) { + removeExistingBeasts(); + let beastImage = document.createElement("img"); + beastImage.setAttribute("src", beastURL); + beastImage.style.height = "100vh"; + beastImage.className = "beastify-image"; + document.body.appendChild(beastImage); + } + + /** + * Remove every beast from the page. + */ + function removeExistingBeasts() { + let existingBeasts = document.querySelectorAll(".beastify-image"); + for (let beast of existingBeasts) { + beast.remove(); + } + } + + /** + * Listen for messages from the background script. + * Call "beastify()" or "reset()". + */ + browser.runtime.onMessage.addListener((message) => { + if (message.command === "beastify") { + insertBeast(message.beastURL); + } else if (message.command === "reset") { + removeExistingBeasts(); + } + }); + +})(); +</pre> + +<p>The first thing the content script does is to check for a global variable <code>window.hasRun</code>: if it's set the script returns early, otherwise it sets <code>window.hasRun</code> and continues. The reason we do this is that every time the user opens the popup, the popup executes a content script in the active tab, so we could have multiple instances of the script running in a single tab. If this happens, we need to make sure that only the first instance is actually going to do anything.</p> + +<p>After that, the place to start is line 40, where the content script listens for messages from the popup, using the <code><a href="/en-US/Add-ons/WebExtensions/API/runtime/onMessage">browser.runtime.onMessage</a></code> API. We saw above that the popup script can send two different sorts of messages: "beastify" and "reset".</p> + +<ul> + <li>if the message is "beastify", we expect it to contain a URL pointing to a beast image. We remove any beasts that might have been added by previous "beastify" calls, then construct and append an <code><a href="/en-US/docs/Web/HTML/Element/img"><img></a></code> element whose <code>src</code> attribute is set to the beast URL.</li> + <li>if the message is "reset", we just remove any beasts that might have been added.</li> +</ul> + +<h3 id="The_beasts">The beasts</h3> + +<p>Finally, we need to include the images of the beasts.</p> + +<p>Create a new directory called "beasts", and add the three images in that directory, with the appropriate names. You can get the images from <a href="https://github.com/mdn/webextensions-examples/tree/master/beastify/beasts">the GitHub repository</a>, or from here:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/11459/frog.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11461/snake.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11463/turtle.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"></p> + +<h2 id="Testing_it_out">Testing it out</h2> + +<p>First, double check that you have the right files in the right places:</p> + +<pre>beastify/ + + beasts/ + frog.jpg + snake.jpg + turtle.jpg + + content_scripts/ + beastify.js + + icons/ + beasts-32.png + beasts-48.png + + popup/ + choose_beast.css + choose_beast.html + choose_beast.js + + manifest.json</pre> + +<p>Starting in Firefox 45, you can install extensions temporarily from disk.</p> + +<p>Open "about:debugging" in Firefox, click "Load Temporary Add-on", and select your manifest.json file. You should then see the extension's icon appear in the Firefox toolbar:</p> + +<p>{{EmbedYouTube("sAM78GU4P34")}}</p> + +<p>Open a web page, then click the icon, select a beast, and see the web page change:</p> + +<p>{{EmbedYouTube("YMQXyAQSiE8")}}</p> + +<h2 id="Developing_from_the_command_line">Developing from the command line</h2> + +<p>You can automate the temporary installation step by using the <a href="/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> tool. Try this:</p> + +<pre class="brush: bash">cd beastify +web-ext run</pre> +</div> |