SoundCloudはどうやってタブ間で同期を取っているか


僕の好きな音楽共有サイトの一つに「SoundCloud」というサービスがあります。
日本人もたくさん投稿していて、カッコイイEDMもかなり投稿されてるので、作業用BGMによく利用させてもらっています。
そのSoundCloudでどうやって実装されてるのか興味深い箇所があったので、調べる過程も含めて共有します。

複数タブ(又はウィンドウ)で情報を同期してくれる機能が便利で不思議

20130312
SoundCloudを複数ページ開いた状態で、片方のタブで再生中に別タブの再生ボタン(上の画像で黒で囲んである左側のボタン)を押すと、もう片方の再生が止まるんですよね。
また、ボリュームコントロール(上の画像で黒で囲んである右側のボタン)も、片方のタブで調整するともう片方のタブに自動的に反映されます。
YouTubeでタブ毎に音量調整する癖がついてたので、「おおっ」と少し感動してしまいましたw

どうやって実装してる?

JavaScriptで他のタブに直接アクセスする事は出来ないはず。
じゃあサーバを介して情報をやりとりしてるのかな?と思ってChrome devtoolsで通信を監視してみました。

20130312_2
通信してない…!
ボリュームコントロールをいじってみた所、通信が発生していないのに別タブで再生中の楽曲の音量が変わりました。
つまり、クライアント側の処理だけでタブ間同期を実現しているということ。

クライアントでタブ間で共通して使えるリソースといえば…

CookieかlocalStorageを使っている可能性が高い。
→どちらかを使っていれば、ボリュームを変更した時にそのどちらかの値が書き換わっているはず!

ということで、またdevtoolsで以下のjavascriptを実行してみました。

cookieの値が変化しているか確認

  1. ボリュームを変更する操作をする前に以下を実行。
    console.log(document.cookie);
  2. 実行結果をコピーして、SoundCloudの画面上のボリュームを変更。
  3. 以下を実行。
    console.log(document.cookie === '__qca=...'); // 右項は上記1.の実行結果の文字列のコピペ
  4. trueと表示されたらCookieの値が変更されていない。falseなら変更されてる。

実行結果

true
ふむ。Cookieはこの機能に利用されていない様子。

localStorageの値が変化しているか確認

  1. ボリュームを変更する操作をする前に以下を実行。(localStorageはオブジェクトなので、テキスト化するためにちょっと余計な事してます)
    console.log(escape(JSON.stringify(localStorage)));
  2. 実行結果をコピーして、SoundCloudの画面上のボリュームを変更。
  3. 以下を実行。
    console.log(escape(JSON.stringify(localStorage)) === '%7B%22V2%3A%3Alocal...'); // 右項は上記1.の実行結果の文字列のコピペ
  4. trueと表示されたらlocalStorageの値が変更されていない。falseなら変更されてる。

実行結果

false
きた!!!変更されてるのでタブ間同期にlocalStorageが利用されている可能性が高い。
localStorageの内容を見ると「V2::local::volume-settings: “{“volume”:0.5}”」というフィールドがあったので、この値を各タブで共有して音量情報を同期してるっぽいです。

どうやってlocalStorageの変更を監視しているか?

localStorageの変更時に’storage’イベントが発火するようなので、多分それを利用してるんじゃないかと(ソースは読んでない)。
このイベント、localStorageを変更したウィンドウ以外のウィンドウでも発火するんですね。意外。

W3Cの仕様書の「4.4 The storage event」の章に以下の記述があるので、これがタブ間の同期に利用されている仕様なんでしょうかね。。(英語得意じゃないのであんまり自信ないです)

When this happens, the user agent must queue a task to fire an event with the name storage, which does not bubble and is not cancelable, and which uses the StorageEvent interface, at each Window object whose Document object has a Storage object that is affected.

まとめ

  • SoundCloudの複数ウィンドウ間の同期にはlocalStorageのstorageイベントが使われてるっぽい。
  • 異なるウィンドウ同士の同期にlocalStorageが使える、ということだけでも覚えておくと役に立つかも。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です