aboutsummaryrefslogtreecommitdiff
path: root/files/ja/mozilla/add-ons/webextensions/modify_a_web_page/index.html
blob: 9a2d92b0b89afe844067802cd42ff05db5678664 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
---
title: ウェブページを変更する
slug: Mozilla/Add-ons/WebExtensions/Modify_a_web_page
tags:
  - WebExtensions
translation_of: Mozilla/Add-ons/WebExtensions/Modify_a_web_page
---
<div>{{AddonSidebar}}</div>

<p>拡張機能の一般的な事例の1つはウェブページを変更することです。例えば、ページのスタイルを変更、特定の DOM ノードを隠す、別の DOM ノードをページに挿入する、といいでしょう。</p>

<p>WebExtensions API での実現方法は2つあります:</p>

<ul>
 <li><strong>手動で定義する: </strong><span lang="ja"><span>URL に一致するパターンを定義し、その URL が一致するページにスクリプトを読み込まれるようにします。</span></span></li>
 <li><strong>自動で行う: </strong>JavaScript API を使い、特定のタブでホストされているページにスクリプトを読み込まれるようにします。</li>
</ul>

<p>どちらの方法のスクリプトも<em>コンテンツスクリプト</em>と呼ばれ、拡張機能を構成する他のスクリプトとは異なります:</p>

<ul>
 <li>WebExtension API の一部のサブセットのみにアクセスできます。</li>
 <li>読み込まれたウェブページに直接アクセスできます。</li>
 <li>messaging API を使い、拡張機能の残りの部分と対話できます。</li>
</ul>

<p>この記事ではスクリプトを読み込むそれぞれの方法について説明します。</p>

<h2 id="Modifying_pages_that_match_a_URL_pattern" name="Modifying_pages_that_match_a_URL_pattern">URL パターンにマッチしたページを変更する</h2>

<p>まず始めに、"modify-page" という新しいディレクトリーを作成します。このディレクトリーで "manifest.json" というファイルを作成し、以下のように記述します。</p>

<pre class="brush: json">{

  "manifest_version": 2,
  "name": "modify-page",
  "version": "1.0",

  "content_scripts": [
    {
      "matches": ["https://developer.mozilla.org/*"],
      "js": ["page-eater.js"]
    }
  ]

}</pre>

<p><code><a href="/ja/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts</a></code> キーは URL パターンと一致するページにスクリプトを読み込む方法です。この場合、<code>content_scripts</code><a href="/"> https://developer.mozilla.org/</a> 以下のすべてのページで "page-eater.js" というスクリプトをロードするようにブラウザーに指示します。</p>

<div class="note">
<p><code>content_scripts</code><code>"js"</code> プロパティ は配列なので、マッチしているページに複数のスクリプトを挿入できます。<span id="result_box" lang="ja"><span>これを行うと、ページによってロードされるいくつかのスクリプトと同じように、ページは同じスコープを共有し、配列にリストされている順序でロードされます。</span></span></p>
</div>

<div class="note">
<p><code>content_scripts</code> キーでは <code>"css"</code> プロパティで CSS スタイルシートを挿入することもできます。</p>
</div>

<p>次に、"page-eater.js" というファイルを "modify-page" ディレクトリー内に作り、以下のように記述します。</p>

<pre class="brush: js">document.body.textContent = "";

var header = document.createElement('h1');
header.textContent = "This page has been eaten";
document.body.appendChild(header);</pre>

<p><a href="/ja/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">拡張機能をインストール</a> して <a href="/">https://developer.mozilla.org/</a> を訪れてみましょう。</p>

<p>{{EmbedYouTube("lxf2Tkg6U1M")}}</p>

<div class="note">
<p><span id="result_box" lang="ja"><span>このビデオでは </span></span><a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> <span lang="ja"><span>で動作するコンテンツスクリプトを示していますが、現在このサイトではコンテンツスクリプトはブロックされています。</span></span></p>
</div>

<h2 id="Modifying_pages_programmatically" name="Modifying_pages_programmatically">自動でページを変更する</h2>

<p>ユーザーがあなたに質問してきたとき、まだページを処理している場合どうしたらいいですか? <span id="result_box" lang="ja"><span>この例を更新して、ユーザーがコンテキストメニュー項目をクリックしたときにコンテンツスクリプトを挿入しましょう。</span></span></p>

<p>始めに、"manifest.json" を以下のように更新してください。</p>

<pre class="brush: json">{

  "manifest_version": 2,
  "name": "modify-page",
  "version": "1.0",

  "permissions": [
    "activeTab",
    "contextMenus"
  ],

  "background": {
    "scripts": ["background.js"]
  }

}</pre>

<p>これは <code>content_scripts</code> キーを削除し、新たに 2 つのキーを追加しました。</p>

