Написал простенькое расширение, которое показывает, заблокирован ли сайт Роскомнадзором. Но Google его отклонил к публикации, объяснив, что расширение подозрительное. Как быть?
Текст письма от GoogleDear Developer,
Your Google Chrome item, "BlockListCheck", with ID:
mdbffnnpjhnfmnenfkffjohdgjfeiodn did not comply with our policies and was
removed from the Google Chrome Web Store.
We routinely review items in the Chrome Web Store for compliance with our
Program policies to ensure a safe and trusted experience for our users. Per
our policies, where possible, make as much of your code visible in the
package as you can. If some of your app's logic is hidden and it appears to
be suspicious, we may remove it. During the course of a review, your item
was found to be suspicious and has one or more file(s) that contain
minified or obfuscated code which is not human readable.
To have your item reinstated, please make any necessary changes to ensure
that all of the files and code are included in the item’s package and are
human readable.
If you'd like to re-submit your item, please make appropriate changes to
the item so that it complies with our policies, then re-publish it in your
developer dashboard. Please reply to this email for issues regarding this
item removal.
*Please keep in mind that your re-submitted item will not be immediately
published live in the store. All re-submitted items undergo a strict
compliance review and will be re-published if the item passes review.
*Important Note- Repeated or egregious violations in the store may result
in your developer account being banned from the store. This may also result
in the suspension of related Google services associated with your Google
account. All re-submitted items will continue to be subject to Chrome Web
Store policies and terms of service.
Thank you for your cooperation,
Google Chrome Web Store team
Код простейший:
popup.js - 8 строкlet time_str = chrome.extension.getBackgroundPage().temp_domain_blocked;
document.addEventListener('DOMContentLoaded', function () {
if (time_str && time_str != "?")
document.getElementById('time').innerHTML = "Дата блокировки: " + time_str;
else
document.getElementById('time').innerHTML = "В реестре отсутствует";
})
background.js - 86 строкfunction extractHostname(url) {
var hostname;
if (url.indexOf("//") > -1) {
hostname = url.split('/')[2];
}
else {
hostname = url.split('/')[0];
}
hostname = hostname.split(':')[0];
hostname = hostname.split('?')[0];
return hostname;
}
function extractRootDomain(url) {
var domain = extractHostname(url),
splitArr = domain.split('.'),
arrLen = splitArr.length;
if (arrLen > 2) {
domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1];
if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) {
domain = splitArr[arrLen - 3] + '.' + domain;
}
}
return domain;
}
var data_updated = "?";
var data_blocked_ip = {};
var data_blocked_domain = {};
var temp_domain_blocked = "?";
function updateIcon(url) {
//chrome.browserAction.setIcon({imageData:canvasContext.getImageData(0, 0, canvas.width,canvas.height)});
temp_domain_blocked = "?";
//console.log("url:",url);
if (!url)
chrome.browserAction.setIcon({path: "images/circ_gray_gray_16.png"});
else if (url.substr(0,4) != "http" && url.substr(0,5) != "https") {
chrome.browserAction.setIcon({path: "images/circ_gray_gray_16.png"});
}
else if (temp_domain_blocked = data_blocked_domain[extractHostname(url)] || data_blocked_domain[extractRootDomain(url)] ) {
chrome.browserAction.setIcon({path: "images/circ_pink_red_16.png"});
}
else
chrome.browserAction.setIcon({path: "images/circ_green_green_16.png"});
}
function addDomain(domain, date) {
data_blocked_domain[domain] = date;
}
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let data = JSON.parse(xhttp.responseText);
console.log('rules loaded');
data_updated = Object.keys(data)[0];
data = data[data_updated];
for(let i=0,len=data.length;i<len;i++){
let row = data[i];
for(let j=0;j<row.ip.length;j++) data_blocked_ip[row.ip[j]] = true;
if (row.page) addDomain(row.page, row.date);
}
console.log('done');
}
};
xhttp.open("GET", "testdata.txt", true);
xhttp.send();
chrome.tabs.onActivated.addListener(function(activeInfo) {
//console.log([activeInfo.tabId, activeInfo.windowId]);
chrome.tabs.get(activeInfo.tabId, function( tab) {
console.log("onActivated",tab.url,tab)
updateIcon(tab.url)
})
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.url && tab.active) {
console.log("onUpdated",changeInfo.url,changeInfo,tab);
updateIcon(changeInfo.url)
}
})
Разрешения - только доступ к вкладкам{
"manifest_version": 2,
"name": "BlockListCheck",
"short_name": "BlockListCheck",
"description": "Показывает в виде иконки, внесён ли сайт в реестр, и как именно.",
"version": "0.11",
"icons": {
"16": "images/logo_16.png",
"32": "images/logo_32.png",
"48": "images/logo_48.png"
},
"permissions": [
"tabs"
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"options_page": "options.html",
"browser_action": {
"default_icon": {
"16": "images/logo_16.png",
"32": "images/logo_32.png",
"48": "images/logo_48.png"
},
"default_title": "BlockListCheck",
"default_popup": "popup/popup.html"
}
}
То есть расширение даже не имеет доступа к содержимому страниц. Может только читать URL вкладки. Не обращается к внешним ресурсам! То есть априори (согласно коду) не может ничего отправить или получить с других сайтов. Код не обфусцирован и крайне простой.
База реестра Роскомнадзора скачана с
Роскомсвободы (json 20 мегабайт). И сохранена в локальном файле расширения в виде json файла. (В будущем хотел, конечно же, прикрутить авто обновление).
В чём может заключаться подозрительность, и как доказать Гуглу, что всё чисто?