Samouczek: przenoszenie do platformy Manifest V2

Wersja Manifest 1 została wycofana w Chrome 18, a jej obsługa będzie stopniowo wyłączana zgodnie z harmonogramem obsługi wersji Manifest 1. Zmiany z wersji 1 na wersję 2 można podzielić na 2 szerokie kategorie: zmiany w interfejsie API i zmiany dotyczące bezpieczeństwa.

W tym dokumencie znajdziesz listy kontrolne dotyczące migracji rozszerzeń do Chrome z wersji manifestu 1 na wersję 2, a także bardziej szczegółowe podsumowania tego, co oznaczają te zmiany i dlaczego zostały wprowadzone.

Lista kontrolna zmian w interfejsie API

  • Czy korzystasz z właściwości browser_actions czy z interfejsu chrome.browserActions API?

  • Zastąp browser_actions pojedynczą właściwością browser_action.

  • Zastąp chrome.browserActions tekstem chrome.browserAction.

  • Zastąp właściwość icons właściwością default_icon.

  • Zastąp właściwość name właściwością default_title.

  • Zastąp właściwość popup właściwością default_popup (która musi być teraz ciągiem znaków).

  • Czy korzystasz z właściwości page_actions czy z interfejsu chrome.pageActions API?

  • Zastąp page_actions tekstem page_action.

  • Zastąp chrome.pageActions tekstem chrome.pageAction.

  • Zastąp właściwość icons właściwością default_icon.

  • Zastąp właściwość name właściwością default_title.

  • Zastąp właściwość popup właściwością default_popup (która musi być teraz ciągiem znaków).

  • Czy używasz właściwości chrome.self?

  • Zastąp elementem chrome.extension.

  • Czy używasz właściwości Port.tab?

  • Zastąp elementem Port.sender.

  • Czy korzystasz z interfejsu API chrome.extension.getTabContentses() czy chrome.extension.getExtensionTabs()?

  • Zastąp elementem chrome.extension.getViews( { "type" : "tab" } ).

  • Czy Twoje rozszerzenie korzysta ze strony w tle?

  • Zastąp właściwość background_page właściwością background.

  • Dodaj właściwość scripts lub page, która zawiera kod strony.

  • Dodaj persistentwłaściwość i ustaw jej wartość na false, aby przekonwertować stronę w tle na stronę zdarzenia.

Lista kontrolna zmian dotyczących bezpieczeństwa

  • Czy używasz bloków skryptu wbudowanego na stronach HTML?

  • Usuń kod JS zawarty w tagach <script> i umieść go w zewnętrznym pliku JS.

  • Czy używasz wbudowanych funkcji obsługi zdarzeń (np. onclick)?

  • Usuń je z kodu HTML, przenieś do zewnętrznego pliku JS i zamiast nich użyj addEventListener().

  • Czy rozszerzenie wstrzykuje skrypty dotyczące zawartości na strony internetowe, które muszą mieć dostęp do zasobów (takich jak obrazy i skrypty) zawartych w pakiecie rozszerzenia?

  • Zdefiniuj właściwość web_accessible_resources i wymień zasoby (opcjonalnie możesz też podać oddzielne (standard) Content Security Policy dla tych zasobów).

  • Czy Twoje rozszerzenie osadza zewnętrzne strony internetowe?

  • Zdefiniuj właściwość sandbox.

  • Czy Twój kod lub biblioteka używa eval(), nowego Function(), innerHTML, setTimeout() lub w inny sposób przekazuje ciągi kodu JS, które są dynamicznie oceniane?

  • Użyj JSON.parse(), jeśli analizujesz kod JSON w celu utworzenia obiektu.

  • Używaj biblioteki zgodnej z CSP, np. AngularJS.

  • Utwórz w pliku manifestu wpis piaskownicy i uruchom w niej odpowiedni kod, używając postMessage() do komunikacji ze stroną w piaskownicy.

  • Czy wczytujesz kod zewnętrzny, np. jQuery lub Google Analytics?

  • Rozważ pobranie biblioteki i spakowanie jej w rozszerzeniu, a następnie załadowanie jej z lokalnego pakietu.

  • Umieść na liście dozwolonych domenę HTTPS, która obsługuje zasób w sekcji „content_security_policy” pliku manifestu.

Podsumowanie zmian w interfejsie API

Wersja 2 pliku manifestu wprowadza kilka zmian w interfejsach API działań przeglądarki i działań na stronie oraz zastępuje kilka starych interfejsów API nowszymi.

Zmiany w działaniach w przeglądarce

Interfejs API działań w przeglądarce wprowadza pewne zmiany w nazwach:

  • Właściwości browser_actionschrome.browserActions zostały zastąpione ich odpowiednikami w liczbie pojedynczej: browser_actionchrome.browserAction.
  • W starej usłudze browser_actions były usługi icons, namepopup. Zastąpiliśmy je tymi:

  • default_icon – ikona plakietki czynności wykonywanej w przeglądarce;

  • default_name w przypadku tekstu, który pojawia się w etykietce po najechaniu kursorem na plakietkę.

  • default_popup w przypadku strony HTML, która reprezentuje interfejs działania przeglądarki (musi to być teraz ciąg znaków, a nie obiekt);

Zmiany w działaniach na stronie

Podobnie jak w przypadku zmian w działaniach przeglądarki, zmienił się też interfejs API działań na stronie:

  • Właściwości page_actionschrome.pageActions zostały zastąpione ich odpowiednikami w liczbie pojedynczej: page_actionchrome.pageAction.
  • W starej usłudze page_actions były usługi icons, namepopup. Zostały one zastąpione tymi:

  • default_icon w przypadku ikony plakietki czynności wykonywanej na stronie.

  • default_name w przypadku tekstu, który pojawia się w etykietce po najechaniu kursorem na plakietkę.

  • default_popup w przypadku strony HTML, która reprezentuje interfejs działania na stronie (musi to być teraz ciąg znaków, a nie obiekt);

