aboutsummaryrefslogtreecommitdiff
path: root/files/de/mozilla/add-ons/sdk/guides/content_scripts/index.html
blob: a94176f2cbf6fefe79c1bc5eb1ff30eec9c3e291 (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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
---
title: Content Scripts
slug: Mozilla/Add-ons/SDK/Guides/Content_Scripts
translation_of: Archive/Add-ons/Add-on_SDK/Guides/Content_Scripts
---
<article id="wikiArticle">
<p><span class="seoSummary">Viele Add-ons müssen den Inhalt von Webseiten modifizieren oder auf diesen zugreifen können. Der Grundcode des Add-on  bekommt aber keinen direkten Zugriff auf Webinhalte. Stattdessen müssen SDK Add-ons den Code,  der Zugriff auf Webinhalte erhält in seperate Skripte auslagern, die sogenannten "Content Scripts". Diese Seite beschreibt wie man Content Scripts entwickelt und diese implementiert. </span></p>

<p>Content Scripts sind einer der verwirrenderen Aspekte beim Arbeiten mit der SDK, aber Sie werden mit Sicherheit mit ihnen arbeiten müssen. Es gibt fünf grundlegende Prinzipien:</p>

<ul>
 <li>Der Grundcode des Add-ons, wie zum Beispiel "main.js" und andere module im "lib" Verzeichnis, können die <a href="/de/Add-ons/SDK/High-Level_APIs">high-level</a> und <a href="/de/Add-ons/SDK/Low-Level_APIs">low-level</a> APIs benutzen, aber nicht direkt auf Webinhalte zugreifen.</li>
 <li>Content Skripts <a href="/de/Add-ons/SDK/Guides/Two_Types_of_Scripts#API_Access_for_Add-on_Code_and_Content_Scripts">können keine SDK APIs</a> ( kein Zugang zu <code>exports</code>, <code>require</code>), dafür aber auf Webinhalte zugreifen.</li>
 <li>SDK APIs, die Content Skripts verwenden, wie zum Beispiel <a href="/de/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a> und <a href="/de/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>, bieten Funktionen die es dem Grundcode des Add-ons ermöglichen Content Skripts  in eine Weebseite zu laden.</li>
 <li>Content Skripts können als Strings geladen werden, werden aber öfter in seperaten Dateien im Add-on Ordner "data" abgespeichert. Jpm erzeugt keinen "data" Ordner, daher muss dieser manuell hinzugefügt werden und ihr Content Scrikt dort abgespeichert werden.</li>
 <li>Eine Nachricht übertragende API erlaubt es dem Grundcode und dem Content Skript miteinander zu kommunizieren.</li>
</ul>

<p>Dieses komplette Add-on zeigt alle diese Prinzipien. Die "main.js" hängt ein Content Skript an den aktuellen Tab, mittels den <a href="/de/Add-ons/SDK/High-Level_APIs/tabs">tabs </a>Modules, an. In diesem Fall wird der Content Skript in Form eines Strings übergeben. Das Content Skript ersetzt einfach nur den Inhalt der Seite:</p>

<pre class="brush: js">// main.js
var tabs = require("sdk/tabs");
var contentScriptString = 'document.body.innerHTML = "&lt;h1&gt;Diese Seite wurde aufgegessen&lt;/h1&gt;";'

tabs.activeTab.attach({
  contentScript: contentScriptString
});</pre>

<p>Die folgenden high-level SDK Module können Content Skripts benutzen, um Webseiten zu bearbeiten:</p>

<ul>
 <li><a href="/de/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>: Erlaubt es Ihnen Content Skripts bei Webseiten, die mit einem bestimmten URL Muster übereinstimmen, einzusetzen.</li>
 <li><a href="/de/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>: Exportiert ein Tab Objekt um mit einem Browser Tab zu arbeiten.Das Tab Objekt beinhaltet eine Funktion <a href="/de/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>attach()</code></a> um dem Skript Content Skripte anzuhängen.</li>
 <li><a href="/de/Add-ons/SDK/High-Level_APIs/page-worker">page-worker</a>:  Lässt Sie eine Webseite erhalten ohne diese anzuzeigen. Sie können diesen Seiten Content Skripte anhängen, die DOM der Seite erreichen oder diese maniulieren.</li>
 <li><a href="/de/Add-ons/SDK/High-Level_APIs/context-menu">context-menu</a>: Hiermit können Sie ein Content Skript benutzen um mit einer Seite zu interagieren, in der das Menü aufgerufen ist.</li>
</ul>

<p>Zusätzlich sind manche SDK Benutzeroberflächen Komponenten - Panel, Sidebar, frames - darauf ausgelegt HTML zu benutzen und haben deshalb seperate Skripte um mit ihrem Inhalt zu interagieren. In vielen Punkten sind diese Skripte wie Content Skripte, aber dies ist nicht Teil dieses Artikels. Um mehr über die Interaktion des Inhalts eines Benutzeroberflächenmoduls zu erfahren, schauen Sie sich die modulspezifischen Dokumentationen: <a href="/de/Add-ons/SDK/High-Level_APIs/panel">panel</a>, <a href="/de/Add-ons/SDK/Low-Level_APIs/ui_sidebar">sidebar</a>, <a href="/de/Add-ons/SDK/Low-Level_APIs/ui_frame">frame </a>an.</p>

<p>Fast alle diese Beispiele, die in dieser Anleitung präsentiert werden, sind als komplette, aber minimalistische, Add-ons in der<a href="https://github.com/mdn/addon-sdk-content-scripts"> addon-sdk-content-scripts repository</a> auf Github vorhanden.</p>

<h2 id="Content_Skripts_laden">Content Skripts laden</h2>

<article id="wikiArticle">
<p>Sie können ein einzelnes Skript laden, indem Sie einen String an die <code>contentScript</code> oder die <code>contentScriptFile</code> Option übergeben. Die <code>contentScript</code> Option behandelt den übergebenen String wie ein eigenes Skript:</p>

<pre class="brush: js">// main.js

var pageMod = require("sdk/page-mod");
var contentScriptValue = 'document.body.innerHTML = ' +
                         ' "&lt;h1&gt;Page matches ruleset&lt;/h1&gt;";';

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScript: contentScriptValue
});</pre>

