До того, как мы будем выполнять запросы к внешним ресурсам, надо внести изменения в manifest.json, дав соответствующее разрешение "<all_urls>" в permissions.
Все разрешения для нашего аддона:
"permissions": [
"activeTab",
"tabs",
"storage",
"<all_urls>"
]
Внимание! Если разрешение "<all_urls>" не дать, то при попытке обращения к внешнему ресурсу произойдет ошибка:
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://api.myip.com/. (Причина: отсутствует заголовок CORS «Access-Control-Allow-Origin»).
Почему-то ссылка на пояснение к ошибке на сайте Мозиллы ведет не совсем на то, что нужно, а в поиске, тоже неизвестно почему, информация о том, что нужно просто дать разрешение "<all_urls>" в manifest.json не всплывает. Сам еле догадался, практически методом научного тыка устранил данный глюк.
После долгого ковыряния в отладке и интернете я решил немного отдохнуть, и дополнить дизайн расширения.
Фактически, у запроса есть три состояния:
— запрос выполняется
— запрос выполнен успешно
— запрос завершен с ошибкой
Обо всем этом можно и нужно сообщать пользователю, и симпатичнее всего это сделать, меняя иконку. Нарисовал и сохранил в каталог flags.
— запрос выполняется (1working.png)
— запрос завершен с ошибкой (2error.png)
— если запрос выполнен успешно, то будем показывать флаг страны, как и планировалось изначально. Но, на всякий случай, можно предусмотреть ситуацию, когда страну определить не удалось (с api.myip.com это вряд ли случится, но с другим скриптом, выдающим данные в том же формате может быть).
— страна неизвестна (3unknow.png)
GET-запрос к сайту оказалось проще всего сделать с помощью библиотеки JQuery.
Скачиваем библиотеку и сохраняем ее в каталог с ip_popup.html. В самом ip_popup.html подключаем ее (перед скриптом ip_popup.js):
<script src="jquery-3.4.1.min.js"></script>
Правим ip_popup.js.
Понятно, что пока мы не получим адрес сайта из хранилища, запрос мы сделать не сможем, а функция browser.storage.local.get работает асинхронно и возвращает промис (gettingItem), на который мы навесили обработчики onGot и onGotError, но прикол в том, что then в gettingItem.then(onGot, onGotError) тоже возвращает промис! К которому, в свою очередь, можно подцепится с помощью then. И пока первый промис в цепочке не завершит работу, второй работу не начнет.
Подробности: Использование промисов
Поэтому, модифицируем функцию loadSettings так, чтобы она возвращала промис, просто добавив return:
Было:
function loadSettings()
{
var gettingItem = browser.storage.local.get('server_settings');
gettingItem.then(onGot, onGotError);
}
Стало:
function loadSettings()
{
var gettingItem = browser.storage.local.get('server_settings');
return gettingItem.then(onGot, onGotError);
}
Далее модифицируем функцию bodyLoad добавив после loadSettings следующее звено цепочки:
function bodyLoad()
{
loadSettings()
.then(doRequest);
}
В функции doRequest будем выполнять GET-запрос и обрабатывать результат.
До самого запроса меняем иконку во всплывающем окне:
document.getElementById("flag").src = 'flags/1working.png';
document.getElementById("flag").alt = 'Working';
document.getElementById("flag").title = 'working...';
Далее, выполняем запрос и обрабатываем результат, так, как сказано в мануале JQuery. Функции JQuery вызываются через $.<функция>
$.get(curAddr)
.done (function (data) {
//запрос успешно завершен, тут будет код обработки данных
})
.fail(function () {
// ошибка запроса, обрабатываем ошибку
});
Подробности: jQuery.get()
.done передаем функцию-коллбэк со следующим кодом:
var json = $.parseJSON(data);
document.getElementById("ip").value = json.ip;
document.getElementById("country").value = json.country;
if (json.cc.trim() == '') //no country code
{
document.getElementById("flag").src = 'flags/3unknow.png';
document.getElementById("flag").alt = 'Unknow';
document.getElementById("flag").title = 'Unknow country code';
}
else //country code exist
{
document.getElementById("flag").src = 'flags/'+json.cc.trim()+'.png';
document.getElementById("flag").alt = json.cc;
document.getElementById("flag").title = json.cc;
}
1. Распарсим, опять же, средствами JQuery ($.parseJSON(data)) полученные от сайта данные.
2. Присвоим полям с id ip и id country значения, соответственно, IP-адреса и названия страны.
3. Если поле cc, объекта json пустое, значит не удалось определить код страны. Присваиваем изображению флага картинку неопознанной страны, а свойствам изображения alt и title (всплывающая подсказка), соответствующие значения.
4. Если код страны не пустой, т.е. страна определена, присваиваем изображению соответствующую картинку с флагом (файлы флагов названы в соответствии с кодом страны) и сам код в качестве описания и всплывающей подсказки.
Функция doRequest() целиком:
function doRequest() //main request function
{
document.getElementById("flag").src = 'flags/1working.png';
document.getElementById("flag").alt = 'Working';
document.getElementById("flag").title = 'working...';
$.get(curAddr)
.done (function (data) {
//data processing code here
var json = $.parseJSON(data);
document.getElementById("ip").value = json.ip;
document.getElementById("country").value = json.country;
if (json.cc.trim() == '') //no country code
{
document.getElementById("flag").src = 'flags/3unknow.png';
document.getElementById("flag").alt = 'Unknow';
document.getElementById("flag").title = 'Unknow country code';
}
else //country code exist
{
document.getElementById("flag").src = 'flags/'+json.cc.trim()+'.png';
document.getElementById("flag").alt = json.cc;
document.getElementById("flag").title = json.cc;
}
})
.fail(function () {
//error processing code here
document.getElementById("flag").src = 'flags/2error.png';
document.getElementById("flag").alt = 'Error';
document.getElementById("flag").title = 'Error';
});
}
Вот, что получилось:
— Работает:



На этом разработку всплывающего окна можно считать завершенной.