From 2bb7d31042b04cc19dd7b010dd3d4f19c75776ea Mon Sep 17 00:00:00 2001 From: tophf Date: Sun, 9 Apr 2017 09:43:51 +0300 Subject: [PATCH] fixups for Opera/Vivaldi/Firefox-compatibility --- .eslintrc | 5 +++-- background.js | 10 +++++----- edit.js | 6 +++--- localization.js | 4 ++-- manage.css | 11 +++++++++++ manage.html | 2 +- manage.js | 4 ++-- messaging.js | 45 ++++++++++++++++++++++++++------------------- options/index.css | 11 ++++++++++- options/index.html | 9 +++++---- options/index.js | 5 +++-- popup.css | 4 ++++ popup.html | 4 ++-- popup.js | 24 +++++++++++++++++------- storage.js | 6 +++--- 15 files changed, 97 insertions(+), 53 deletions(-) diff --git a/.eslintrc b/.eslintrc index 1d17b783..fa044597 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,10 +10,11 @@ env: globals: # messaging.js - OWN_ORIGIN: false KEEP_CHANNEL_OPEN: false RX_SUPPORTED_URLS: false - configureCommands: false + FIREFOX: false + OPERA: false + URLS: false notifyAllTabs: false refreshAllTabs: false updateIcon: false diff --git a/background.js b/background.js index c662a52d..415f1b3b 100644 --- a/background.js +++ b/background.js @@ -23,8 +23,8 @@ function webNavigationListener(method, data) { // we can't inject chrome:// and chrome-extension:// pages // so we'll only inform our page of the change // and it'll retrieve the styles directly - if (method && !data.url.startsWith('chrome:')) { - const isOwnPage = data.url.startsWith(OWN_ORIGIN); + if (method && !data.url.startsWith('chrome:') && data.tabId >= 0) { + const isOwnPage = data.url.startsWith(URLS.ownOrigin); chrome.tabs.sendMessage( data.tabId, {method, styles: isOwnPage ? 'DIY' : styles}, @@ -127,7 +127,7 @@ if (/Vivaldi\/[\d.]+$/.test(navigator.userAgent) contextMenus.editDeleteText = { title: 'editDeleteText', contexts: ['editable'], - documentUrlPatterns: [OWN_ORIGIN + 'edit*'], + documentUrlPatterns: [URLS.ownOrigin + 'edit*'], click: (info, tab) => { chrome.tabs.sendMessage(tab.id, {method: 'editDeleteText'}); }, @@ -160,7 +160,7 @@ getDatabase(function() {}, reportError); // When an edit page gets attached or detached, remember its state // so we can do the same to the next one to open. -const editFullUrl = OWN_ORIGIN + 'edit.html'; +const editFullUrl = URLS.ownOrigin + 'edit.html'; chrome.tabs.onAttached.addListener((tabId, data) => { chrome.tabs.get(tabId, tabData => { if (tabData.url.startsWith(editFullUrl)) { @@ -198,7 +198,7 @@ chrome.storage.local.get('version', prefs => { injectContentScripts(); function injectContentScripts() { - const contentScripts = chrome.app.getDetails().content_scripts; + const contentScripts = chrome.runtime.getManifest().content_scripts; for (const cs of contentScripts) { cs.matches = cs.matches.map(m => ( m == '' ? m : wildcardAsRegExp(m) diff --git a/edit.js b/edit.js index 9ac64449..9587df87 100644 --- a/edit.js +++ b/edit.js @@ -1648,8 +1648,8 @@ function showLintHelp() { function showRegExpTester(event, section = getSectionForChild(this)) { const GET_FAVICON_URL = 'https://www.google.com/s2/favicons?domain='; - const OWN_ICON = chrome.app.getDetails().icons['16']; - const RX_SUPPORTED_URLS = new RegExp(`^(file|https?|ftps?):|^${OWN_ORIGIN}`); + const OWN_ICON = chrome.runtime.getManifest().icons['16']; + const RX_SUPPORTED_URLS = new RegExp(`^(file|https?|ftps?):|^${URLS.ownOrigin}`); const cachedRegexps = showRegExpTester.cachedRegexps = showRegExpTester.cachedRegexps || new Map(); const regexps = [...section.querySelector('.applies-to-list').children] @@ -1713,7 +1713,7 @@ function showRegExpTester(event, section = getSectionForChild(this)) { const full = []; const partial = []; for (const [url, match] of urls.entries()) { - const faviconUrl = url.startsWith(OWN_ORIGIN) + const faviconUrl = url.startsWith(URLS.ownOrigin) ? OWN_ICON : GET_FAVICON_URL + new URL(url).hostname; const icon = ``; diff --git a/localization.js b/localization.js index 47a2ca16..9bce918c 100644 --- a/localization.js +++ b/localization.js @@ -28,7 +28,7 @@ function tHTML(html) { const node = document.createElement('div'); node.innerHTML = html.replace(/>\s+<'); // spaces are removed; use   for an explicit space if (html.includes('i18n-')) { - tNodeList(node.querySelectorAll('*')); + tNodeList(node.getElementsByTagName('*')); } return node.firstElementChild; } @@ -70,7 +70,7 @@ function tNodeList(nodes) { function tDocLoader() { // localize HEAD - tNodeList(document.all); + tNodeList(document.getElementsByTagName('*')); // localize BODY const process = mutations => { diff --git a/manage.css b/manage.css index c9f6910e..c0a96fae 100644 --- a/manage.css +++ b/manage.css @@ -1,6 +1,9 @@ body { margin: 0; font: 12px arial, sans-serif; + /* Firefox: fill the entire page for drag'n'drop to work */ + display: flex; + height: 100%; } a { @@ -29,6 +32,10 @@ a:hover { margin-top: 0; } +.firefox .chromium-only { + display: none; +} + #installed { position: relative; margin-left: 280px; @@ -274,6 +281,10 @@ summary { letter-spacing: .1ex; } +.newUI .has-favicons .applies-to .expander { + padding-left: 20px; +} + .newUI .target:hover { background-color: inherit; } diff --git a/manage.html b/manage.html index 4657d072..8eb30b92 100644 --- a/manage.html +++ b/manage.html @@ -162,7 +162,7 @@