<p><code>Die contentScriptFile</code> Option behandelt den String wie eine resource:// URL, die auf ein Skript zeigt, dass in ihrem Add-on Verzeichnis "data" gespeichert ist. jpm erstellt standardmäßig keinen "data" Ordner, also muss dieser erst erstellt werden, wenn Sie ihre Content Scripts verwenden wollen.</p>

<p>Das Add-on liefert eine URL, die auf die Datei "content-script.js" zeigt, welche im <code>data</code> Unterordner des Add-on Stammverzeichnisses enthalten ist:</p>

<pre class="brush: js">// main.js

var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScriptFile: data.url("content-script.js")
});</pre>

<pre class="brush: js">// content-script.js

document.body.innerHTML = "&lt;h1&gt;Seite erfüllt die Regeln.&lt;/h1&gt;";</pre>

<div class="note">
<p>Ab Firefox 34 , kann "./content-script.js" als Alias für self.data.url("content-script.js") verwendet werden. Die main.js kann also auch folgendermaßen geschrieben werden:</p>

<pre class="brush: js">var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScriptFile: "./content-script.js"
});
</pre>
</div>

<div class="warning">
<p>Wenn ihr Content Skript nicht sehr simpel ist oder aus einem statischen String besteht, sollten Sie <code>contentScript</code>:  nicht benutzen. Wenn Sie es doch tun, könnten Sie Probleme haben Ihr Add.on auf AMO verifiziert zu bekommmen.</p>

<p>Stattdessen sollten Sie ihr Skript in einer seperaten Datei schreiben und mit<code> contentScriptFile</code> laden. Das macht ihren Code übersichtlicher und er ist einfacher zu Warten, sichern und debuggen.</p>
</div>

<p>Sie können auch mehrere Skripte in <code>contentScript oder contentScriptFile laden, indem Sie ein Array von Strings übergeben:</code></p>

<pre class="brush: js">// main.js

var tabs = require("sdk/tabs");

