2013-08-04 18 views
6

Na stronie tle mojego rozszerzenia Chrome muszę wykonać następujące czynności:Utwórz zakładkę i wstrzyknąć zawartość skrypt w to daje błąd uprawnień

  1. utworzyć kartę ze strony html który rezyduje w moim rozszerzeniu folder lub jest dynamicznie generowany przez stronę tła;
  2. po wczytaniu nowej karty należy wprowadzić do niej skrypt zawartości, aby użyć przekazywania wiadomości;
  3. po wstrzyknięciu skryptu, wyślij wiadomość do nowej karty z niektórymi danymi.

To zawsze zamienia się błąd:
tabs.executeScript: nie można uzyskać dostępu do zawartości URL "". Manifest rozszerzenia musi prosić o pozwolenie na dostęp do tego hosta.
lub, jeśli strona lub skrypt są przechowywane w dedykowanych plikach .html i .js w moim folderze rozszerzeń:
tabs.executeScript: Nie można uzyskać dostępu do zawartości adresu URL "chrome-extension: //ehdjfh.../page. html ". Manifest rozszerzenia musi prosić o pozwolenie na dostęp do tego hosta.

Błąd jest generowany po wykonaniu chrome.tabs.executeScript(), a wstrzyknięcie skryptu treści jest zablokowane. (Potrzebowałbym tej struktury, aby przekazać duże dane do karty, która zostanie obcięta, jeśli zostanie przekazana bezpośrednio jako ciąg do zakodowanego URL-a html)

Oto przykład kodu, który może być użyty do przetestowania zachowania w działającym rozszerzeniu , tylko kopiuj-wklej i załadować rozszerzenia w Chrome:

background.js

chrome.browserAction.onClicked.addListener(function() { 
    var getSampleHTML = function() { 
     return 'javascript:\'<!doctype html><html>' + 
      '<head></head>' + 
      '<body>' + 
      '<p id="myId">page created...</p>' + 
      '</body>' + 
      '</html>\''; 
    }; 

    // create a new tab with an html page that resides in extension domain: 
    chrome.tabs.create({'url': getSampleHTML(), 'active': false}, function(tab){ 
     var getSampleScript = function() { 
      return 'chrome.extension.onRequest.addListener(' + 
       'function(request, sender, sendResponse) {' + 
        'if(request.action == "print_data" && sender.tab.id == ' + tab.id + '){' + 
         'var p = document.getElementById("myId");' + 
         'p += "<br>data received: " + request.data;' + 
        '}' + 
       '});' 
       'document.getElementById("myId").innerHTML += "<br>content-script loaded...";' 
     }; 
     // inject the content-script in the page created: 
     chrome.tabs.executeScript(tab.id, {code: getSampleScript()}, function(){ 
      // send the data to the content-script: 
      chrome.tabs.sendRequest(tab.id, {action: "print_data", 
              data: "some long data"}); 
     }); 
    }); 
}); 

manifest.json

{ 
    "name": "ContentScript Injection Sample", 
    "description": "", 
    "version": "0.1", 
    "permissions": ["tabs"], 
    "background": { 
    "persistent": false, 
    "scripts": ["background.js"] 
    }, 
    "browser_action": { 
    "default_title": "open a new tab and inject contentscript" 
    }, 
    "manifest_version": 2 
} 
+1

Błąd dokładnie informuje, co jest nie tak. Musisz zadeklarować uprawnienia hosta, zobacz [wzorce dopasowania] (https://developer.chrome.com/extensions/match_patterns.html). –

+1

Jeśli chcesz udostępnić dane między różnymi stronami we własnym rozszerzeniu, możesz po prostu użyć polecenia 'chrome.extension.getViews' (https://developer.chrome.com/extensions/extension.html#method-getViews). Skrypty zawartości są używane (i mogą być używane) tylko do wstrzykiwania skryptów na strony internetowe. Przesyłanie wiadomości jest zwykle używane do komunikacji ze stronami internetowymi, skryptami treści lub * innymi * rozszerzeniami. –

+0

@RobW Zastanawiam się, w jaki sposób można ustawić wzorzec dopasowania w manifeście, aby umożliwić wykonanie skryptu treści wstrzykniętego w czasie wykonywania na stronę lokalną (przez wstawienie _ "rozszerzenie chrome: // */*" _ w "permissions" _, tak jak w przypadku zewnętrznych adresów URL http, daje błąd podczas ładowania manifestu rozszerzenia, ustawiając go w _ "matches" _ właściwość _ "content_scripts" _ to bzdura i daje również błąd, ponieważ nie ma żadnego _ "js" _ skryptu wstrzykiwać programowo) Podejrzewam, że mój ** background.js ** kod nie może być uruchomiony ze zmianą w ** manifest.json ** – guari

Odpowiedz

5

OK, jest to możliwe rozwiązanie, dzięki @RobW i @ 方 觉 za wskazanie mojego błędu (moim błędem było wzięcie pod uwagę lokalnej strony otwartej na nowo utworzonej karcie jako zwykłej strony internetowej, zamiast tego ma ona bezpośredni dostęp do API chrome.extension jak np. popup):

background.js

chrome.browserAction.onClicked.addListener(function() { 
    // create a new tab with an html page that resides in extension domain: 
    chrome.tabs.create({'url': chrome.extension.getURL("page.html"), 
         'active': false}, function(tab){ 
     var selfTabId = tab.id; 
     chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { 
      if (changeInfo.status == "complete" && tabId == selfTabId){ 
       // send the data to the page's script: 
       var tabs = chrome.extension.getViews({type: "tab"}); 
       tabs[0].doSomething("some long data"); 
      } 
     }); 
    }); 
}); 

page.html

<!doctype html> 
<html> 
    <head> 
    </head> 
    <body> 
     <p id="myId">page created...</p> 
     <script src="page.js" type="text/javascript"></script> 
    </body> 
</html> 

page.js

var alreadyRun = false; 
function doSomething(data){ 
    if (!alreadyRun) { 
     var p = document.getElementById("myId"); 
     p.innerHTML += "<br>data received: " + data; 
     // needed because opening eg. DevTools to inpect the page 
     // will trigger both the "complete" state and the tabId conditions 
     // in background.js: 
     alreadyRun = true; 
    } 
} 
document.getElementById("myId").innerHTML += "<br>script loaded..."; 

co ja don tak wiele z tego rozwiązania polega na sprawdzeniu, czy stworzona karta jest całkowicie załadowana i że w ten sposób jest wyzwalana dla dowolnej zmiany stanu otwartych zakładek (to bezużyteczne ... byłby świetnym sposobem na uruchom czek tylko dla zainteresowanej karty)