Usunięte i zmienione interfejsy API

Niektóre interfejsy API rozszerzeń zostały usunięte i zastąpione nowymi odpowiednikami:

  • Właściwość background_page została zastąpiona właściwością background.
  • Właściwość chrome.self została usunięta. Użyj właściwości chrome.extension.
  • Właściwość Port.tab została zastąpiona właściwością Port.sender.
  • Interfejsy API chrome.extension.getTabContentses()chrome.extension.getExtensionTabs() zostały zastąpione interfejsem chrome.extension.getViews( { "type" : "tab" } ).

Podsumowanie zmian dotyczących bezpieczeństwa

Przejście z wersji 1 na wersję 2 pliku manifestu wiąże się z wieloma zmianami dotyczącymi bezpieczeństwa. Wiele z tych zmian wynika z wdrożenia w Chrome standardu Content Security Policy. Aby zrozumieć jego konsekwencje, zapoznaj się z nim.

Skrypty wbudowane i moduły obsługi zdarzeń są niedozwolone

Ze względu na użycie Content Security Policy nie możesz już używać tagów <script>, które są wstawione w treści HTML. Muszą one zostać przeniesione do zewnętrznych plików JS. Dodatkowo nie są obsługiwane wbudowane procedury obsługi zdarzeń. Załóżmy na przykład, że w rozszerzeniu masz ten kod:

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

Ten kod spowoduje błąd w czasie działania. Aby rozwiązać ten problem, przenieś zawartość tagu <script> do zewnętrznych plików i odwołuj się do nich za pomocą atrybutu src='path_to_file.js'.

Podobnie nie będą wykonywane wbudowane procedury obsługi zdarzeń, które są powszechnie stosowane i stanowią wygodną funkcję dla wielu programistów internetowych. Na przykład:

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

Nie będą one działać w rozszerzeniach platformy Manifest V2. Usuń wbudowane moduły obsługi zdarzeń, umieść je w zewnętrznym pliku JS i użyj funkcji addEventListener(), aby zarejestrować dla nich moduły obsługi zdarzeń. Na przykład w kodzie JS użyj:

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

To znacznie lepszy sposób na oddzielenie działania rozszerzenia od znaczników interfejsu.

Umieszczanie treści

W niektórych przypadkach rozszerzenie może osadzać treści, które mogą być używane zewnętrznie lub pochodzić ze źródła zewnętrznego.

Treści rozszerzenia na stronach internetowych: jeśli rozszerzenie umieszcza zasoby (np. obrazy, skrypty, style CSS itp.), które są używane w skryptach treści wstrzykiwanych na strony internetowe, musisz użyć właściwości web_accessible_resources, aby dodać te zasoby do listy dozwolonych, tak aby zewnętrzne strony internetowe mogły ich używać:

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

Osadzanie treści zewnętrznych: standard Content Security Policy zezwala na wczytywanie z pakietu tylko lokalnych skryptów i obiektów, co uniemożliwia zewnętrznym atakującym wprowadzenie do rozszerzenia nieznanego kodu. Czasami jednak chcesz wczytywać zasoby obsługiwane zewnętrznie, takie jak jQuery lub kod Google Analytics. Można to zrobić na dwa sposoby:

  1. Pobierz odpowiednią bibliotekę lokalnie (np. jQuery) i spakuj ją z rozszerzeniem.
  2. Możesz w ograniczonym zakresie zmniejszyć ograniczenia CSP, dodając do listy dozwolonych źródła HTTPS w sekcji „content_security_policy” w manifeście. Aby uwzględnić bibliotekę, np. Google Analytics, wykonaj te czynności:

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

Korzystanie z dynamicznej oceny skryptu

Jedną z największych zmian w nowym schemacie manifestu w wersji 2 jest to, że rozszerzenia nie mogą już używać dynamicznych technik oceny skryptów, takich jak eval() lub nowy Function(), ani przekazywać ciągów kodu JavaScript do funkcji, które spowodują użycie eval(), np. setTimeout(). Dodatkowo niektóre popularne biblioteki JavaScript, takie jak Mapy Google i określone biblioteki szablonów, korzystają z tych technik.

Chrome udostępnia piaskownicę, w której strony mogą działać w swojej domenie. Nie mają one dostępu do chrome.*. interfejsy API, Aby korzystać z eval() i podobnych funkcji w ramach nowych zasad Content Security Policy:

  1. Utwórz wpis piaskownicy w pliku manifestu.
  2. W pozycji piaskownicy wymień strony, które mają być w niej uruchamiane.
  3. Używaj przekazywania wiadomości za pomocą postMessage() do komunikacji ze stroną w piaskownicy.

Więcej informacji o tym, jak to zrobić, znajdziesz w dokumentacji Sandboxing Eval.

Więcej informacji

Zmiany w wersji 2 pliku manifestu mają na celu zachęcenie programistów do tworzenia bezpieczniejszych i solidniejszych rozszerzeń oraz aplikacji. Pełną listę zmian w pliku manifestu w wersji 1 w porównaniu z wersją 2 znajdziesz w dokumentacji pliku manifestu. Więcej informacji o używaniu piaskownicy do izolowania niebezpiecznego kodu znajdziesz w artykule sandboxing eval. Więcej informacji o zasadach bezpieczeństwa treści znajdziesz w samouczku dotyczącym rozszerzeń oraz w dobrym wprowadzeniu na stronie HTML5Rocks.