Подтвердить что ты не робот

Как определить текущий тип mime tab в расширении Google Chrome?

Я хочу посмотреть, будет ли текущая вкладка PDF файлом с фоновой страницы.

Я могу проверить url для .pdf в конце, но есть некоторые файлы PDF, которые этого не имеют.

4b9b3361

Ответ 1

Вы не можете получить его, используя текущий API-интерфейс Chrome API. Вы можете снова загрузить эту страницу через XHR и проверить возвращенный заголовок типа содержимого. Что-то вроде этого:

background html:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if(changeInfo.status == "loading") {
        if(checkIfUrlHasPdfExtension(tab.url)) {
            //.pdf
            pdfDetected(tab);
        } else {
             var xhr = new XMLHttpRequest();
             xhr.open("GET", tab.url, true);
             xhr.onreadystatechange = function() {
               if (xhr.readyState == 4) {
                 var contentType = xhr.getResponseHeader("Content-Type");
                 if(checkIfContentTypeIsPdf(contentType)) {
                    pdfDetected(tab);
                 }
               }
             }
             xhr.send();
        }
    }
});

manifest.json:

"permissions": [
    "tabs", "http://*/*", "https://*/*"
]

Для возвращаемых файлов PDF тип содержимого должен быть application/pdf. Что-то, о чем следует помнить, состоит в том, что заголовок содержимого также может содержать кодировку: text/html; charset=UTF-8.

Ответ 2

Выдача нового запроса только для получения типа MIME немного тяжела и не надежна. Например, если отображаемая на данный момент страница является результатом отправки формы POST, выдача запроса GET обычно не приведет к одной странице.

Если вы разрабатываете расширение, для которого часто требуется доступ к этой информации, используйте chrome.webRequest API для отслеживания ответов. Следующее демонстрационное расширение отображает тип содержимого при нажатии кнопки браузера:

// background.js
var tabToMimeType = {};
chrome.webRequest.onHeadersReceived.addListener(function(details) {
    if (details.tabId !== -1) {
        var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
        // If the header is set, use its value. Otherwise, use undefined.
        tabToMimeType[details.tabId] = header && header.value.split(';', 1)[0];
    }
}, {
    urls: ['*://*/*'],
    types: ['main_frame']
}, ['responseHeaders']);

chrome.browserAction.onClicked.addListener(function(tab) {
    alert('Tab with URL ' + tab.url + ' has MIME-type ' + tabToMimeType[tab.id]);
});

function getHeaderFromHeaders(headers, headerName) {
    for (var i = 0; i < headers.length; ++i) {
        var header = headers[i];
        if (header.name.toLowerCase() === headerName) {
            return header;
        }
    }
}

Примечания:

  • Это расширение отображает результат только для вкладок, загружаемых после загрузки расширения.
  • Это работает только на страницах http/https. ftp:, file:, filesystem:, blob:, data: не поддерживается.
  • Если MIME-тип не задан сервером или когда тип MIME text/plain, Chrome возвращается к MIME sniffing, если только X-Content-Type-Options: nosniff не является задавать. В первом случае обнаруженный MIME-тип может быть любым. В последнем случае MIME-тип по умолчанию - text/plain.

Для полноты, вот файл manifest.json, который можно использовать для проверки предыдущего кода:

{
    "name": "Click button to see MIME",
    "version": "1",
    "manifest_version": 2,
    "background": {
        "scripts": ["background.js"],
        "persistent": true
    },
    "browser_action": {
        "default_title": "Show MIME"
    },
    "permissions": [
        "webRequest",
        "activeTab",
        "*://*/*"
    ]
}

Ответ 3

Несколько хакерский способ (я понятия не имею, работает ли он всегда или просто иногда), чтобы посмотреть содержимое страницы. Там вы найдете элемент для просмотра chrome PDF. Он выглядит следующим образом:

<embed width="100%" height="100%" name="plugin" src="https://example.com/document.pdf" type="application/pdf">

Вы можете проверить атрибут "type", чтобы узнать, с чем имеете дело.

Ответ 4

Мне нужно было сделать что-то подобное в одном из моих расширений и сделать что-то очень похожее на ответ, заданный @serg, но вместо этого используя запрос HEAD. Теоретически запрос HEAD должен быть идентичен запросу GET, но без отправки тела ответа, которое в случае изображения или файла может быть довольно большим количеством дополнительных данных и времени ожидания.

Я также разбиваю и сдвигаю заголовок, чтобы удалить любые кодировки, которые могут быть добавлены в тип содержимого.

getContentType: function(tab, callback){
    var xhr = new XMLHttpRequest();
    xhr.open("HEAD", tab.url, false);
    xhr.onload =  function(e) {
        if (xhr.readyState === 4) {
            if(xhr.status === 200) {
                callback(xhr.getResponseHeader("Content-Type").split(";").shift());
            }
            else{
                callback('Unknown');
                console.error(xhr.statusText);
                return;
            }
        }
    };

    xhr.onerror = function (e) {
        console.error(xhr.statusText);
        return;
    };

    xhr.send();
}