2016-05-19 22 views
1

私は、windowオブジェクトのプロパティjQueryを、設定スクリプトのコードを含むコンテンツスクリプトから定義しようとしています。このようにして、実際のjQueryオブジェクトが定義されたらすぐに使用できます。私はそれを正しく得ることができないようだ。どのようにしてタブのメインウィンドウオブジェクトにプロパティを定義できますか?

対象のWebサイトはOutlook.comです。それはOutlookのウェブメール版です。

私が直接コンテンツスクリプト内のコードを入れてみましたが、私はマニフェストのcontent_scriptsセクションに"all_frames": trueを入れても、(そのコードはすべてのフレームに注入します)、それが機能していません。

function afterInit(){ 
    var _jQuery; 
    console.log('This gets logged'); 
    Object.defineProperty(window, 'jQuery', { 
    get: function() { return _jQuery; }, 
    set: function(newValue) { 
     _jQuery = $ = newValue; 

     console.log('This is never logged!'); 

     $(document.body).append($('<span>I want to use jQuery here</span>')); 
    } 
    }); 
} 
afterInit(); 

私はwindow.jQueryが適切に実際のjQuery機能/オブジェクトによって、後で定義されていることを確認し、私のセッター・コードが実行されることはありません。
私はメッセージの受け渡しでそれを試しました。文字列としてのコードを含むメッセージをバックグラウンドスクリプトに送り、executeScriptを使って正しいタブでそれを実行しますが、これも機能しません。

chrome.runtime.sendMessage(
    {action:'jQueryPreInit', value: '('+afterInit.toString()+')();'}); 

そして、私のバックグラウンドスクリプトで:

chrome.runtime.onMessage.addListener(function(message, sender, callback) { 
    switch (message.action){ 
    case "jQueryPreInit": chrome.tabs.executeScript(sender.tab.id, {code: message.value}); 
    } 
}); 

私は正常に動作executeScriptコード、中Object.definePropertyコード以外の何かを置く場合。私はプロパティを定義する際に問題があります。

+0

簡単な質問:なぜこの複雑なダンスをやっていますか? – Xan

+0

私は、ページ自体が提供するjQueryを使用したいと思います。私は、Outlookと同じjQueryファイルを挿入しようとする可能性があり、キャッシュからロードされることを期待していますが、私はエクステンションをできるだけきれいに保ち、すでに利用可能なものを使用します。 すべてのことが言われて終了したら、私はjQueryの 'ajaxSuccess'関数を使用して、読み取りウィンドウで電子メールが開かれるたびにコードを実行します。 –

答えて

1

ザンのおかげで、私はこれを行う方法が2つしかないことを発見しました。

まず、<script>要素を適切なコードを含むDOMに追加します。これはかなり広範なStackOverflowの答えです:https://stackoverflow.com/a/9517879/125938

2番目はJavascript疑似URLとwindow.locationオブジェクトを使用しています。 window.locationにJavascriptを含むブックマークレットスタイルのURLを割り当てることで、特定のセキュリティ対策をバイパスすることもできます。コンテンツスクリプトでは、置く:https://developer.chrome.com/extensions/content_scripts#execution-environment

location = 'javascript:(' + (function(){ 
    var _jQuery; 
    Object.defineProperty(window, 'jQuery', { 
    get: function() { return _jQuery; }, 
    set: function(newValue) { 
     _jQuery = $ = newValue; 

     console.log('totally logged!'); 

     $('<span>jQuery stuff here</span>'); 

    } 
    }); 
}).toString().replace(/\n/g, ' ')+')();'; 

をI /あなたは、もともと私たちが使っていたコードインジェクションの両方の方法ので、それを定義した失敗した理由は、私たちのコードが分離された世界にサンドボックス化される原因となりました。つまり、彼らはページのDOMを共有し、それを介して通信することができますが、お互いのwindowオブジェクトに直接アクセスすることはできません。

2

私はページ自体が提供するjQueryのを使用したい

