Javascript-форум (https://javascript.ru/forum/)
-   Opera, Safari и др. (https://javascript.ru/forum/css-html-browser/)
-   -   Нужна помощь с доработкой скрипта расширения под Chrome (https://javascript.ru/forum/css-html-browser/71964-nuzhna-pomoshh-s-dorabotkojj-skripta-rasshireniya-pod-chrome.html)

BeleK0ss 25.12.2017 17:54

Нужна помощь с доработкой скрипта расширения под Chrome
 
Всем доброго времени суток!
Ребята выручайте, неделю воюю, но опыта 0. Делаю расширение для рабочего сайта. Расширение само по себе блокирует возможность открывать более чем задано количество вкладок в окне браузера.
Реализованный алгоритм, на данный момент, его таков: Есть 1 вкладка с главным сайтом на котором есть 2 кнопки -> при попытке открыть новое окно оно закрывается через N секунд. -> когда новая вкладка закрывается, главная страница автоматически обновляется.
Мне нужно что бы после обновления страницы, нажималась кнопка id=0.
Вот кнопка:
<button class="button" type="button" data-href="https://sportloto.com.ua/#sports" data-index="0" id="0">Ставки на спорт</button>


manifest.json:
{
    "name": "Tab Limit",
    "description": "Limit the number of open, non-pinned browser tabs",
    "version": "0.1.0",
	
    "background": {
        "scripts": ["background.js"]
    },

    "permissions": [
        "tabs"
		
    ],
    "browser_action": {
        "default_icon": {
            "19": "icons/19.png",
            "38": "icons/38.png"
        },
        "default_title": "Tab Limit"
    },
    "icons": {
        "48": "icons/48.png",
        "128": "icons/128.png"
    },
    "manifest_version": 2
}

background.js:
var isEnabled = true;
var maxTabs = 1;
var tabsCount;


function updateBadgeText() {
    var tabsBalance = maxTabs - tabsCount;
    var tabsAllowanceRemaining = (tabsBalance > 0) ? tabsBalance : 0;

    chrome.browserAction.setBadgeText({
        text: "" + tabsAllowanceRemaining
		
    });
	
}

function updateTabsCount() {
	
    chrome.tabs.query({
        windowType: 'normal',
        pinned: false
    }, function (tabs) {
        tabsCount = tabs.length;
        updateBadgeText();
    });
}

function handleTabCreated(tab) {
   if (tabsCount >= maxTabs) {
		setTimeout(function() {
        chrome.tabs.remove(tab.id);
		}, 2000);	
	}
    else {
        updateTabsCount();
    }
}

function handleTabClick() {
	
			setTimeout(function() 	{
				
		}, 5000);
}

function handleTabRemoved(tab) {
    updateTabsCount();
	chrome.tabs.reload(tab.id);
		handleTabClick();
	}

function handleTabUpdated(tab) {
    updateTabsCount();
}


function init() {
    updateTabsCount();
    chrome.tabs.onCreated.addListener(handleTabCreated);
    chrome.tabs.onRemoved.addListener(handleTabRemoved);
    chrome.tabs.onUpdated.addListener(handleTabUpdated);
	}

function teardown() {
    chrome.tabs.onCreated.removeListener(handleTabCreated);
    chrome.tabs.onRemoved.removeListener(handleTabRemoved);
    chrome.tabs.onUpdated.removeListener(handleTabUpdated);
	}

chrome.browserAction.onClicked.addListener(function (tab) {
    if (!isEnabled) {
        init();
        chrome.browserAction.setIcon({ path: "icons/19.png" });
	}
    else {
        teardown();
        chrome.browserAction.setIcon({ path: "icons/19-disabled.png" });
        chrome.browserAction.setBadgeText({ 'text': '' });
  }

    isEnabled = !isEnabled;
});


init();


Соответствено пробовал все что нашел в Google и тут на сайте. Ничего не вышло. В консоли браузера все отлично работает. Подставляю в расширение, ноль.
function handleTabClick() {
	
			setTimeout(function() 	{
				
		}, 5000);
}

В эту же форму вставляю Alert('111'); для проверки, сообщение как положено выводится через 5 секунд. Вставляю
document.getElementById('0').click();

или
document.getElementByClassName('button')[0].click();

Ничего не работает :(

Aetae 25.12.2017 18:11

background процесс не имеет доступа к контенту страниц, нужен content_scripts.

BeleK0ss 25.12.2017 18:48

Понял, а не могли бы подсказать как правильно было бы оформить. Или хотя бы пример. Может постараюсь разобраться теперь более эффективно :) А то только начал в этом всем разбираться, немного сложновато со старта... насчет контента я понял в манифест добавить нужно
"content_scripts": [
    {
      "matches": [ "*://*.*/*" ],
      "js": [ "content.js" ],
      "run_at": "document_start"
    }
 ],

А вот что в контент писать ? Или вы имеете в виду нужно ему как-то предоставить доступ? Если да, то каким образом?

Aetae 26.12.2017 01:07

Нет. В content пишете то, что пишете в консоли. В background общее управление. Общение между background только через sendMessage, прямое взаимодействие невозможно(разные процессы потому что). Ну и вместо *://*.*/* укажите конкретный сайт, зачем вам теребить все?
В принципе в вашем случае можно было бы обойтись вообще одним content(а лучше вообще без расширения, раз уж сайт ваш), ибо сейчас есть такие штуки как SharedWorker, window.postMessage и windowObj.onstorage.

BeleK0ss 26.12.2017 10:27

Спасибо большое! Буду пробовать.
Вы правы, но к сожалению все немного сложнее, по этому и приходится идти в обход :)

BeleK0ss 26.12.2017 10:43

О великий гуру. Я восхищаюсь вами, вашими знаниями и вашим безмерным благодушием !Все заработало! Я вам бесконечно благодарен за оказаную мне и моему маленькому опыту, помощь :dance: :thanks:

BeleK0ss 26.12.2017 18:29

Еще вопрос. Если прямое взаимодействие между процессами невозможно, есть ли какой нибудь другой вариант вызвать нажатие в content.js после того как в background.js выполнится
chrome.tabs.reload(tab.id);
или
chrome.tabs.remove(tab.id);
?
Или хотя бы не вызывать нажатие кнопки если вкладка свежеоткрыта а не обновлена?

Aetae 26.12.2017 20:07

sendMessage же. Прицип такой же как с событиями(типа onclick итп), просто событие приходит не от юзера, а со стороны background. Точно также вешаются обработчики onMessage, которые вызывают уже нужный код.

BeleK0ss 26.12.2017 22:03

Теперь я понял что вы имеете в виду. Но еще не до конца понимаю как мне правильно все реализовать.
Получается, нужно в Background добавить sendMessage, что бы вызвать функцию на выполнение, а в Content на эту функцию повесить onMessage что бы она ответила на запрос и выполнилась. Я правильно мыслю? :)

BeleK0ss 27.12.2017 13:43

Попытался, по совету реализовать.
//background.js
function handleTabRemoved(tab) {
    updateTabsCount();
	chrome.tabs.reload(tab.id);
	began();
	}
	
function began() {

  chrome.runtime.sendMessage({greeting: 'hello'}, function(response) {
      console.log(response.msg); /*При необходимости получаете ответ*/
    });
}

//content.js
function handleTabClick() {
	
		setTimeout(function() 	{
				document.getElementById('0').click();
		}, 5000);
}

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.greeting == 'hello'){
    alert('111');
/*Можете отправить ответ, если необходимо*/

      sendResponse({msg: 'Update'});

    }

  });
