2016-09-22 2 views
0

バックグラウンドスクリプトオブジェクトにアクセスするにはクロムエクステンション内にコンテンツスクリプトを作成するにはどうすればよいですか?コンテンツスクリプトからバックグラウンドスクリプトオブジェクトにアクセスする

// this will store settings 
    var settings = {}; 

    // load settings from background 
    chrome.extension.sendMessage({ 
     name: "get-settings" 
    }, function(response) { 
     debugger; 
     settings = response.data.settings; 
    }); 

私が持っているバックグラウンドスクリプト内側::私が持っているコンテンツのスクリプトで

var Settings = function() { 
    var me = this; 
    // internal, default 
    var settingList = { 
     serverUrl : "http://automatyka-pl.p4", 
     isRecordingEnabled : true, 
     isScanEnabled : true 
    }; 

    this.get = function(key) { 
     return settingList[key]; 
    }; 
    this.set = function(key , value) { 
     if (settingList[key] != value) { 
      var setting = {}; 
      setting[key] = value; 

      chrome.storage.sync.set(setting, function() { 
       settingList[key] = value; 
      }); 
     } 
     return true; 
    }; 

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { 
    if (request.name == 'get-settings') { 
     sendResponse({ 
      data : { 
       settings : settings 
      } 
     }); 
     return true; 
    } 
}); 

var settings = new Settings(); 

Messagingは動作しますが、私は意味の応答が送信されますが、返されたオブジェクトは空です。あなたはそれを解決する方法を知っていますか?

EDIT あなたのコメントと回答に基づいて、私の質問に異なる光を追加しようとします。

実際の問題は次のとおりです。 コンテンツスクリプトから背景「モデル」にアクセスする方法

コンテンツスクリプトは、ページのDOM変更に連続して応答すると仮定します。変更が検出されると、コンテンツスクリプトの内部で処理が行われます。しかし、この処理は拡張設定に依存します。これらの設定は、ページアクションポップアップスクリプトを介して設定することができ、背景モデルにこれらの設定を通知します。

ので、いつでもページがコンテンツスクリプトで処理され、それは背景スクリプト内部に格納され現在の設定に注意する必要があります。

すでに説明したように、バックグラウンドから設定を引き出すのは非同期な処理なので、コンテンツスクリプト内でさらに処理するためにコールバックが必要です。それ以上の処理は設定を待つ必要があります(同期的に処理する必要があります)。

この場合、どのようなプログラムフローが表示されるのか想像がつきにくいです。

  1. 背景負荷
  2. ページの負荷を(初期化設定) - >コンテンツスクリプトのロード
  3. コンテンツスクリプトが設定を要求 - >更なる処理は、コールバック関数の内部で行われます。設定
  4. ユーザーの変更は、バックグラウンドの設定が変更された
  5. ページの変更がトリガされ、コンテンツスクリプトが応答
  6. コンテンツスクリプトは、設定を要求 - >さらなる処理がコールバック関数の内部で行われている - しかし、それは、PTのように同じ機能することはできません。 3(コンテンツ "モデル"は初期化する必要はありません)?
+0

すべてのクロム。*関数コールバックを持つAPIは非同期です。 「非同期呼び出しからの応答を返すにはどうすればよいですか?」(https://stackoverflow.com/q/14220321) – wOxxOm

+0

が見つかりました!私はコードを再構成する必要があるようだ。 –

+0

[非同期呼び出しから応答を返すにはどうすればよいですか?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) –

答えて

2
  1. のsendMessageは、オブジェクト自体を転送するが、唯一そのJSON-ifiable表現、 効果的objReceived = JSON.parse(JSON.stringify(objSent))ので、あなたのオブジェクトのsettingListは、それがシリアル化中に失われています目に見えない外側の関数コンテキストであるので、しません。

    あなたはstringifiable財産正常にコンテンツスクリプトに転送される

    this.settingList = { foo: 'bar' }; 
    

    を暴露することによって、それは公開することができます。

  2. メッセージングは​​、応答コールバックの内側にそれを行う必要があり、コンテンツのスクリプトで応答を使用し、asynchronousあるので:設定はの設定セッターで、あなたのコンテンツスクリプトの外に変更されているかどうかを知るために

    // this will store the settings 
    var settings = {}; 
    
    // load settings from background 
    chrome.runtime.sendMessage({ 
        name: "get-settings" 
    }, function(response) { 
        settings = response.data.settings; 
        onSettingsReady(); 
    }); 
    
    function onSettingsReady() { 
        // put your logic here, settings are set at this point 
    } 
    
  3. background.jsは、あなたのタブのコンテンツのスクリプトにメッセージを送信:

    this.set = function(key , value) { 
        ... 
        // notify active tab if settings changed 
        chrome.tabs.query({"windowType":"normal"}, function(tabs){ 
        for(id in tabs){ 
         if("id" in tabs[id]){ 
          chrome.tabs.sendMessage(tabs[id].id,{"action":"update-settings","settings":settings}); 
         } 
        } 
    }); 
        return true; 
    }; 
    
  4. およびコンテンツのスクリプトで聞くとプロセスのメッセージ:

    chrome.runtime.onMessage.addListener(function(msg){ 
        if("action" in msg && msg.action == 'update-settings'){ 
         // You are setting global settings variable, so on it will be visible in another functions too 
         settings = msg.settings; 
        } 
    }); 
    

詳細:https://developer.chrome.com/extensions/runtime#method-sendMessage

P.S.後者はChrome APIでは推奨されず、WebExtensions API(Firefox/Edge)では完全にサポートされていないため、chrome.extension.sendMessageではなくchrome.runtime.sendMessageを使用してください。

+0

さて、私は 'settingList'をpublicにしました。そして、実際には、それは、小道具は、コンテンツスクリプトで直列化され、再度取得することができます。しかし、とにかく 'sendMessage'の非同期性のため、コンテンツスクリプト内の設定オブジェクトは必要になる前に初期化されません。 –

+0

'settings = response.data.settings;のようなメッセージ受信者からのコールバックを使用します。 ready(); '' document.ready'コールバックの中で他のコードを実行します。これはあなたの質問の例ではリストされていない問題です。 – MobDev

+0

固定のサンプルコード – MobDev

0

コンテンツスクリプトにSettingsという別のインスタンスを追加するのはおそらく意味があります。

結局のところ、chrome.storage APIはコンテンツスクリプトで利用できます。

もちろん、拡張の他の部分の変更を監視する必要があります。ただし、あなたはchrome.storage.syncを使用していて、その値はChrome Syncによって独立して変更できるため、

ので、提案された解決策:

  1. 必要に応じて、あなたのsettingListを更新するためにchrome.storage.onChangedとプロセスの変更にリスナーを追加します。
  2. Storageロジックを別のJS「ライブラリ」に移動します。 storage.js
  3. コンテンツスクリプトにstorage.jsをロードして通常通り使用してください。

また、保存されたデータは実際が考慮されるように、ストレージ・ロジックを調整することをお勧めします - 今それは常にデフォルトです。

var defaultSettingList = { 
    serverUrl : "http://automatyka-pl.p4", 
    isRecordingEnabled : true, 
    isScanEnabled : true 
}; 
var settingList = Object.assign({}, defaultSettingList); 
chrome.storage.sync.get(defaultSettingList, function(data) { 
    settingList = Object.assign(settingList, data); 
    // At this point you probably should call the "ready" callback - initial 
    // load has to be async, no way around it 
}); 
関連する問題