(引用符は、コメントからです)。私は、Outlookと同じjQueryファイルを挿入しようとする可能性があり、キャッシュからロードされることを期待していますが、私はエクステンションをできるだけきれいに保ち、すでに利用可能なものを使用します。

エクステンションの最適化は実行できません。

まず、the isolation between content script and webpage codeのためにページのコードを使用することはできません。ページの自分のjQuery/$への参照を取得することはできません。

しかし、しばらくお待ちください。そして、サイトはjQueryを別のバージョンに更新し、jQueryオブジェクトの名前を変更するか、コントロールの外側にあるオブジェクト全体の使用を停止します。結果:あなたの内線が壊れています。これは部分的には、最初の分離の背後にある論理的根拠です。

コンテキスト分離の結果、jQueryのコピーとサイト上で実行されているものとの間に競合がないことが保証されます。したがって、あなたはそれについて心配する必要はありません:あなたのコピーを使用し、標準$を使ってアクセスしてください。

バンドルエクステンションを1回限りのダウンロードとして使用すると、コードが使用可能になり、最悪のディスクアクセス待ち時間では「きれい」にはなりません。それは一般的な練習で、enshrined in the docsです。


あなたの実際のコードを見てみると、そうではありませんページコンテキストに、(それはマニフェストまたはexecuteScriptを通じてだかどうかにかかわらず)コンテンツスクリプトコンテキストで実行されます。したがって、ページの内容に関係なく、$は定義されません。

私はwindow.jQueryが適切に実際のjQueryの関数/オブジェクトによって、後で定義されていることを確認し、[...]

私はあなたがコンソールにwindow.jQueryを実行しようとしたことを前提としています。デフォルトではexecutes it in the page context, not in your content script contextです(したがって、コンテンツスクリプトのコンテキストの状態は反映されず、ゲッター/セッターは呼び出されません)。コンテンツスクリプトをテストする場合は、コンソール上のコンテキストドロップダウンのtopを拡張機能のコンテキストに変更する必要があります。すべての作業を完了すると


言ったことすべてが、しかし、

は、私は、コードに電子メールを読む]ペインで開かれるたびに実行するためにjQueryのajaxSuccess機能を使用します。

ここに問題があります。コンテンツスクリプトコードとウェブページコードは分離されているので、あなたのコードはページのコピー内で実行しているAJAXについては決して知りません(とにかくajaxSuccess経由ではありません)。アクションの

可能なコース:

  1. は、あなたがしたいイベントを検出するための他の方法に依存しています。おそらくmonitoring the DOM
  2. 一部のコードを入力into the page itself;そうする唯一の方法は、コンテンツスクリプトのページに<script>タグを挿入することです。ここで、ページのjQueryのコピーにアクセスし、リスナーを添付して、何かが起きたときにmessage your content scriptを呼び出すことができます。
  3. webRequest APIで必要なアクティビティを検出するためにバックグラウンドページに依存してください。これはおそらくAJAXの呼び出しを傍受しますが、あなたに返答の内容は与えません。

最後の注意:これはAJAX呼び出しほど単純ではないかもしれません。おそらくページはWebSocket接続を維持してリアルタイムプッシュ更新を取得します。 Tapping into thisはやわらかいです。

+0

私の_problem_を解決しようとしていますが、あなたは私の_question_に答えなかったことを感謝します。私は自分の問題を解決するために別のルートをとることができることを知っていますが、この問題は私の問題に対するちょっとした解決策を見つけることではなく、なぜ特定の解決策が機能していないのかについてです。また、すでにコンテンツスクリプトとして、またバックグラウンドスクリプトからexecuteScriptを使用して、コード自体にコードを挿入しています。しかし、jQueryは両方の注入時間にまだロードされていません。したがって、この複雑なダンス。 –

+0

私はあなたのポイントを見ます。それでも、 '$'はあなたのコンテンツスクリプトの文脈では決して初期化されません(そして 'executeScript'はページにではなく)。 – Xan

+0

私はあなたの_question_をより良く扱ったと思います。 – Xan

関連する問題