iOS9のコンテンツブロッカー

WWDCで新しいiOS9の機能がいろいろと発表されましたが、Safariでの表示項目を制限することが 「コンテンツブロッカー」機能については、Web業界の方はちょっと気になるのではないでしょうか。 さっそく調べてみました。

(なお、この記事はAppleが一般に公開している情報を元に書いています)

コンテンツブロッカー

コンテンツブロッカーとはiOSやMacでSafariに表示する項目を、自動的に制限してくれる機能です。

iOSでは、コンテンツブロッカーは、Today WidgetやShare ExtensionのようにApp Extensionとして提供されます。

Mobile Safariでwebを見る時に、cssで指定された特定の要素を非表示にしたり、特定のファイルを読み込まないようにすることができます。

Safari以外のブラウザ(Chromeなど)には影響がありません。 また、iOS9からの機能なので、iOS8までのユーザーにも影響がありません。 iOS9から導入された SFSafariViewControllerにも、このコンテンツブロッカーは適用されます。

コンテンツブロッカーの実装方法

コンテンツブロッカーは、App Extensionとして提供されています。 既存のアプリの一部の機能となるので、まずは本体となるアプリを作成します。

Xcodeでアプリを作ったら、メニューから「File」「New」「Target」を選び、「iOS-Application Extension」の「Content Blocker Extension」を選びます。

すると、コンテンツブロッカーのターゲットが追加され、「ActionRequestHandler.swift」と「blockerList.json」のファイルが生成されます。

コンテンツブロッカーでブロックする要素と条件は「blockerList.json」ファイルで設定します。 このファイルを変更すれば(ソースコードを編集しなくても)実装は終わりです。

元のページでは、試しにこちらのページの要素にコンテンツブロッカーを適用させてみましょう。

コンテンツを非表示にする

まずは、CSSの特定の要素を非表示にする方法です。 この記事の、タイトルの下の日付や著者名を消してみましょう。

「blockerList.json」には、複数の表示設定を追加することができ、ファイルの先頭から順番に適用されていきます。 それぞれの表示設定には、action要素とtrigger要素が必要です。 action要素は、処理についての設定、trigger要素は適用箇所の設定です。

日付のCSS要素

SafariのWeb Inspector機能を表示して、消したい部分のcss属性を確認します。

class属性は「byline」ですね。

そうすると、blockerList.jsonにtype:css-display-noneのaction要素を追加することでこの部分を非表示にすることができます。 action要素のselectorには"div.byline"を指定します。 (selectorの設定はCSS Selectors Level 4に準拠しています)

trigger要素でこの条件の適用場所の指定ができますが、ここでは、必須項目のurl-filterだけ追加します。 正規表現が利用可能なので、すべてのURLに適用されるように".*"としておきます。

[
    {
        "action": {
            "type": "css-display-none",
            "selector" : "div.byline"
        },
        "trigger": {
            "url-filter": ".*"
        }
    } 
]

ついでに、facebookのlikeボタンも消してみましょう。 同じく、Web Inspector機能で確認すると、divのclass属性はwsbl_facebook_likeですね。

facebookのCSS要素

それを追加するとblockerList.jsonはこうなります。

[
    {
        "action": {
            "type": "css-display-none",
            "selector" : "div.byline"
        },
        "trigger": {
            "url-filter": ".*"
        }
    },
 
    {
        "action": {
            "type": "css-display-none",
            "selector" : "div.wsbl_facebook_like"
        },
        "trigger": {
            "url-filter": ".*"
       }
    }

]

この設定でさきほどのページを表示すると、こうなります。

日付を消したページ

タイトルの下の日付や著者名の部分と、facebookのlikeボタンの表示が消えていますね。

コンテンツをブロックする

さて、次は、コンテンツの読み込みをブロックしてみましょう。

さきほどの記事の、先頭に表示された画像のよみこみをブロックしてみます。

Web Inspector機能で確認すると、画像のURLはhttp://www.toyship.org/wp-content/uploads/2014/03/XcodeScreen-636x310.pngです。 さきほどの「blockerList.json」にtype:blockのaction要素を追加すると、この画像の読み込みをブロックすることができます。

[
    {
        "action": {
            "type": "css-display-none",
            "selector" : "div.byline"
        },
        "trigger": {
            "url-filter": ".*"
        }
    },
 
    {
        "action": {
            "type": "css-display-none",
            "selector" : "div.wsbl_facebook_like"
        },
        "trigger": {
            "url-filter": ".*"
       }
    },
 
    {
        "action": {
            "type": "block"
        },
        "trigger": {
            "url-filter": "/wp-content/uploads/2014/03/",
            "if-domain": ["www.toyship.org"]
        }
    }
 
]

画像の読み込みを消したページ

画像の読み込みブロックだけではなく、特定のjsファイルやcssファイルのブロックもできるので、使い方によってはサイトの機能がかなり変わる場合もありますね。

コンテンツブロッカーで、実際にどんなコンテンツがブロックされたのかはアプリで知ることはできません。

また、もしブロックされた要素がキャッシュされていた場合にも、読み込みはブロックされます。

クッキーをブロックする

動作確認はしていませんが、上記と同じ手順でtype:block-cookiesのaction要素を追加することでクッキーのブロックもできます。

コンテンツブロッカーの設定方法

さて、上記の手順でコンテンツブロッカーを含むアプリを作ることができますが、これをユーザーがSafariで有効にするためには下記の手順が必要です。

  • コンテンツブロッカーを含むアプリをダウンロードする
  • Safariの設定の「コンテンツブロッカー」の項目から、インストールしたアプリのコンテンツブロッカーを選んでonにする

その他

「blockerList.json」の設定方法については、詳しくはIntroduction to WebKit Content Blockersをみてください。

なお、これはまだWebKitで開発中の機能なので、バグやリクエストなどがあれば、WebKit Engineerの Benjamin Poulain(@awfulben)さんに言ってみるといいでしょう。

なお、ソースコードも公開されています。

まとめ

  • コンテンツブロッカーは、iOS9から搭載される機能。
  • コンテンツブロッカーをonにすると、特定のcss要素を非表示にしたり、特定のファイルやクッキーの読み込みをブロックすることができる。
  • コンテンツブロッカーはToday WidgetやShare Extensionのように、既存のアプリの一部として提供される。
  • コンテンツブロッカーは、何種類もインストールすることができる。
  • コンテンツブロッカーで何をブロックしたのかという情報は、コンテンツブロッカーを含むアプリで取得することはできない

上記は2015/6/14現時点でのiOSでの仕様であり、今後変わる可能性もあります。 また、ここで調べたのはiOSだけですが、MacOSXでも同様の機能がSafari Extensionとして提供されます。

参考リンク