<ul>
 <li><code><a href="/ja/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code>: スクリプトをページに挿入するには、変更するページへの権限が必要です。<a href="/ja/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>activeTab</code> パーミッション</a>は現在アクティブなタブへの一時的な権限を取得する方法です。コンテキストメニューに項目を追加するには <code>contextMenus</code> パーミッションも必要となります。</li>
 <li><code><a href="/ja/Add-ons/WebExtensions/manifest.json/background">background</a></code>: <a href="/ja/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">"バックグラウンドスクリプト"</a> という "background.js" を永続的に読み込み<span id="result_box" lang="ja"><span>、ここでコンテキストメニューを設定し、コンテンツスクリプトを挿入します。</span></span></li>
</ul>

<p>このファイルを作りましょう。"background.js" というファイルを "modify-page" ディレクトリー内に作り以下のように記述します。</p>

<pre class="brush: js">browser.contextMenus.create({
  id: "eat-page",
  title: "Eat this page"
});

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "eat-page") {
    browser.tabs.executeScript({
      file: "page-eater.js"
    });
  }
});
</pre>

<p>このスクリプトでは <a href="/ja/Add-ons/WebExtensions/API/ContextMenus/create">context menu item</a> を作成し、特定の id とタイトルを指定します。(コンテキストメニューに表示するテキスト) <span id="result_box" lang="ja"><span>次に、イベントリスナーを設定して、ユーザーがコンテキストメニュー項目をクリックしたときに、それが </span></span><code>eat-page</code><span lang="ja"><span> 項目であるかどうかをチェックします。</span></span>それが正しければ、<code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript()</a></code> API を利用して、"page-eater.js" を挿入します。<span id="result_box" lang="ja"><span>この API はオプションでタブ ID を引数として取ります、よってタブ ID は省略されています。つまり、スクリプトは現在アクティブなタブに挿入されています。</span></span></p>

<p>この時点で拡張機能は以下のようになっています。</p>

<pre class="line-numbers  language-html"><code class="language-html">modify-page/
    background.js
    manifest.json
    page-eater.js</code></pre>

<p><a href="/ja/Add-ons/WebExtensions/Temporary_Installation_in_Firefox#Reloading_a_temporary_add-on">拡張機能を再読み込み</a>して、ページを開きます (任意のページ)  コンテキストメニューを有効化し、"Eat this page" を選択します。</p>

<p>{{EmbedYouTube("zX4Bcv8VctA")}}</p>

<div class="note">
<p><span id="result_box" lang="ja"><span>このビデオでは </span></span><a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> <span lang="ja"><span>で動作するコンテンツスクリプトを示していますが、現在このサイトではコンテンツスクリプトはブロックされています。</span></span></p>
</div>

<h2 id="Messaging" name="Messaging">メッセージ</h2>

<p>コンテンツスクリプトとバックグラウンドスクリプトはお互いの状態に直接アクセスすることはできません。しかし、メッセージを送ることによる対話をすることができます。<span id="result_box" lang="ja"><span>一方のエンドはメッセージリスナーを設定し、もう一方のエンドはメッセージを送信します。</span> <span>次の表は、各側面に関連する API をまとめたものです。</span></span></p>

<table class=" fullwidth-table standard-table">
 <thead>
  <tr>
   <th scope="row"></th>
   <th scope="col">コンテンツスクリプト内</th>
   <th scope="col">バックグラウンドスクリプト内</th>
  </tr>
  <tr>
   <th scope="row">メッセージ送信</th>
   <td><code><a href="/ja/Add-ons/WebExtensions/API/runtime#sendMessage()">browser.runtime.sendMessage()</a></code></td>
   <td><code><a href="/ja/Add-ons/WebExtensions/API/Tabs/sendMessage">browser.tabs.sendMessage()</a></code></td>
  </tr>
  <tr>
   <th scope="row">メッセージ受信</th>
   <td><code><a href="/ja/Add-ons/WebExtensions/API/runtime/onMessage">browser.runtime.onMessage</a></code></td>
   <td><code><a href="/ja/Add-ons/WebExtensions/API/runtime#onMessage">browser.runtime.onMessage</a></code></td>
  </tr>
 </thead>
</table>

<div class="blockIndicator note">
<p>このワンオフメッセージを送る通信メソッドに加えて、<a href="/ja/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Connection-based_messaging">メッセージ交換するコネクションベースの方法</a>も使えます。これらのオプションを選択するアドバイスは、<a href="/ja/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Choosing_between_one-off_messages_and_connection-based_messaging">ワンオフメッセージとコネクションベースのメッセージのいずれかを選択する</a>を見てください。</p>
</div>

