Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Хотя вы определенно находитесь в правильном направлении (и на самом деле довольно близки к концу), в вашем коде существует несколько (imo) плохих практик (например, для инъекции целой библиотеки (jquery) для такой тривиальной задачи, объявления ненужных разрешений , делая суперплошные вызовы API-методам и т. д.). Я сам не тестировал ваш код, но из краткого обзора считаю, что исправление следующего может привести к рабочему решению (хотя и не очень близкому к оптимальному):
onMessage
. Итак, вот мой предложенный подход:
root-directory/
|_____img
|_____icon19.png
|_____icon38.png
|_____manifest.json
|_____background.js
|_____content.js
|_____popup.js
|_____popup.html
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": true,
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["*://*.stackoverflow.com/*"],
"js": ["content.js"],
"run_at": "document_idle",
"all_frames": false
}],
"page_action": {
"default_title": "Test Extension",
//"default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
//},
"default_popup": "popup.html"
}
// No special permissions required...
//"permissions": []
}
chrome.runtime.onMessage.addListener(function (msg, sender) {
// First, validate the message's structure
if ((msg.from === 'content') && (msg.subject === 'showPageAction')) {
// Enable the page-action for the requesting tab
chrome.pageAction.show(sender.tab.id);
}
});
// Inform the background page that
// this tab should have a page-action
chrome.runtime.sendMessage({
from: 'content',
subject: 'showPageAction'
});
// Listen for messages from the popup
chrome.runtime.onMessage.addListener(function (msg, sender, response) {
// First, validate the message's structure
if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
// Collect the necessary data
// (For your specific requirements `document.querySelectorAll(...)`
// should be equivalent to jquery's `$(...)`)
var domInfo = {
total: document.querySelectorAll('*').length,
inputs: document.querySelectorAll('input').length,
buttons: document.querySelectorAll('button').length
};
// Directly respond to the sender (popup),
// through the specified callback */
response(domInfo);
}
});
// Update the relevant fields with the new data
function setDOMInfo(info) {
document.getElementById('total').textContent = info.total;
document.getElementById('inputs').textContent = info.inputs;
document.getElementById('buttons').textContent = info.buttons;
}
// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
// ...query for the active tab...
chrome.tabs.query({
active: true,
currentWindow: true
}, function (tabs) {
// ...and send a request for the DOM info...
chrome.tabs.sendMessage(
tabs[0].id,
{from: 'popup', subject: 'DOMInfo'},
// ...also specifying a callback to be called
// from the receiving end (content script)
setDOMInfo);
});
});
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<h3 style="font-weight:bold; text-align:center;">DOM Info</h3>
<table border="1" cellpadding="3" style="border-collapse:collapse;">
<tr>
<td nowrap>Total number of elements:</td>
<td align="right"><span id="total">N/A</span></td>
</tr>
<tr>
<td nowrap>Number of input elements:</td>
<td align="right"><span id="inputs">N/A</span></td>
</tr>
<tr>
<td nowrap>Number of button elements:</td>
<td align="right"><span id="buttons">N/A</span></td>
</tr>
</table>
</body>
</html>
Для этого вы можете использовать localStorage. Вы можете хранить любые данные в формате хэш-таблицы в памяти браузера, а затем обращаться к нему в любое время. Я не уверен, можем ли мы получить доступ к localStorage из сценария содержимого (ранее он был заблокирован), попробуйте сделать это самостоятельно. Вот как это сделать на вашей фоновой странице (сначала я передаю данные из сценария контента на фоновый рисунок, а затем сохранил его в localStorage):
в contentScript.js:
chrome.runtime.sendMessage({
total_elements: totalElements // or whatever you want to send
});
в eventPage.js (ваша фоновая страница):
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
localStorage["total_elements"] = request.total_elements;
}
);
Затем вы можете получить доступ к этой переменной в popup.js с помощью localStorage ["total_elements"].
Возможно, вы можете получить доступ к localStorage непосредственно из сценария содержимого в современных браузерах. Затем вам не нужно передавать данные через вашу фоновую страницу.
Хорошее чтение о localStorage: http://diveintohtml5.info/storage.html
.extension.xxx
вместо того, чтобы просто показывать правильный путь (которые некоторые люди могут рассматривать как «альтернативу в равной степени»). Думаю, это скорее вопрос стиля. Продолжайте хорошую работу !
– gkalpak
12 June 2014 в 09:08