но не работает... Сообщение не выводится...

Aetae 27.12.2017 22:34

Потому что чтоб отправить сообщение вкладке нужно использовать chrome.tabs.sendMessage с указанием конкретной вкладки куда слать.

BeleK0ss 28.12.2017 14:09

Огромное тебе спасибо! Все заработало. в таком вот виде:

//background.js
function handleTabRemoved(tab,response)
{
    updateTabsCount();
    if (response.isWindowClosing == false)
    {
        chrome.tabs.query({ "active": true, "windowId": response.windowId }, function (tabs)
        {
            chrome.tabs.reload(tabs[0].id, function ()
            {
                began(tabs[0].id);
            });
        });
    }
}
    
 function began(tabId) {
	setTimeout( function() {
		chrome.tabs.sendMessage(tabId, {greeting: "hello"}, function(response) 
   {});
   }, 1000);
}


//content.js
function handleTabClick() {

				document.getElementById('0').click();

}


chrome.runtime.onMessage.addListener(
  function(request, sender) {
    if (request.greeting == "hello"){
   handleTabClick();
    }
  });


Без задержки chrome.tabs.sendMessage выполняется раньше и не работает. Пришлось ставить задержку. Очень благодарен тебе за советы!
А если ли возможность заменить setTimeout на что нибудь по проще? Что бы функция выполнялась после загрузки страницы? Пробовал оформить через window.onload но функция запускается единоразово после обновления расширения и после не выполняется вовсе...


Часовой пояс GMT +3, время: 12:30.