<p><span id="result_box" lang="ja"><span>例を更新して、バックグラウンドスクリプトからメッセージを送信する方法を示します。</span></span></p>

<p>始めに "background.js" を編集して、次のようにします。</p>

<pre class="brush: js">browser.contextMenus.create({
  id: "eat-page",
  title: "Eat this page"
});

function messageTab(tabs) {
  browser.tabs.sendMessage(tabs[0].id, {
    replacement: "Message from the extension!"
  });
}

function onExecuted(result) {
    var querying = browser.tabs.query({
        active: true,
        currentWindow: true
    });
    querying.then(messageTab);
}

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "eat-page") {
    let executing = browser.tabs.executeScript({
      file: "page-eater.js"
    });
    executing.then(onExecuted);
  }
});
</pre>

<p>次に、"page-eater.js" を挿入し、<code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query">tabs.query()</a></code> を使用し、現在アクティブなタブを取得し、<code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">tabs.sendMessage()</a></code> を使用し、<span id="result_box" lang="ja"><span>そのタブにロードされたコンテンツスクリプトにメッセージを送信します。</span></span> メッセージにはペイロード <code>{replacement: "Message from the extension!"}</code> があります。</p>

<p>次に "page-eater.js" を次のように更新します。</p>

<pre class="brush: js">function eatPageReceiver(request, sender, sendResponse) {
  document.body.textContent = "";
  var header = document.createElement('h1');
  header.textContent = request.replacement;
  document.body.appendChild(header);
}
browser.runtime.onMessage.addListener(eatPageReceiver);
</pre>

<p><span id="result_box" lang="ja"><span>今すぐページを処理する代わりに、コンテンツスクリプトは </span></span><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage">runtime.onMessage</a></code><span lang="ja"><span>を使ってメッセージを取得します。</span> <span>メッセージが到着すると、コンテンツスクリプトは前と同じコードを実行しますが、置換テキストは </span></span><code>request.replacement</code><span lang="ja"><span> から取得されます。</span></span></p>

<p><code><a href="/ja/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript()</a></code><span lang="ja"><span> は非同期関数であり、リスナーが "page-eater.js" に追加された後にのみメッセージを送信するために、"page-eater.js" を実行した後に呼び出される </span></span><code>onExecuted</code><span lang="ja"><span> を使用します。</span></span></p>

<div class="note">
<p>Ctrl+Shift+J (Mac では Cmd+Shift+J) を押します。もしくは <code>web-ext run --bc</code><a href="/ja/docs/Tools/Browser_Console">Browser Console</a> を開きバックグラウンドスクリプトの <code>console.log</code> を見ます。<span id="result_box" lang="ja"><span>または、</span></span> <a href="/ja/Add-ons/Add-on_Debugger">Add-on Debugger</a>  <span lang="ja"><span>を使用して、ブレークポイントを設定することもできます。</span> <span>現在、</span></span><a href="https://github.com/mozilla/web-ext/issues/759">web-ext から 直接 Add-on Debugger を起動する</a> 方法<span lang="ja"><span>はありません。</span></span></p>
</div>

<p><span id="result_box" lang="ja"><span>コンテンツスクリプトからバックグラウンドページにメッセージを戻したい場合は、</span></span> <code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage">runtime.sendMessage()</a></code><span lang="ja"><span> の代わりに </span></span><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">tabs.sendMessage()</a></code><span lang="ja"><span> を使用します</span></span></p>

<p>例:</p>

<pre class="brush: js">browser.runtime.sendMessage({
    title: "from page-eater.js"
});</pre>

<div class="note"><span id="result_box" lang="ja"><span>これらの例はすべて JavaScript を注入します。</span><span> </span></span><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS">tabs.insertCSS()</a></code> <span lang="ja"><span> 関数を使用してプログラムで CSS を挿入することもできます。</span></span></div>

<h2 id="Learn_more" name="Learn_more">関連項目</h2>

<ul>
 <li><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">Content scripts</a> ガイド</li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts</a></code> manifest キー</li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> manifest キー</li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript()</a></code></li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS">tabs.insertCSS()</a></code></li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">tabs.sendMessage()</a></code></li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage">runtime.sendMessage()</a></code></li>
 <li><code><a href="/ja/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage">runtime.onMessage</a></code></li>
 <li><code>content_scripts</code> を使用した例:
  <ul>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/borderify">borderify</a></li>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/emoji-substitution" rel="noopener">emoji-substitution</a></li>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a></li>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/page-to-extension-messaging">page-to-extension-messaging</a></li>
  </ul>
 </li>
 <li><code>tabs.executeScript()</code> を使用した例:
  <ul>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/beastify">beastify</a></li>
   <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/context-menu-copy-link-with-types">context-menu-copy-link-with-types</a></li>
  </ul>
 </li>
</ul>