Chrome Custom Tabs でもトラッキングの夢は見られない

# はじめに
つい先日、[SFSafariViewContoroller について調べた](http://qiita.com/akitaika_/items/8955a6f3ff5a8447f9e7)のですが、
Chrome Custom Tabs についても依頼があったので、

__ホームグラウンドｷﾀ━━━━(ﾟ∀ﾟ)━━━━!!__

と喜び勇んで調べてみたメモ

# やりたいこと
 + アプリと Chrome で Cookie を同期したい

# 結論
__無理！！__
例によって、言い訳していきます。

# カスタムは許されない
この辺は、SFSafariViewController と同じですね。
とはいえ、カスタムできない理由は SFSafariViewController と異なります。

以下、Chrome Custom Tabs の呼び出しのコードです。

```java
// ビルダーを使って Chrome Custom Tabs のインテントを生成
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder
        .setToolbarColor(Color.BLUE)
        .setShowTitle(true)
        .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
        .setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right)
        .build();

// Chrome Custom Tabs の開始
customTabsIntent.launchUrl(this, Uri.parse(url));
```

コードを見てわかるように、__呼び出しはインテントを利用__しています。
つまり、別アプリ＼(^o^)／
手出しなんて、しようがありません。

こいつの主機能も__「指定された URL にアクセスしてウェブページを表示する」だけ__です。

# でも、Cookieの共有は双方向　※
Chrome Custom Tabs と Chrome の Cookie 共有は、双方向です。
SFSafariViewController と手順で Google ログインを試したところ、どちらも OK でした。わーい！

| 手順 | 期待値 | 結果 |
|:-----|:-----|:-----|
| Chrome Custom Tabs からログイン → Chrome でログイン後のページを表示 | ログイン状態で表示される | OK |
| Chrome からログイン → Chrome Custom Tabs でログイン後のページを表示 | ログイン状態で表示される | OK |

Chrome Custom Tabs を経由せずに Chrome を立ち上げても同じ結果でした。
ここも SFSafariViewController とは異なりますね。

__ただし、アプリ側に Cookie をひっぱってこれないのは一緒。__

よく考えたら、コレできちゃうと脆弱性だよね。仕方ないね。

# 余談
本筋からずれちゃうので、余談として相違点とか Tips とか書いときます。

## SFSafariViewController との相違点
相違点は、以下の通り。

 + 表示対象のウェブページを先読みできる  
   → 誰かしら書いてるだろうと思ってここではコードとか省いてるけど、  
  　 先読みによって表示時のロード時間を短縮できます。  
  　 CustomTabsServiceConnection クラスを利用するので、CustomTabsService 的なものが待機していて、  
  　 それに対して、「この URL を読んどいてくれー」的に通知してるんだろうね。  
  　 ちゃんとコーディングしたら、また追記します。
 + サポートライブラリが提供されている  
   → 現在は、API 15 以上を対象としたサポートライブラリが存在しています。  
  　 Gradle への追記は「※1」な感じ。  
  　 先読みの時は、モジュールを[公式](https://github.com/GoogleChrome/custom-tabs-client)から持ってこないといけないらしいので、「※2」な感じ。
 + 端末側にバージョン 45 以上の Chrome のインストールが必要  
   → Chrome Custom Tabs に対応してないバージョンの Chrome だった場合や  
  　 Chrome ではなく、他のブラウザ系のアプリしかインストールされていない場合は、  
  　 __別アプリとしてブラウザ系のアプリが起動します。__  
  　 Chrome Custom Tabs として起動されません。  
  　 ちなみにブラウザ系アプリが端末に存在しない場合は、ActivityNotFoundException が発生します。  
  　 この辺りは、もろインテント利用時の動きですね。  

※1 単純に Chrome Custom Tabs を使う時の build.gradle（一部抜粋）

```text
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'

    // Chrome Custom Tabs のサポートライブラリ
    compile 'com.android.support:customtabs:23.1.0'
}
```

※2 Chrome Custom Tabs を先読みさせたい時の build.gradle（一部抜粋）

```text
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'

    // Chrome Custom Tabs のサポートライブラリ
    compile 'com.android.support:customtabs:23.1.0'

    // ↑を指定せずに、公式の customtabs モジュールを読み込んでもいい。
    // shared モジュールとバージョンを合わせたいという観点の時は、こっちの方がいいかも？
//    compile project(':customtabs')

    // 公式の shared モジュールの組み込み
    // サービスのバインド時に必要なパッケージ名をとってくるヘルパークラスがいるので、こいつは必須です。
    // （そこを自作するというなら、使わなくてもいい気がしないでもない）
    compile project(':shared')
}
```

## Chrome Custom Tabs のツールバーをアプリのアクションバーと同じ色にしたい
以下のようにすればできます。

```java
/**
 * テーマのプライマリーカラーを取得する
 *
 * @return プライマリーカラー
 */
private int getThemeColorPrimary() {
    final TypedValue typedValue = new TypedValue();
    getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
    return typedValue.data;
}

/**
 * アニメーションなしで Chrome Custom Tabs を起動
 * 
 * @param url 表示対象のURL
 */
private void launchCustomTabs(Uri url) {
    // ビルダーを使ってカスタムタブのインテントを生成
    CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
    CustomTabsIntent customTabsIntent = builder
            .setToolbarColor(getThemeColorPrimary()) // ← ここで指定
            .setShowTitle(true)
            .build();

    // カスタムタブの開始
    customTabsIntent.launchUrl(this, url);
}
```

# まとめ
 + 双方向の共有ができるけど、アプリでの利用はできないよ！
 + 実態は、別アプリだよ！たぶん iframe 的に Chrome が入れ子されてるよ！
 + Android 好きだよ！

# 参考
 + GoogleChrome/custom-tabs-client · GitHub  
   https://github.com/GoogleChrome/custom-tabs-client
 + How to get accent color programmatically?  
   http://stackoverflow.com/questions/27611173/how-to-get-accent-color-programmatically