2017-10-22 5 views
2

サイドパネルを持つエクステンションを作成しようとしています。このサイドパネルには、ホストページの状態に基づいてアクションを実行するボタンがあります。クロムエクステンションから注入されたjsからグローバルjs変数にアクセス

私は、this exampleの後ろにサイドパネルを挿入し、ボタンをオンにすることができますリスナー。しかし、私はグローバルjs変数にアクセスすることができません。デベロッパーコンソールでは、ホストページのスコープ内で、私が従っている変数(variable-configの名前)を見ることができます。サイドパネルのコンテキスト(popup.html)に次のエラーが表示されるとき -
VM523:1 Uncaught ReferenceError:configが定義されていません。 popup.htmlも別のスレッドで実行されているようです。

ボタンのonClickハンドラのグローバル変数jsにアクセスするにはどうすればよいですか?

マイコード:

manifest.jsonを

{ 
    "manifest_version": 2, 

    "name": "Hello World", 
    "description": "This extension to test html injection", 
    "version": "1.0", 
    "content_scripts": [{ 
     "run_at": "document_end", 
     "matches": [ 
      "https://*/*", 
      "http://*/*" 
     ], 
     "js": ["content-script.js"] 
    }], 
    "browser_action": { 
     "default_icon": "icon.png" 
    }, 
    "background": { 
     "scripts":["background.js"] 
    }, 
    "permissions": [ 
     "activeTab" 
    ], 
    "web_accessible_resources": [ 
     "popup.html", 
     "popup.js" 
    ] 
} 

background.js

chrome.browserAction.onClicked.addListener(function(){ 
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs){ 
     chrome.tabs.sendMessage(tabs[0].id,"toggle"); 
    }) 
}); 

コンテンツ-script.js

chrome.runtime.onMessage.addListener(function(msg, sender){ 
    if(msg == "toggle"){ 
     toggle(); 
    } 
}) 

var iframe = document.createElement('iframe'); 
iframe.style.background = "green"; 
iframe.style.height = "100%"; 
iframe.style.width = "0px"; 
iframe.style.position = "fixed"; 
iframe.style.top = "0px"; 
iframe.style.right = "0px"; 
iframe.style.zIndex = "9000000000000000000"; 
iframe.frameBorder = "none"; 
iframe.src = chrome.extension.getURL("popup.html") 

document.body.appendChild(iframe); 

function toggle(){ 
    if(iframe.style.width == "0px"){ 
     iframe.style.width="400px"; 
    } 
    else{ 
     iframe.style.width="0px"; 
    } 
} 

popup.html

<head> 
<script src="popup.js"> </script> 
</head> 
<body> 
<h1>Hello World</h1> 
<button name="toggle" id="toggle" >on</button> 
</body> 

popup.js

document.addEventListener('DOMContentLoaded', function() { 
    document.getElementById("toggle").addEventListener("click", handler); 
}); 

function handler() { 
    console.log("Hello"); 
    console.log(config); 
} 
+0

私はホストページにアクセスできません。ホストページはchrome.storage.localに保存しません – Leon

+0

拡張JSはページJSと対話できません。彼らはドキュメントでそれを伝えます。 – Jerinaw

+0

@wOxxOmリンクをありがとう。私はそれに遭遇しましたが、それによって混乱するものもありました。私が理解するのを助けてくれますか?私は、JS変数を抽出してメッセージを送るために別のスクリプトを注入する必要がありますか? – Leon

答えて

4

ページJS変数を直接拡張からアクセスすることはできませんので、あなたがinsert code in script element so that it runs in the page contextに必要とリレーDOMメッセージングを介してコンテンツスクリプトに変更することができます。その後、コンテンツスクリプトはメッセージをiframeに中継することができます。

  • コンテンツスクリプト:

    runInPage(initConfigExtractor); 
    
    chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { 
        switch (msg) { 
        case 'toggle': 
         toggle(); 
         return; 
        case 'getConfig': 
         window.addEventListener(chrome.runtime.id + '-config', event => { 
         sendResponse(event.detail); 
         }, {once: true}); 
         window.dispatchEvent(new Event(chrome.runtime.id)); 
         return true; 
        } 
    }) 
    
    function initConfigExtractor(extensionId) { 
        window.addEventListener(extensionId,() => { 
        window.dispatchEvent(new CustomEvent(extensionId + '-config', { 
         detail: window.config, 
        })); 
        }); 
    } 
    
    function runInPage(fn) { 
        const script = document.createElement('script'); 
        document.head.appendChild(script).text = 
        '((...args) => (' + fn + ')(...args))(' + JSON.stringify(chrome.runtime.id) + ')'; 
        script.remove(); 
    } 
    
  • のiframeスクリプト:

    function handler() { 
        chrome.tabs.getCurrent(tab => { 
        chrome.tabs.sendMessage(tab.id, 'getConfig', config => { 
         console.log(config); 
         // do something with config 
        }); 
        }); 
    } 
    

だから、基本的には:

  1. のiframeスクリプトが取得します独自のタブIDとは、コンテンツスクリプト
  2. コンテンツスクリプトが以前に挿入ページのスクリプト
  3. ページのスクリプトが、そのDOMのメッセージを聞くにDOMメッセージを送るにメッセージを送信し、コンテンツスクリプト
  4. に戻って別のDOMメッセージを送信します
  5. コンテンツスクリプトはiframeスクリプトの応答に返信します。

すべてが非同期なので、メッセージチャネルを開いたままにするためにonMessageリスナーにreturn trueが必要でした。

+0

ありがとう。私は逃げなければなりませんが、数時間後にテストされます – Leon

+0

ありがとう、コードはほとんどそのままです。私はconfigがevent.detailsとして渡されていないので、少し問題がありました。私はこれがメンバーの1つが関数ポインタだからだと信じています。私は、全体の設定の代わりに必要なパラメータを選択的に渡すことで回避することができます。 – Leon

関連する問題