誰かが入力するとChrome拡張機能が表示される

一部の人々は、ソーシャルネットワークに多くの時間を費やしています。 彼らはすでに中毒になっているほどです。 そのうちの1人はプログラマーのAlexander Kirszenbergで、ユーザーインターフェイスと通信を担当するJavaScriptコードでFacebookの内部を詳しく調べることも好きです。
「数か月前、私はあなたの友人の1人があなたのためにタイプしていることを示す小さなステータスインジケータについて考えました」とアレクサンダーは書いています 。 -UIのこのような小さな拡張は、対話者に関する多くの情報を提供します。 インジケータが点灯し、数回消灯する場合、これは未決定を示します。 彼が長い間火をつけたら、誰かがあなたに素晴らしいエッセイを書いてくれます。 そして、インジケーターが消えて点灯しなくなったときの耐え難い気持ちほど悪いことはありません。」
まず、Alexanderは、Facebook Messengerを実行していない場合でも、Facebook Messengerで誰かがメッセージを入力しているという通知をFacebookが送信するかどうかを判断することにしました。 彼が送っていたことが判明した。
typ
"long poll"
/pull
(long polling)のイベントは、すべての友人に送信されます。 小規模な調査によると、受信者がチャットを開かず、受信しなかったとしても、イベントは実際に各チャットごとに送信されます 。
これが、Chromeブラウザ用のFacebookの拡張機能であるSixth Senseの誕生です。 誰かがFacebookの投稿を入力すると、ブラウザーに表示されます。

プログラマーは、文書化されていないFacebook APIを使用してこの拡張機能を作成しました。 Facebookが冷酷に縮小してJavaScriptのコードを処理しなければならず、文字の寄せ集めに変わりました。
最初に、彼はFacebookが非同期読み込みのために非同期モジュール定義モジュール編成システムを介してインポートするモジュールを見つけました(Facebookには独自のAMD実装があります)。 モジュールと依存関係は、標準の
__d(name, dependencies, factory)
関数
__d(name, dependencies, factory)
によって定義されます。 モジュールをインポート
require
および
requireLazy
も
require
ます。
これがどのように機能するかを確認する最も簡単な方法は、ブラウザコンソールで行うことです(ただし、Facebookはこれを禁止しています)。 真面目な人はそこで働いているようです。冗談を言ってはいけません。

しかし、私たちはまだあえて。

ご覧のとおり、Facebookは常に最新バージョンのReact (ユーザーインターフェイスコンポーネントの優れたライブラリ)をダウンロードします。 Facebookはサイト全体でReactをかなり頻繁に使用しています。 Facebookコードには15,000を超えるReactコンポーネントがあります(2015年10月現在)。
ソースコードで
__d(
を検索できます
__d(
インポートに使用できるモジュールのリストを参照してください。メインページには、3000のモジュールしかありません。
もちろん、Facebook MessengerもReactコンポーネントを使用しています。 入力通知を傍受する必要があります。 コードのより詳細な研究のために、Alexander KirzenbergはReact Developer Toolsの使用を推奨しています 。


この拡張機能をインストールすると、Chromeデベロッパーツールに新しい[React]タブが表示されます。 チャットを選択します。

ここでは、Facebook Messengerのさまざまなコンポーネントの中で、
<ChatTabComposerContainer />
と
<MercuryLastMessageIndicator />
間にある入力インジケーターを探しています。
__d('ChatTyping
検索します
__d('ChatTyping
Reactコードベース
__d('ChatTyping
は、
ChatTypingIndicator.react.js
と
ChatTypingIndicators.react.js
2つのモジュールを検出します。これがまさに必要なものです、Kirzenbergが書いています。
ChatTypingIndicators.react.js
は2回目にのみ検出できます。
これが彼のコードです。
function() { var k = c('MercuryThreadInformer').getForFBID(this.props.viewer) , l = c('MercuryTypingReceiver').getForFBID(this.props.viewer); this._subscriptions = new (c('SubscriptionsHandler'))(); this._subscriptions.addSubscriptions( l.addRetroactiveListener( 'state-changed', this.typingStateChanged ), k.subscribe( 'messages-received', this.messagesReceived ) ); },
つまり、
c('MercuryTypingReceiver')
呼び出すことに興味があります。
コンソールで、その仕組みを確認できます。
> MercuryTypingReceiver.getForFBID // function (i){var j=this._getInstances();if(!j[i])j[i]=new this(i);return j[i];} > MercuryTypingReceiver.get // function (){return this.getForFBID(c('CurrentUser').getID());}
ステータスインジケータの動作を確認するために、アレキサンダーは自分のスマートフォンのメッセンジャーアプリケーションを使用して、対応するイベントをPCに送信し、コンソールでキャッチしました。
コードをさらに詳しく調べた結果、
MercuryThreads
と
ShortProfiles
2つの有用なモジュールが見つかりました。 1つ目は、メッセンジャースレッドに関するすべての情報をその識別子で取得し、2つ目はプロファイルに対して同じことを行います。
一般に、すべての調査の後、Chromeの最終的な拡張コードは次のようになります。わずか40行です。
function getUserId(fbid) { return fbid.split(':')[1]; } requireLazy( ['MercuryTypingReceiver', 'MercuryThreads', 'ShortProfiles'], (MercuryTypingReceiver, MercuryThreads, ShortProfiles) => { MercuryTypingReceiver .get() .addRetroactiveListener('state-changed', onStateChanged); // Called every time a user starts or stops typing in a thread function onStateChanged(state) { // State is a dictionary that maps thread ids to the list of the // currently typing users ids' const threadIds = Object.keys(state); // Walk through all threads in order to retrieve a list of all // user ids const userIds = threadIds.reduce( (res, threadId) => res.concat(state[threadId].map(getUserId)), [] ); MercuryThreads.get().getMultiThreadMeta(threadIds, threads => { ShortProfiles.getMulti(userIds, users => { // Now that we've retrieved all the information we need // about the threads and the users, we send it to the // Chrome application to process and display it to the user. window.postMessage({ type: 'update', threads, users, state, }, '*'); }); }); } } );
Facebookの内部をわずかに明らかにする良いハック。
拡張機能のソースコードはGithubで公開されています。
ちなみに、Facebookメッセンジャーからのタイムスタンプによると、友達のスリープモード ( ソースコード )を追跡することもできます。