- +

chrome.runtime.openOptionsPage(); - $('#manage-shortcuts-button').onclick = configureCommands.open; + $('#manage-shortcuts-button').onclick = () => openURL({url: URLS.configureCommands}); $$('#header a[href^="http"]').forEach(a => (a.onclick = handleEvent.external)); // focus search field on / key diff --git a/messaging.js b/messaging.js index cd353526..0de622f5 100644 --- a/messaging.js +++ b/messaging.js @@ -3,8 +3,21 @@ // keep message channel open for sendResponse in chrome.runtime.onMessage listener const KEEP_CHANNEL_OPEN = true; -const OWN_ORIGIN = chrome.runtime.getURL(''); -const RX_SUPPORTED_URLS = new RegExp(`^(file|https?|ftps?):|^${OWN_ORIGIN}`); +const FIREFOX = /Firefox/.test(navigator.userAgent); +const OPERA = /OPR/.test(navigator.userAgent); +const URLS = { + ownOrigin: chrome.runtime.getURL(''), + optionsUI: new Set([ + chrome.runtime.getURL('options/index.html'), + 'chrome://extensions/?options=' + chrome.runtime.id, + ]), + configureCommands: OPERA ? 'opera://settings/configureCommands' + : 'chrome://extensions/configureCommands', +}; +const RX_SUPPORTED_URLS = new RegExp(`^(file|https?|ftps?):|^${URLS.ownOrigin}`); + +document.documentElement.classList.toggle('firefox', FIREFOX); +document.documentElement.classList.toggle('opera', OPERA); function notifyAllTabs(request) { @@ -20,9 +33,9 @@ function notifyAllTabs(request) { const affectsIcon = affectsAll || request.affects.icon; const affectsPopup = affectsAll || request.affects.popup; if (affectsTabs || affectsIcon) { - chrome.tabs.query(affectsOwnOrigin ? {url: OWN_ORIGIN + '*'} : {}, tabs => { + chrome.tabs.query(affectsOwnOrigin ? {url: URLS.ownOrigin + '*'} : {}, tabs => { for (const tab of tabs) { - if (affectsTabs || tab.url.startsWith(OWN_ORIGIN + 'options')) { + if (affectsTabs || URLS.optionsUI.has(tab.url)) { chrome.tabs.sendMessage(tab.id, request); } if (affectsIcon) { @@ -38,7 +51,7 @@ function notifyAllTabs(request) { onBackgroundMessage(request); } // notify background page and all open popups - if (affectsPopup) { + if (affectsPopup || request.prefs) { chrome.runtime.sendMessage(request); } } @@ -72,7 +85,7 @@ function updateIcon(tab, styles) { // while NTP is still loading only process the request for its main frame with a real url // (but when it's loaded we should process style toggle requests from popups, for example) const isNTP = tab.url == 'chrome://newtab/'; - if (isNTP && tab.status != 'complete') { + if (isNTP && tab.status != 'complete' || tab.id < 0) { return; } if (styles) { @@ -167,11 +180,13 @@ function openURL({url, currentWindow = true}) { return; } } - getActiveTab().then(tab => ( - tab && tab.url == 'chrome://newtab/' - ? chrome.tabs.update({url}, resolve) - : chrome.tabs.create({url, openerTabId: tab.id}, resolve) - )); + getActiveTab().then(tab => { + if (tab && tab.url == 'chrome://newtab/') { + chrome.tabs.update({url}, resolve); + } else { + chrome.tabs.create(tab && !FIREFOX ? {url, openerTabId: tab.id} : {url}, resolve); + } + }); }); }); } @@ -203,11 +218,3 @@ function wildcardAsRegExp(s, flags) { function ignoreChromeError() { chrome.runtime.lastError; // eslint-disable-line no-unused-expressions } - - -const configureCommands = { - url: navigator.userAgent.includes('OPR') - ? 'opera://settings/configureCommands' - : 'chrome://extensions/configureCommands', - open: () => openURL({url: configureCommands.url}), -}; diff --git a/options/index.css b/options/index.css index ffbb0fc8..7ab692c2 100644 --- a/options/index.css +++ b/options/index.css @@ -1,3 +1,8 @@ +html { + max-width: 40em; + margin: auto; +} + body { margin: 0; font-family: "Helvetica Neue", Helvetica, sans-serif; @@ -14,6 +19,10 @@ body > *:first-child { padding-top: .75rem; } +.firefox .chromium-only { + display: none; +} + table { width: 100%; border-collapse: collapse; @@ -34,6 +43,7 @@ input[type="color"], .onoffswitch, #update-counter { width: 80px; + box-sizing: border-box; } a { @@ -46,7 +56,6 @@ button { input[type=number] { text-align: right; - padding-right: 1em; } #actions { diff --git a/options/index.html b/options/index.html index ac89629b..a48471bf 100644 --- a/options/index.html +++ b/options/index.html @@ -58,7 +58,7 @@