tabs.on('ready', function(tab) {
  tab.attach({
      contentScript: ['document.body.style.border = "5px solid red";', 'window.alert("hi");']
  });
});
</pre>

<pre class="brush: js">// main.js

var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScriptFile: [data.url("jquery.min.js"), data.url("my-content-script.js")]
});</pre>

<p>Wenn Sie das tuen, können die Skripte direkt miteinander kommunizieren, als wären es Skripte der gleichen Webseite.</p>

<p>Sie können auch <code>contentScript und contentScriptFile zusammen benutzen.</code> Wenn Sie das tun, werden die Skripte, die sie in <code>contentScriptFile spezifizieren vor denen in contentScript geladen. Das ermöglicht es Ihnen javaScript Bibliotheken, wie JQuery über eine URL zu laden und dann ein simples Skript inline zu verwenden, dass diese Bibliothek benutzt:</code></p>

<pre class="brush: js">// main.js

var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");

var contentScriptString = '$("body").html("&lt;h1&gt;Page matches ruleset&lt;/h1&gt;");';

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScript: contentScriptString,
  contentScriptFile: data.url("jquery.js")
});</pre>

<div class="warning">
<p>Wenn ihr Content Skript nicht sehr simpel ist oder aus einem statischen String besteht, sollten Sie <code>contentScript</code>:  nicht benutzen. Wenn Sie es doch tun, könnten Sie Probleme haben Ihr Add.on auf AMO verifiziert zu bekommmen.</p>

<p>Stattdessen sollten Sie ihr Skript in einer seperaten Datei schreiben und mit<code> contentScriptFile</code> laden. Das macht ihren Code übersichtlicher und er ist einfacher zu Warten, sichern und debuggen.</p>
</div>

<h3 id="Kontrollieren_wann_das_Skript_angehängt_werden_soll.">Kontrollieren, wann das Skript angehängt werden soll.</h3>

<p>Die <code>contentScriptWhen</code> Option spezifiziert, wann das/die Content Skript/e geladen werden sollen. Diese brauch eine dieser Parameter:</p>

<ul>
 <li><code>"start"</code>: Läd das Skript sofort, nach dem das Dokumentelement der Seite in den DOM eingefügt wird. ZU diesem Zeitpunkt wurde der DOM Inhalt noch nicht geladen,, deshalb kann das Skript nicht damit interagieren.</li>
 <li><code>"ready"</code>: Läd das Skript nachdem der DOM der Seite geladen wurde: Dies ist der Fall, wenn das <a href="https://developer.mozilla.org/de/Gecko-Specific_DOM_Events">DOMContentLoaded Event  </a>abgefeuert wird. Ab diesem Zeitpunkt können Content Skripts mit dem DOM interagieren, aber extern referenzierte Stylesheets und Bilder könnten noch nicht geladen sein.</li>
 <li><code>"end"</code>: Läd das Skript nachdem der komplette Inhalt (DOM, JS, CSS, images) der Seute geladen wurde. Zu diesem Zeitpunkt wird das <a href="https://developer.mozilla.org/de/DOM/window.onload">window.onload event</a> abgefeuert.</li>
</ul>

<p>Der Standardwert ist <code>"end"</code>.</p>

<p>Die Funktion <a href="/de/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>tab.attach()</code></a> akzepiert contentScriptWhen nicht, da es generell aufgerufen wird wenn die Seite geladen wurde.</p>

<h3 id="Übergabe_von_Konfigurationsoptionen">Übergabe von Konfigurationsoptionen</h3>

<p>Das <code>contentScriptOptions</code> Objekt ist ein JSON Objekt, das den Content Skripts als "read-only" Wert als <code><a href="/de/Add-ons/SDK/Guides/Content_Scripts/self">self</a>.options Eigenschaft</code> übergeben wird:</p>

<pre class="brush: js">// main.js

var tabs = require("sdk/tabs");

tabs.on('ready', function(tab) {
  tab.attach({
      contentScript: 'window.alert(self.options.message);',
      contentScriptOptions: {"message" : "hello world"}
  });
});</pre>

