Search code examples
javascriptgoogle-chrome-extensionfirefox-addonbrowser-extension

page_action click does not work while browser_action click works in Chrome Extension?


I want to make a simple browser extension like Font Face Ninja which toggles UI when page_action or browser_action is clicked.

The following code using browser_action works -

background.js

chrome.browserAction.onClicked.addListener(function(tab) {
  console.log(`clicked browserAction`)
})

manifest.json

{
    ...
    "browser_action": {
    "default_icon": {
      "19": "icon19.png",
      "38": "icon38.png"
    }
  },
    ...
}

While the following code using page_action does not work -

background.js

chrome.pageAction.onClicked.addListener(function(tab) {
  console.log(`clicked pageAction`)
})

manifest.json

{
    ...
    "page_action": {
    "default_icon": {
      "19": "icon19.png",
      "38": "icon38.png"
    }
  },
    ...
}

According to MDN docs,

Page actions are like browser actions, except that they are associated with particular web pages rather than with the browser as a whole. If an action is only relevant on certain pages, then you should use a page action and display it only on relevant pages. If an action is relevant to all pages or to the browser itself, use a browser action.

Which confirms I want to use page_action but its not working.

How do I make it work using page_action?


Solution

  • Page Action

    A way to make page_action work can be found on my Github → https://github.com/deadcoder0904/insert-remove-ui-chrome-extension/tree/page_action

    background.js

    var hasExecutedOnce = false
    
    function addUI(tabId) {
      chrome.tabs.sendMessage(tabId, {
        from: 'background',
        subject: 'isUIAdded?',
      })
    }
    
    chrome.runtime.onInstalled.addListener(function() {
      chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
        chrome.declarativeContent.onPageChanged.addRules([
          {
            conditions: [
              new chrome.declarativeContent.PageStateMatcher({
                pageUrl: { hostEquals: 'www.google.co.in' },
              }),
            ],
            actions: [new chrome.declarativeContent.ShowPageAction()],
          },
        ])
      })
    })
    
    chrome.pageAction.onClicked.addListener(function(tab) {
      if (!hasExecutedOnce) {
        chrome.tabs.executeScript(
          tab.id,
          {
            file: 'contentScript.js',
          },
          function() {
            addUI(tab.id)
          },
        )
        hasExecutedOnce = true
      }
      addUI(tab.id)
    })
    

    contentScript.js

    var body = document.getElementsByTagName('body')[0]
    
    function insertUI() {
      var div = document.createElement('div')
      div.setAttribute('id', 'sample-extension-12345')
      div.innerHTML = `<h1>Sample Extension</h1>`
      body.appendChild(div)
    }
    
    function removeUI() {
      document.getElementById('sample-extension-12345').remove()
    }
    
    function main() {
      chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
        if (request.subject === 'isUIAdded?') {
          const id = document.getElementById('sample-extension-12345')
          if (id === null) insertUI()
          else removeUI()
        }
      })
    }
    
    main()
    

    Browser Action

    It also has a solution for browser_action on the master branch → https://github.com/deadcoder0904/insert-remove-ui-chrome-extension/

    background.js

    var hasExecutedOnce = false
    
    function addUI(tabId) {
      chrome.tabs.sendMessage(tabId, {
        from: 'background',
        subject: 'isUIAdded?',
      })
    }
    
    chrome.browserAction.onClicked.addListener(function(tab) {
      if (!hasExecutedOnce) {
        chrome.tabs.executeScript(
          tab.id,
          {
            file: 'contentScript.js',
          },
          function() {
            addUI(tab.id)
          },
        )
        hasExecutedOnce = true
      }
      addUI(tab.id)
    })
    

    contentScript.js

    var body = document.getElementsByTagName('body')[0]
    
    function insertUI() {
      var div = document.createElement('div')
      div.setAttribute('id', 'sample-extension-12345')
      div.innerHTML = `<h1>Sample Extension</h1>`
      body.appendChild(div)
    }
    
    function removeUI() {
      document.getElementById('sample-extension-12345').remove()
    }
    
    function main() {
      chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
        if (request.subject === 'isUIAdded?') {
          const id = document.getElementById('sample-extension-12345')
          if (id === null) insertUI()
          else removeUI()
        }
      })
    }
    
    main()