-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRX: persistent background page -> event page #1487
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,152 +16,117 @@ | |
*/ | ||
'use strict'; | ||
|
||
document.addEventListener('DOMContentLoaded', _ => { | ||
const background = chrome.extension.getBackgroundPage(); | ||
const defaultAggregations = background.getDefaultAggregations(); | ||
|
||
const siteNameEl = window.document.querySelector('header h2'); | ||
const generateReportEl = document.getElementById('generate-report'); | ||
const subpageVisibleClass = 'subpage--visible'; | ||
|
||
const statusEl = document.body.querySelector('.status'); | ||
const statusMessageEl = document.body.querySelector('.status__msg'); | ||
const statusDetailsMessageEl = document.body.querySelector('.status__detailsmsg'); | ||
const feedbackEl = document.body.querySelector('.feedback'); | ||
|
||
const generateOptionsEl = document.getElementById('configure-options'); | ||
const optionsEl = document.body.querySelector('.options'); | ||
const optionsList = document.body.querySelector('.options__list'); | ||
const okButton = document.getElementById('ok'); | ||
/** | ||
* Error strings that indicate a problem in how Lighthouse was run, not in | ||
* Lighthouse itself, mapped to more useful strings to report to the user. | ||
*/ | ||
const NON_BUG_ERROR_MESSAGES = { | ||
'Another debugger': 'You probably have DevTools open. Close DevTools to use Lighthouse', | ||
'multiple tabs': 'You probably have multiple tabs open to the same origin. ' + | ||
'Close the other tabs to use Lighthouse.', | ||
// The extension debugger API is forbidden from attaching to the web store. | ||
// @see https://chromium.googlesource.com/chromium/src/+/5d1f214db0f7996f3c17cd87093d439ce4c7f8f1/chrome/common/extensions/chrome_extensions_client.cc#232 | ||
'The extensions gallery cannot be scripted': 'The Lighthouse extension cannot audit the ' + | ||
'Chrome Web Store. If necessary, use the Lighthouse CLI to do so.', | ||
// The user tries to review an error page or has network issues | ||
'Unable to load the page': 'Unable to load the page. Please verify the url you ' + | ||
'are trying to review.' | ||
}; | ||
|
||
const subpageVisibleClass = 'subpage--visible'; | ||
|
||
const getBackgroundPage = new Promise((resolve, reject) => { | ||
chrome.runtime.getBackgroundPage(resolve); | ||
}); | ||
|
||
const MAX_ISSUE_ERROR_LENGTH = 60; | ||
let siteURL = null; | ||
let statusEl = null; | ||
|
||
let siteURL = null; | ||
|
||
/** | ||
* Error strings that indicate a problem in how Lighthouse was run, not in | ||
* Lighthouse itself, mapped to more useful strings to report to the user. | ||
*/ | ||
const NON_BUG_ERROR_MESSAGES = { | ||
'Another debugger': 'You probably have DevTools open. Close DevTools to use Lighthouse', | ||
'multiple tabs': 'You probably have multiple tabs open to the same origin. ' + | ||
'Close the other tabs to use Lighthouse.', | ||
// The extension debugger API is forbidden from attaching to the web store. | ||
// @see https://chromium.googlesource.com/chromium/src/+/5d1f214db0f7996f3c17cd87093d439ce4c7f8f1/chrome/common/extensions/chrome_extensions_client.cc#232 | ||
'The extensions gallery cannot be scripted': 'The Lighthouse extension cannot audit the ' + | ||
'Chrome Web Store. If necessary, use the Lighthouse CLI to do so.', | ||
// The user tries to review an error page or has network issues | ||
'Unable to load the page': 'Unable to load the page. Please verify the url you ' + | ||
'are trying to review.' | ||
}; | ||
|
||
function getLighthouseVersion() { | ||
return chrome.runtime.getManifest().version; | ||
} | ||
function getLighthouseVersion() { | ||
return chrome.runtime.getManifest().version; | ||
} | ||
|
||
function getChromeVersion() { | ||
return /Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]; | ||
} | ||
function getChromeVersion() { | ||
return /Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]; | ||
} | ||
|
||
function buildReportErrorLink(err) { | ||
const reportErrorEl = document.createElement('a'); | ||
reportErrorEl.className = 'button button--report-error'; | ||
function startSpinner() { | ||
statusEl.classList.add(subpageVisibleClass); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
let qsBody = '**Lighthouse Version**: ' + getLighthouseVersion() + '\n'; | ||
qsBody += '**Chrome Version**: ' + getChromeVersion() + '\n'; | ||
function stopSpinner() { | ||
statusEl.classList.remove(subpageVisibleClass); | ||
} | ||
|
||
if (siteURL) { | ||
qsBody += '**URL**: ' + siteURL + '\n'; | ||
} | ||
|
||
qsBody += '**Error Message**: ' + err.message + '\n'; | ||
qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; | ||
function buildReportErrorLink(err) { | ||
const MAX_ISSUE_ERROR_LENGTH = 60; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. top level const is normal for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
const base = 'https://github.com/googlechrome/lighthouse/issues/new?'; | ||
let titleError = err.message; | ||
if (titleError.length > MAX_ISSUE_ERROR_LENGTH) { | ||
titleError = `${titleError.substring(0, MAX_ISSUE_ERROR_LENGTH - 3)}...`; | ||
} | ||
const title = encodeURI('title=Extension Error: ' + titleError); | ||
const body = '&body=' + encodeURI(qsBody); | ||
let qsBody = '**Lighthouse Version**: ' + getLighthouseVersion() + '\n'; | ||
qsBody += '**Chrome Version**: ' + getChromeVersion() + '\n'; | ||
|
||
reportErrorEl.href = base + title + body; | ||
reportErrorEl.textContent = 'Report Error'; | ||
reportErrorEl.target = '_blank'; | ||
return reportErrorEl; | ||
if (siteURL) { | ||
qsBody += '**URL**: ' + siteURL + '\n'; | ||
} | ||
|
||
function startSpinner() { | ||
statusEl.classList.add(subpageVisibleClass); | ||
} | ||
qsBody += '**Error Message**: ' + err.message + '\n'; | ||
qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; | ||
|
||
function stopSpinner() { | ||
statusEl.classList.remove(subpageVisibleClass); | ||
} | ||
const base = 'https://github.com/googlechrome/lighthouse/issues/new?'; | ||
let titleError = err.message; | ||
|
||
function logstatus([, message, details]) { | ||
statusMessageEl.textContent = message; | ||
statusDetailsMessageEl.textContent = details; | ||
if (titleError.length > MAX_ISSUE_ERROR_LENGTH) { | ||
titleError = `${titleError.substring(0, MAX_ISSUE_ERROR_LENGTH - 3)}...`; | ||
} | ||
|
||
function createOptionItem(text, isChecked) { | ||
const input = document.createElement('input'); | ||
input.setAttribute('type', 'checkbox'); | ||
input.setAttribute('value', text); | ||
if (isChecked) { | ||
input.setAttribute('checked', 'checked'); | ||
} | ||
|
||
const label = document.createElement('label'); | ||
label.appendChild(input); | ||
label.appendChild(document.createTextNode(text)); | ||
const listItem = document.createElement('li'); | ||
listItem.appendChild(label); | ||
|
||
return listItem; | ||
const title = encodeURI('title=Extension Error: ' + titleError); | ||
const body = '&body=' + encodeURI(qsBody); | ||
|
||
const reportErrorEl = document.createElement('a'); | ||
reportErrorEl.className = 'button button--report-error'; | ||
reportErrorEl.href = base + title + body; | ||
reportErrorEl.textContent = 'Report Error'; | ||
reportErrorEl.target = '_blank'; | ||
|
||
return reportErrorEl; | ||
} | ||
|
||
function logstatus([, message, details]) { | ||
document.querySelector('.status__msg').textContent = message; | ||
const statusDetailsMessageEl = document.querySelector('.status__detailsmsg'); | ||
statusDetailsMessageEl.textContent = details; | ||
} | ||
|
||
function createOptionItem(text, isChecked) { | ||
const input = document.createElement('input'); | ||
input.setAttribute('type', 'checkbox'); | ||
input.setAttribute('value', text); | ||
if (isChecked) { | ||
input.setAttribute('checked', 'checked'); | ||
} | ||
|
||
/** | ||
* Generates a document fragment containing a list of checkboxes and labels | ||
* for the aggregation categories. | ||
* @param {!Object<boolean>} selectedAggregations | ||
* @return {!DocumentFragment} | ||
*/ | ||
function generateOptionsList(list, selectedAggregations) { | ||
const frag = document.createDocumentFragment(); | ||
|
||
defaultAggregations.forEach(aggregation => { | ||
const isChecked = selectedAggregations[aggregation.name]; | ||
frag.appendChild(createOptionItem(aggregation.name, isChecked)); | ||
}); | ||
|
||
return frag; | ||
} | ||
const label = document.createElement('label'); | ||
label.appendChild(input); | ||
label.appendChild(document.createTextNode(text)); | ||
const listItem = document.createElement('li'); | ||
listItem.appendChild(label); | ||
|
||
if (background.isRunning()) { | ||
startSpinner(); | ||
} | ||
return listItem; | ||
} | ||
|
||
background.listenForStatus(logstatus); | ||
background.loadSelectedAggregations().then(aggregations => { | ||
const frag = generateOptionsList(optionsList, aggregations); | ||
optionsList.appendChild(frag); | ||
}); | ||
function onGenerateReportButtonClick() { | ||
startSpinner(); | ||
|
||
generateReportEl.addEventListener('click', () => { | ||
startSpinner(); | ||
feedbackEl.textContent = ''; | ||
const feedbackEl = document.querySelector('.feedback'); | ||
feedbackEl.textContent = ''; | ||
|
||
background.loadSelectedAggregations() | ||
.then(selectedAggregations => { | ||
getBackgroundPage.then(background => { | ||
background.loadSelectedAggregations().then(selectedAggregations => { | ||
return background.runLighthouseInExtension({ | ||
flags: { | ||
disableCpuThrottling: true | ||
}, | ||
restoreCleanState: true | ||
}, selectedAggregations); | ||
}) | ||
.catch(err => { | ||
}).catch(err => { | ||
let message = err.message; | ||
let includeReportLink = true; | ||
|
||
|
@@ -186,26 +151,69 @@ document.addEventListener('DOMContentLoaded', _ => { | |
background.console.error(err); | ||
}); | ||
}); | ||
} | ||
|
||
generateOptionsEl.addEventListener('click', () => { | ||
optionsEl.classList.add(subpageVisibleClass); | ||
}); | ||
document.addEventListener('DOMContentLoaded', _ => { | ||
getBackgroundPage.then(background => { | ||
statusEl = document.querySelector('.status'); | ||
|
||
/** | ||
* Generates a document fragment containing a list of checkboxes and labels | ||
* for the aggregation categories. | ||
* @param {!Object<boolean>} selectedAggregations | ||
* @return {!DocumentFragment} | ||
*/ | ||
function generateOptionsList(list, selectedAggregations) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move this outside of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. but needed to add a background page param to make that work. |
||
const frag = document.createDocumentFragment(); | ||
|
||
const defaultAggregations = background.getDefaultAggregations(); | ||
defaultAggregations.forEach(aggregation => { | ||
const isChecked = selectedAggregations[aggregation.name]; | ||
frag.appendChild(createOptionItem(aggregation.name, isChecked)); | ||
}); | ||
|
||
return frag; | ||
} | ||
|
||
okButton.addEventListener('click', () => { | ||
// Save selected aggregation categories on options page close. | ||
const checkedAggregations = Array.from(optionsEl.querySelectorAll(':checked')) | ||
.map(input => input.value); | ||
background.saveSelectedAggregations(checkedAggregations); | ||
if (background.isRunning()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move all the rest of this to a named setup function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
startSpinner(); | ||
} | ||
|
||
optionsEl.classList.remove(subpageVisibleClass); | ||
}); | ||
const optionsList = document.querySelector('.options__list'); | ||
|
||
chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) { | ||
if (tabs.length === 0) { | ||
return; | ||
} | ||
background.listenForStatus(logstatus); | ||
background.loadSelectedAggregations().then(aggregations => { | ||
const frag = generateOptionsList(optionsList, aggregations); | ||
optionsList.appendChild(frag); | ||
}); | ||
|
||
siteURL = new URL(tabs[0].url); | ||
siteNameEl.textContent = siteURL.origin; | ||
const generateReportEl = document.getElementById('generate-report'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
generateReportEl.addEventListener('click', onGenerateReportButtonClick); | ||
|
||
const generateOptionsEl = document.getElementById('configure-options'); | ||
const optionsEl = document.querySelector('.options'); | ||
generateOptionsEl.addEventListener('click', () => { | ||
optionsEl.classList.add(subpageVisibleClass); | ||
}); | ||
|
||
const okButton = document.getElementById('ok'); | ||
okButton.addEventListener('click', () => { | ||
// Save selected aggregation categories on options page close. | ||
const checkedAggregations = Array.from(optionsEl.querySelectorAll(':checked')) | ||
.map(input => input.value); | ||
background.saveSelectedAggregations(checkedAggregations); | ||
|
||
optionsEl.classList.remove(subpageVisibleClass); | ||
}); | ||
|
||
chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) { | ||
if (tabs.length === 0) { | ||
return; | ||
} | ||
|
||
siteURL = new URL(tabs[0].url); | ||
|
||
document.querySelector('header h2').textContent = siteURL.origin; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment here? or intermediate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not just a spinner...
showStatusSubpage
/hideStatusSubpage
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done