<p>Jeder Wert (Objekt, Feld, String, etc), dass in JSON dargestellt werden kann, kann hier benutzt werden.</p>

<h2 id="Zugriff_auf_den_DOM">Zugriff auf den DOM</h2>

<p>Content Skripts können natürlich wie jedes andere Skript, dass die Seite geladen hat ( Page Skripts) auf den DOM zugreifen. Content Skripts und Page Skripts sind wie folgt von einander isoliert:</p>

<ul>
 <li>Content Skripts sehen keine JavaScript Objekte, die der Seite über Page Skripts hinzugefügt wurden.</li>
 <li>Auch wenn ein Page Skript das Verhalten eines DOM Objekts verändert hat, sieht das Content Skript nur das Originalverhalten.</li>
</ul>

<p>Das gleiche gilt auch umgekehrt: Page Skripts sehen keine JavaScript Objekte, die von Content Skripts hinzugefügt wurden.</p>

<p>Stellen Sie sich eine Seite vor, die zum Beispiel eine Variable <code>foo</code> über ein Page Skript zum <code>window</code> Objekt hinzufügt:</p>

<pre class="brush: html">&lt;!DOCTYPE html"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;script&gt;
    window.foo = "hello from page script"
    &lt;/script&gt;
  &lt;/head&gt;
&lt;/html&gt;</pre>

<p>Ein anderes Skript, dass nach diesem Skript in die Seite geladen wird, kann auf <code>foo </code>zugreifen. Ein Content Skript kann dies nicht:</p>

<pre class="brush: js">// main.js

var tabs = require("sdk/tabs");
var mod = require("sdk/page-mod");
var self = require("sdk/self");

var pageUrl = self.data.url("page.html")

var pageMod = mod.PageMod({
  include: pageUrl,
  contentScript: "console.log(window.foo);"
})

tabs.open(pageUrl);</pre>

<pre>console.log: my-addon: null
</pre>

<p>Es gibt gute Gründe für diese Isolation. Erstens können Content Skripts so keine Objekte an Webseiten übermitteln und somit Sicherheitslücken schaffen. Zweitens können Content Skripts so Objekte erzeugen, ohne sich Sorgen machen zu müssen, dass diese mit Objekten kollidieren, die in Page Skripts erzeugt wurden.</p>

<p>Die Isulation bedeutet, dass wenn zum Beispiel eine Webseite die JQuery Bibliothek läd, das Content Skript nicht in der Lage ist dieses zu sehen, aber eine eigene JQuery Bibliothek laden kann ohne das es ein Problem mit der Version gibt, die über das Page Skript hinzugefügt wurde.</p>

<h3 id="Interaktion_mit_Page_Skripts">Interaktion mit Page Skripts</h3>

<p>Normalerweise möchte man Content Skripts und Page Skripts voneinander isolieren. Wenn dies nicht der Fall ist, da Sie zum Beispiel Objekte zwischen beiden Skripten austauschen wollen, oder Nachrichten zwischen ihnen schicken wollen können Sie mehr zum Thema unter  <a href="https://developer.mozilla.org/de/Add-ons/SDK/Guides/Content_Scripts/Interacting_with_page_scripts">Interaktion mit Page Skripts</a> finden.</p>

<h3 id="Event_Listeners">Event Listeners</h3>

<p>Man kann in Content Skripts genau wie in einem Page Skript auf DOM Events warten. Es gibt nur zwei wichtige Unterschieden:</p>

<p>Erstens: Falls Sie einen Event Listener als String an <a href="https://developer.mozilla.org/de/DOM/element.setAttribute"><code>setAttribute()</code></a> übergeben, wird der Listener im Seitenkontext ausgeführt und hat somit keinen Zugriff auf Variablen, die im Content Skript definiert wurden.</p>

<p>Zum Beispiel, wird dieses Content Skript mit der Fehlermeldung "theMessage is not defined" ausgeben:</p>

<pre class="brush: js">var theMessage = "Hello from content script!";
anElement.setAttribute("onclick", "alert(theMessage);");</pre>

