[iOS]Content Blockerを作る

Posted on

Safariのコンテンツブロッカーアプリを作るために、ドキュメントを読んだので要約

  • Safairに対して、ブラウザの中のコンテンツをブロックするルールを与えることができる
    • hiding elements(要素を消す)
    • blocking loads(ロードしない)
    • stripping cookies(クッキーを取り除く)
  • containing app(app extensionを使うためのアプリ)をApp Storeに出すことでこの機能が使える
    • user actionに応答してリクエストを送ることで、extensionを提供したり初期化するcontextを定義する
  • アプリが起動すると、shared resourcesを通してcontaining appとやり取りしたり、直接Safariをやり取りをする
  • アプリは事前にどういうコンテンツをブロックするかをSafariに伝える

    • Safariはページをロードするときにはアプリとやり取りしないし、Xcodeがコンテンツブロッカーをバイトコードにコンパイルしているから
    • Content Blockerはユーザのヒストリーとかは見れないよ
  • Extension targetをcontaining appに追加する

    • File > New > Target -> Content Blocker Extension
  • コンテンツブロッカーの挙動は上記でつけた名前のフォルダに規定されている

    • action request completionHandler
    • JSONファイル
    • trigger,actionのdictionaryでルールを定義している
    • action: triggerがマッチしたときにどうするかをSafariに伝える
    • trigger: Safariにいつ関連するアクションを行うか伝える
    • property listファイル
    • entitlementsファイル

JSONファイルの編集

JSONファイル例

[
{
  "trigger": {
      ...
  },
  "action": {
      ...
  }
},
{
  "trigger": {
      ...
  },
  "action": {
      ...
  }
}
]

triggerの設定

  • url-filter keyが必須
    • URLに対してパターンマッチさせる
  • 他のkeysはオプショナル

"trigger": {
        "url-filter": ".*",
        "resource-type": ["image", "style-sheet"],
        "unless-domain": ["your-content-server.com", "trusted-content-server.com"]
}
  • パターン

    • .* すべてのstingにマッチ
    • . 何かのキャラクター
    • . .文字と一致
    • [a-b] アルファベットキャラクターの範囲で一致
    • (abc) 特定のキャラクターのグループに一致
    • + 前のtermが一回以上
    • * 前のキャラクターが0回以上
    • ? 前のキャラクターが0か1回
  • Trigger Field

    • url-filter-is-case-sensitive Booleanの値、デフォルトはfalse
    • if-domain URLドメインのstring配列. 特定ドメインのリストでアクションが動く.値は小文字のASCIIかnon-ASCIIのためのpunycode. subdomainとdomainにマッチさせるには先頭に*を追加する. unless-domainと同時には使えない
    • unless-domain URLドメインのstring配列.これ以外のドメインでアクションが動く.以下はif-domainと同じ. id-domainと同時に使えない
    • resource-type ブラウザがどうやって使うかを示すリソースタイプを示す.指定しないとすべてのタイプにマッチする
    • 有効なタイプ
      • document
      • image
      • style-sheet
      • script
      • font
      • raw(Any untyped load)
      • svg-document
      • media
      • popup
    • load-type 相互に排他な2つの値のうち1つを含むstring配列.指定しなければすべてのロードタイプにマッチ.
    • first-party リソースがメインページと同じスキーマ、ドメイン、ポートの場合動作
    • third-party メインページと異なるスキーマ、ドメイン、ポートの場合動作
    • if-top-url メインドキュメントの完全なURLのstring配列.アクションを特定のURLパターンに限定する.値は小文字のASCIIかnon-ASCIIのためのpunycode.unless-top-urlと同時に使えない
    • unless-top-url 上記の逆.if-top-urlと同時には使えない
  • Action

    • Safariはすべてのトリガーを評価して順に実行する.同じアクションはskipされる
    • パフォーマンスを良くするために、似たアクションはグループ化する
    • 1つ目のcontentsのロードをブロックするルール、次にcookiesをブロックするルール等
    • トリガーの評価は別のアクションを指定している最初のルールから続けられる
    • 2つのフィールドのみを持つ
    • type: 必須
    • selector: タイプがcss-display-noneのときのみ必須.ほかはオプショナル
"action": {
      "type": "css-display-none",
      "selector": "#newsletter, :matches(.main-page, .article) .news-overlay"
}
  • typeフィールド
    • block リソースのロードを止める.キャッシュがあったとしても無視する
    • block-cookies サーバに送信する前にクッキーを止める.Safariのプライバシーポリシーが受け入れられているクッキーだけがブロックできる.ignore-previous-rulesと組み合わせても、ブラウザのプライバシーセッティングは上書きできない
    • css-display-none CSSセレクターを指定して、要素を隠す.selectorフィールドはselector listを持つ.マッチしたelementはdisplay propertyがnoneになる
    • ignore-previous-rules 前のトリガーアクションを無効にする
    • make-https urlをhttpsに変える.ポート指定のURLやhttp以外のプロトコルには影響しない
  • selector field selector listを定義するstringを指定する.
    • typeがcss-display-noneのとき必須.それ以外のときはSafariに無視される
    • ,で分けて、個々のselector valueとして、CSSの識別子を指定する.SafariとWebKitのすべてのCSSセレクターをブロッキングルールに使える

クラス

とりあえず不明

JSONファイル以外がどういう役割なのかよくわからなかった。ここは触りながらやろう - action request completionHandler - property listファイル - entitlementsファイル