reactjs - Spustiť skript v novom paneli vytvorenom pomocou chrome.tabs.create()
Ako spustím skript pomocou chrome.tabs.executeScript() v karte, ktorú som vytvoril pomocou chrome.tabs.create()? Hľadal som po internete a žiadne z riešení nezaberajú.
Toto je môj aktuálny kód.
runContentScript(){
chrome.tabs.create({url: "https://google.com/", active: true});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
chrome.tabs.executeScript(tab.id!, {file: "tracking.js"});
});
}
Môj manifest je tiež správne nastavený.
UPRAVA: Pridal som celý kód, pretože si nie som istý, či niečo nezasahuje do funkcie runContentScript.
import React, { Component } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { ListGroup } from 'react-bootstrap';
import './Cart.css';
import logo from './greenlake_logo.png';
import { url } from 'inspector';
class ProductList extends Component<{}, {products: any[][]}> {
constructor(props: any){
super(props);
this.addProduct.bind(this);
this.runContentScript.bind(this);
this.checkIfPathsExists.bind(this)
this.loadProductPage.bind(this);
this.removeLocalStorage.bind(this);
this.state = {products: []};
}
setLocalStorage(values: any[]){
chrome.storage.sync.set({'productList': values});
}
async appendLocalStorage(product: any[]){
var promisedStorageValues = new Promise(function(resolve, reject){
chrome.storage.sync.get('productList', function(result){
resolve(result.productList);
})
});
const values: any = await promisedStorageValues;
const newValues: any[] = [];
for(let i=0; i < values.length; i++){
newValues.push(values[i]);
}
newValues.push(product);
this.setLocalStorage(newValues);
this.readLocalStorage();
}
async removeLocalStorage(product: any[]){
var promisedStorageValues = new Promise(function(resolve, reject){
chrome.storage.sync.get('productList', function(result){
resolve(result.productList);
})
});
const values: any = await promisedStorageValues;
values.splice(values.indexOf(product, 0), 1);
this.setLocalStorage(values);
this.readLocalStorage();
}
async readLocalStorage(){
var promisedStorageValues = new Promise(function(resolve, reject){
chrome.storage.sync.get('productList', function(result){
resolve(result.productList);
})
});
const values: any = await promisedStorageValues;
this.setState({products: values});
}
async addProduct(){
var promisedURL = new Promise(function(resolve, reject){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
resolve([tabs[0].url, tabs[0].favIconUrl, tabs[0].title]);
})
});
const urlInformation: any = await promisedURL;
const urlFavicon: any = urlInformation[1];
const urlProduct: any = urlInformation[0]
var workaroundHost: any = new URL(urlInformation[0]);
const urlHost: any = workaroundHost.host;
const urlTitle: any = urlInformation[2];
const urlPrice: any = 'placeholder';
this.appendLocalStorage([urlProduct, urlFavicon, urlTitle, urlPrice, urlHost]);
}
loadProductPage(url: string){
chrome.tabs.create({url: url, active: true});
}
runContentScript(urlProduct: string){
chrome.tabs.create({url: urlProduct}, createdTab => {
chrome.tabs.onUpdated.addListener(function _(tabId, info, tab) {
if (tabId === createdTab.id && info.url) {
chrome.tabs.onUpdated.removeListener(_);
chrome.tabs.executeScript(tabId, {file: 'tracking.js'});
}
});
});
}
loadPath(url: string){
fetch("http://127.0.0.1:5000/getpath/" + url)
.then(response => response.json())
.then(response => {
console.log('loadPath: ' + response)
})
}
checkIfPathsExists(){
for(let i=0; i < this.state.products.length; i++){
const urlHost: string = this.state.products[i][4];
let formattedHost = urlHost.split('.')[1];
const status = fetch("http://127.0.0.1:5000/checkpath/" + formattedHost)
.then(response => response.json())
.then(response => {if(response == true){this.loadPath(formattedHost)}else{this.runContentScript(this.state.products[i][0])}});
}
}
componentDidMount(){
this.readLocalStorage();
}
render(){
return (
<div>
<div className="logoDiv">
<img src={logo} width="128" height="64" />
</div>
<div className="centeredDiv">
{this.state.products.map(product => {return (
<div>
<ListGroup horizontal id="Test">
<ListGroup.Item className="ProductListLogo" onClick={() => this.loadProductPage(product[0])}><img src={product[1]} width="32" height="32"></img></ListGroup.Item>
<ListGroup.Item className="ProductListProduct">{product[2]}</ListGroup.Item>
<ListGroup.Item className="ProductListPrice">{product[3]}</ListGroup.Item>
<ListGroup.Item className="ProductListAction" onClick={() => this.removeLocalStorage(product)}>X</ListGroup.Item>
</ListGroup>
<div className="spacerLine"/>
</div>
)})}
</div>
<div className="actionDiv">
<ListGroup horizontal>
<ListGroup.Item className="ActionButtons" onClick={() => this.addProduct()}>Add To Cart</ListGroup.Item>
<ListGroup.Item className="ActionButtons" onClick={() => this.checkIfPathsExists()}>Checkout</ListGroup.Item>
</ListGroup>
</div>
</div>
);
}
}
class Cart extends Component {
render(){
return (
<div className="containerDiv">
<div>
<ProductList />
</div>
</div>
)
}
}
export default Cart;
RIEŠENIE Musíte pridať "active: false", pretože ak vytvoríte kartu, automaticky sa na ňu sústredí a zatvorí rozšírenie, ak to nie je špecifikované. Funkcia spätného volania sa preto nikdy nevyvolá.
chrome.tabs.create({url: urlProduct, active: false}, createdTab => {
chrome.tabs.onUpdated.addListener(function _(tabId, info, tab) {
if (tabId === createdTab.id && info.url) {
chrome.tabs.onUpdated.removeListener(_);
chrome.tabs.executeScript(tabId, {file: 'tracking.js'});
}
});
});
Odpoveď č. 1
Ak predpokladáme, že permissions v súbore manifest.json obsahuje "https://google.com/" (alebo širší vzor), tu sú tri problémy.
1. Obchádzka chyby Chrome pri presmerovaní
crbug.com/820080: chrome.tabs.executeScript môže zlyhať, ak je odovzdaná karta aktívne pod navigáciou hlavného rámca. Špecifikujete https://google.com/, ale na tejto stránke nie je nič, presmeruje sa na https://www.google.com/, čo v novom Chrome nevidíte, pretože skrýva www. Buď povoľte zobrazovanie úplných URL, alebo použite location.href v konzole vývojárskych nástrojov na zobrazenie skutočnej URL.
Verdikt: keďže akákoľvek stránka sa môže rozhodnúť vykonať presmerovanie z akéhokoľvek dôvodu, spoľahlivým riešením je použiť chrome.tabs.onUpdated, ale urobiť to správne, pozri nižšie.
2. Použite chrome.tabs.onUpdated správne
- Použite vytvorené ID karty v spätnom volaní na obmedzenie onUpdated len na túto kartu
- Zrušte registráciu poslucháča, aby ste predišli hromadeniu poslucháčov, čo by spôsobilo chyby
3. Zabrániť automatickému zatváraniu popupu
Otvorenie aktívnej/zameranej karty zatvorí aktuálne zobrazené rozšírenie vyskakovacie okno, úplne ho ukončí, takže spätné volanie pre create() sa nezobrazí, pretože sa volá asynchrónne.
Obchádzka.
Jednoduchým obchvatom je otvoriť kartu ako neaktívnu a potom sa na ňu zamerať:
chrome.tabs.create({url: 'https://google.com/', active: false}, createdTab => { chrome.tabs.onUpdated.addListener(function _(tabId, info, tab) { if (tabId === createdTab.id && info.url) { chrome.tabs.onUpdated.removeListener(_); chrome.tabs.executeScript(tabId, {file: 'tracking.js'}, () => { chrome.tabs.update(tabId, {active: true}); // the above will close the popup if it doesn't have its own devtools open }); } }); });Riešenie.
Spoľahlivé riešenie je urobiť to v skripte na pozadí, pretože vyššie uvedené obchádzanie môže zlyhať, ak iné rozšírenie mení predvolené správanie nových záložiek a násilne zameriava vašu záložku, čo automaticky zatvorí vyskakovacie okno a zničí obchádzanie.
popup.js:
chrome.runtime.sendMessage({ cmd: 'openTab', url: 'https://google.com/', script: 'tracking.js', });background.js:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.cmd === 'openTab') { chrome.tabs.create({url: msg.url}, createdTab => { chrome.tabs.onUpdated.addListener(function _(tabId, info, tab) { if (tabId === createdTab.id && info.url) { chrome.tabs.onUpdated.removeListener(_); chrome.tabs.executeScript(tabId, {file: msg.script}); } }); }); } });
Odpoveď č. 2
Môžete použiť spätnú volaciu funkciu chrome.tabs.create.
runContentScript(){
chrome.tabs.create({url: 'https://google.com/', active: true}, tab => {
chrome.tabs.executeScript(tab.id, {file: 'tracking.js'});
});
}