<p>Zweitens: Falls Sie einen Event Listener per direkter Zuweisung einem <a href="/de/docs/Web/API/GlobalEventHandlers">globalen Event Handler</a>  wie <code>onclick zuweisen</code>, könnten Zuweisungen, die die Seite vornimmt überschrieben werden. Zur Veranschaulichung ist hier ein Add-on, das versucht einen click Handler per Zuweisung an window.onclick anzufügen:</p>

<pre class="brush: js">var myScript = "window.onclick = function() {" +
               "  console.log('unsafewindow.onclick: ' + window.document.title);" +
               "}";

require("sdk/page-mod").PageMod({
  include: "*",
  contentScript: myScript,
  contentScriptWhen: "start"
});</pre>

<p>Das wird auf den meisten Seiten funktionieren, bis auf denen, die ebenfalls ein onclick zuweisen:</p>

<pre class="brush: html">&lt;html&gt;
  &lt;head&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;script&gt;
    window.onclick = function() {
      window.alert("it's my click now!");
    }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>

<p>Aus diesen Gründen ist es besser Event Listeners per <a href="https://developer.mozilla.org/de/DOM/element.addEventListener"><code>addEventListener()</code></a> hinzuzufügen. So definieren Sie einen Listener als Funktion:</p>

<pre class="brush: js">var theMessage = "Hello from content script!";

anElement.onclick = function() {
  alert(theMessage);
};

anotherElement.addEventListener("click", function() {
  alert(theMessage);
});</pre>

<h2 id="Kommunikation_mit_dem_Add-on">Kommunikation mit dem Add-on</h2>

<p>Damit Add-On Sktipts und Content Skripts miteinander kommunizieren können, haben beide Seiten der Konversation Zugriff auf ein <code>port</code> Objekt.</p>

<ul>
 <li>Um eine Nachricht von einer Seite zur anderen zu schicken nutzen Sie <code>port.emit()</code></li>
 <li>Um eine Nachricht von der anderen Seite zu empfangen nutzen <code>port.on()</code></li>
</ul>

<p><img alt="" src="https://mdn.mozillademos.org/files/7873/content-scripting-overview.png" style="display: block; margin-left: auto; margin-right: auto;">Nachrichten sind asyncron, was bedeutet, dass der Sender nicht wartet, bis er eine Antwort des Empfängers erhält, sondern die Nachricht schickt und das weiter arbeitet.</p>

<p>Hier ist ein simples Beispieladd-on, das eine Nachricht an ein Content Skript per <code>port </code>schickt:</p>

<pre class="brush: js">// main.js

var tabs = require("sdk/tabs");
var self = require("sdk/self");

tabs.on("ready", function(tab) {
  worker = tab.attach({
    contentScriptFile: self.data.url("content-script.js")
  });
  worker.port.emit("alert", "Message from the add-on");
});

tabs.open("http://www.mozilla.org");</pre>

<pre class="brush: js">// content-script.js

self.port.on("alert", function(message) {
  window.alert(message);
});</pre>

<div class="note">
<p>Das context-menu Modul benutzt das Kommunikationsmodul, das hier beschrieben wird nicht. Um etwas über die Kommunikation mit geladenen Content Skripts im context-menu zu erfahren, schauen Sie in die <a href="/de/Add-ons/SDK/High-Level_APIs/context-menu">context-menu Dokumentation</a>.</p>
</div>

<h3 id="Zugriff_auf_port_im_Content_Skript">Zugriff auf port im Content Skript</h3>

<p>Im Content Skript ist das port Objekt als Eigenschaft im globalen Objekt<a href="/de/Add-ons/SDK/Guides/Content_Scripts/self"><code> self</code></a> verfügbar. So versenden Sie eine Nachricht vom Content Skript:</p>

<pre class="brush: js">self.port.emit("myContentScriptMessage", myContentScriptMessagePayload);</pre>

<p>Um eine Nachricht vom Add-on Code zu bekommen:</p>

<pre class="brush: js">self.port.on("myAddonMessage", function(myAddonMessagePayload) {
  // Handle the message
});</pre>