- + @@ -74,9 +74,10 @@
  1. -
  2. +
  3. +
diff --git a/options/index.js b/options/index.js index 8fbd404f..f3e52cfa 100644 --- a/options/index.js +++ b/options/index.js @@ -13,7 +13,7 @@ setupLivePrefs([ enforceInputRange($('#popupWidth')); // overwrite the default URL if browser is Opera -$('[data-cmd="open-keyboard"]').href = configureCommands.url; +$('[data-cmd="open-keyboard"]').href = URLS.configureCommands; // actions document.onclick = e => { @@ -68,7 +68,8 @@ document.onclick = e => { break; case 'open-keyboard': - configureCommands.open(); + openURL({url: e.target.href}); + e.preventDefault(); break; case 'reset': diff --git a/popup.css b/popup.css index 989a104e..8c15be9d 100644 --- a/popup.css +++ b/popup.css @@ -10,6 +10,10 @@ body > div:not(#installed) { margin-right: 0.75em; } +.firefox .chromium-only { + display: none; +} + input[type=checkbox] { outline: none; } diff --git a/popup.html b/popup.html index be687e34..ecb152f5 100644 --- a/popup.html +++ b/popup.html @@ -105,9 +105,9 @@ diff --git a/popup.js b/popup.js index 0ad30bd8..d891a7b5 100644 --- a/popup.js +++ b/popup.js @@ -53,17 +53,27 @@ function initPopup(url) { setPopupWidth(); // force Chrome to resize the popup - document.body.style.height = '10px'; - document.documentElement.style.height = '10px'; + if (!FIREFOX) { + document.body.style.height = '10px'; + document.documentElement.style.height = '10px'; + } // action buttons $('#disableAll').onchange = () => installed.classList.toggle('disabled', prefs.get('disableAll')); setupLivePrefs(['disableAll']); + $('#find-styles-link').onclick = handleEvent.openURLandHide; - $('#popup-manage-button').onclick = () => openURL({url: 'manage.html'}); - $('#popup-options-button').onclick = () => chrome.runtime.openOptionsPage(); - $('#popup-shortcuts-button').onclick = configureCommands.open; + $('#popup-manage-button').onclick = handleEvent.openURLandHide; + + $('#popup-options-button').onclick = () => { + chrome.runtime.openOptionsPage(); + window.close(); + }; + + const shortcutsButton = $('#popup-shortcuts-button'); + shortcutsButton.dataset.href = URLS.configureCommands; + shortcutsButton.onclick = handleEvent.openURLandHide; if (!prefs.get('popup.stylesFirst')) { document.body.insertBefore( @@ -317,8 +327,8 @@ Object.assign(handleEvent, { openURLandHide(event) { event.preventDefault(); - openURL({url: this.href}) - .then(close); + openURL({url: this.href || this.dataset.href}) + .then(window.close); }, }); diff --git a/storage.js b/storage.js index 426fe82c..f1846fa0 100644 --- a/storage.js +++ b/storage.js @@ -441,9 +441,9 @@ function getApplicableSections({style, matchUrl, strictRegexp = true, stopOnFirs do { // only http, https, file, ftp, and chrome-extension://OWN_EXTENSION_ID allowed if (!matchUrl.startsWith('http') - && !matchUrl.startsWith('ftp') - && !matchUrl.startsWith('file') - && !matchUrl.startsWith(OWN_ORIGIN)) { + && !matchUrl.startsWith('ftp') + && !matchUrl.startsWith('file') + && !matchUrl.startsWith(URLS.ownOrigin)) { continue checkingSections; } if (section.urls.length == 0
22