<div class="note">
<p><span>Das globale <a href="/de/Add-ons/SDK/Guides/Content_Scripts/self"><code>self</code></a> Objekt ist etwas komplett anderes als das <a href="https://developer.mozilla.org/de/Add-ons/SDK/High-Level_APIs/self">self Modul</a>, das einer API in einem Add-on die Möglichkeit bietet auf Daten und die ID des Add-ons zuzugreifen.</span></p>
</div>

<h3 id="Zugriff_auf_port_im_Add-on_Skript">Zugriff auf port im Add-on Skript</h3>

<p>Im Add-on Code ist das Bindeglied zur Kommunikation zwischen Add-on und einem spezifischen Content Skript das  <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker"><code>worker</code></a> Objekt. Das <code>port Objekt ist also eine Eigenschaft des</code>  <code>worker</code> Objekts.</p>

<p>Der worker wird aber im Add-on Code nicht von allen Modulen gleich verwendet.</p>

<h4 id="Vom_page-worker"><code>Vom page-worker</code></h4>

<p><code>Das page-worker</code> Objekt integriert die worker API direkt. Um also eine Nachricht von einem Content Skript zu erhalten, das mit dem page-worker assoziiert wird benutzt man <code>pageWorker.port.on()</code>:</p>

<pre class="brush: js">// main.js

var pageWorkers = require("sdk/page-worker");
var self = require("sdk/self");

var pageWorker = require("sdk/page-worker").Page({
  contentScriptFile: self.data.url("content-script.js"),
  contentURL: "http://en.wikipedia.org/wiki/Internet"
});

pageWorker.port.on("first-para", function(firstPara) {
  console.log(firstPara);
});</pre>

<p>Um eine benutzerdefinierte Nachricht vom Add-on zu schicken, nutz man <code>pageWorker.port.emit()</code>:</p>

<pre class="brush: js">// main.js

var pageWorkers = require("sdk/page-worker");
var self = require("sdk/self");

pageWorker = require("sdk/page-worker").Page({
  contentScriptFile: self.data.url("content-script.js"),
  contentURL: "http://en.wikipedia.org/wiki/Internet"
});

pageWorker.port.on("first-para", function(firstPara) {
  console.log(firstPara);
});

pageWorker.port.emit("get-first-para");</pre>

<pre class="brush: js">// content-script.js

self.port.on("get-first-para", getFirstPara);

function getFirstPara() {
  var paras = document.getElementsByTagName("p");
  if (paras.length &gt; 0) {
    var firstPara = paras[0].textContent;
    self.port.emit("first-para", firstPara);
  }
}</pre>

<h4 id="Vom_page-mod"><code>Vom page-mod</code></h4>

<p>Ein einziges  <code>page-mod</code> Objekt kann ein Skript an mehrere Seiten anhängen. Jede dieser Seiten hat ihren eigenen Context, in dem sie dieses Skript aufrufen. Daher benötigt es seperate Kanäle(worker) für jede Seite.</p>

<p><code>page-mod</code> integriert also die worker API nicht direkt, sondern es wird jedes Mal wenn ein Content Skript an eine Seite angehängt wird das <code>attach</code> Event aufgerufen,  dessen listener einen worker für den Kontext übergeben bekommt. Durch das bereit stellen eines listeners bei attach kann man das port Objekt für das Content Skript, dass dieser Seite angefügt wurde über diesen page-mod verwenden:</p>

<pre class="brush: js">// main.js

var pageMods = require("sdk/page-mod");
var self = require("sdk/self");

var pageMod = pageMods.PageMod({
  include: ['*'],
  contentScriptFile: self.data.url("content-script.js"),
  onAttach: startListening
});

function startListening(worker) {
  worker.port.on('click', function(html) {
    worker.port.emit('warning', 'Do not click this again');
  });
}</pre>

<pre class="brush: js">// content-script.js

window.addEventListener('click', function(event) {
  self.port.emit('click', event.target.toString());
  event.stopPropagation();
  event.preventDefault();
}, false);

self.port.on('warning', function(message) {
  window.alert(message);
});
</pre>

<p>Im oben gezeigten Add-on gibt es zwei Nachrichten:</p>

<ul>
 <li><code>click</code> wird vom page-mod an das Add-on geschickt, wenn der Nutzer auf ein Element auf der Seite klickt</li>
 <li><code>warning</code> schickt einen String zurück an den page-mod</li>
</ul>

<h4 id="Von_Tab.attach()"><code>Von Tab.attach()</code></h4>

<p><code>Die Tab.attach()</code> methode liefert einen worker zurück, den man zur Kommunikation mit dem/den Content Skript/Content Skripts, die angehängt wurden, verwenden kann.</p>

<p>Das Add-on fügt einen Button zu Firefox hinzu: Wenn der Benutzer den Button drückt, fügt das Add-on ein Content Skript an den aktuellen Tab an. Das Skript sendet eine Nachricht namens "my-addon-message" und wartet auf eine Antwort namens "my-script-response":</p>

<pre class="brush: js">//main.js

var tabs = require("sdk/tabs");
var buttons = require("sdk/ui/button/action");
var self = require("sdk/self");

buttons.ActionButton({
  id: "attach-script",
  label: "Attach the script",
  icon: "./icon-16.png",
  onClick: attachScript
});

function attachScript() {
  var worker = tabs.activeTab.attach({
    contentScriptFile: self.data.url("content-script.js")
  });
  worker.port.on("my-script-response", function(response) {
    console.log(response);
  });
  worker.port.emit("my-addon-message", "Message from the add-on");
}
</pre>

<pre class="brush: js">// content-script.js

self.port.on("my-addon-message", handleMessage);

function handleMessage(message) {
  alert(message);
  self.port.emit("my-script-response", "Response from content script");
}</pre>

<h3 id="Die_port_API">Die port API</h3>

<p>Schaue unter <a href="/de/Add-ons/SDK/Guides/Content_Scripts/port">der Referenzseite für das port Objekt</a>.</p>
</article>

<h3 id="Die_postMessage_API">Die postMessage API</h3>

<p>bevor das port Objekt hinzugefügt wurde, kommunizierten Add-on Code und Content Skripts über eine andere API:</p>

<ul>
 <li>Das Content Skript rief <code>self.postMessage()</code> auf, um zu senden und <code>self.on() um zu empfangen.</code></li>
 <li>Das Add-on Skript rief <code>worker.postMessage()</code> auf, um zu senden und  <code>worker.on()</code> um zu empfangen</li>
</ul>

<p>Die API ist immer noch verfügbar und <a href="/de/Add-ons/SDK/Guides/Content_Scripts/using_postMessage">dokumentiert</a>, aber es gibt keinen Grund sie statt der port API zu verwenden, die hier beschrieben wird. Die Ausnahme bildet das<a href="/de/Add-ons/SDK/High-Level_APIs/context-menu"> context-menu</a> Modul, welches immer noch postMessage verwendet.</p>

<h3 id="Content_Skript_zu_Content_Skript">Content Skript zu Content Skript</h3>

<p>Content Skripts können nur direkt miteinander kommunizieren, wenn diese im gleichen Kontext geladen wurden. Beispiel: Wenn ein einziger Aufruf von  <code>Tab.attach()</code>  zwei Content Skripts anhängt, können diese sich gegenseitig sehen. Wenn aber <code>Tab.attach() </code>zweimal aufgerufen wird, und die Content Skripts einzeln anhängt,können die Content Skripte nicht miteinander kommunizieren. Dann müssen die Nachrichten über die  port API über den Add-on code gesendet werden.</p>

<h2 id="Cross-domain_Content_Skripts">Cross-domain Content Skripts</h2>

<p>Grundsätzlich hat ein Content Skript keine cross-domain Privilegien. Sie können also keinen Inhalt eines iframes auslesen, wenn dieser Inhalt von einer anderen Domain stammt, oder XMLHttpRequests an eine andere Domain schicken.</p>

<p>Um dieses Feature für spezielle Domains hinzuzufügen fügen Sie dem <a href="/de/Add-ons/SDK/Tools/package_json">package.json </a>ihres Add-ons den Schlüssel <code>"cross-domain-content" </code>unter dem <code>"permissions"</code> Schlüssel hinzu. Siehe dafür den Artikel  <a href="/de/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts">cross-domain content scripts</a>.</p>
</article>