2011-02-07 10 views

risposta

4

Non è possibile ottenerlo utilizzando l'afAk dell'API di Chrome corrente. Quello che puoi fare è caricare di nuovo questa pagina tramite XHR e controllare l'intestazione del tipo di contenuto restituito. Qualcosa di simile a questo:

sfondo 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://*/*" 
] 

Per i file PDF restituito tipo di contenuto dovrebbe essere application/pdf. Qualcosa da tenere a mente però è che l'intestazione content-type potrebbe contenere anche la codifica: text/html; charset=UTF-8.

+1

Grazie credo che funzionerebbe. Ma temo che non lo userò perché ogni pagina verrebbe caricata due volte. – Orny

+0

@Orny Sono d'accordo, vorrei solo controllare l'estensione pdf, dovrebbe essere sufficiente per il 99% dei casi – serg

+0

Ero alla ricerca di qualcosa di simile, e poiché lo userò solo aprendo il popup dell'estensione, penso (spero) che la richiesta utilizzerà la pagina cache nella maggior parte dei casi. – Omiod

10

L'emissione di una nuova richiesta solo per ottenere il tipo MIME è un po 'pesante e non affidabile. Ad esempio, se la pagina attualmente visualizzata è il risultato di un invio di un modulo POST, quindi l'emissione di una richiesta GET di solito non porterà alla stessa pagina.

Se si sta sviluppando un'estensione che richiede spesso l'accesso a queste informazioni, utilizzare l'API chrome.webRequest per tenere traccia delle risposte. La seguente estensione demo mostra il tipo di contenuto su clic del pulsante del browser:

// 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; 
     } 
    } 
} 

Note:

  • Questa estensione mostra solo il risultato per le schede che vengono caricati dopo viene caricato l'estensione.
  • Funziona solo su pagine http/https. ftp :, file :, filesystem :, blob :, data: non è supportato.
  • Se il server non specifica un tipo MIME o quando il tipo MIME è text/plain, Chrome torna a MIME sniffing a meno che non sia impostato X-Content-Type-Options: nosniff. Nel primo caso, il tipo MIME rilevato potrebbe essere qualsiasi cosa. In quest'ultimo caso, il tipo MIME predefinito è text/plain.

Per completezza, ecco un file di manifest.json che può essere utilizzato per testare il codice precedente:

{ 
    "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", 
     "*://*/*" 
    ] 
} 
+0

La tua risposta è molto dettagliata e utile. Grazie! –

+2

Davvero utile. Questo è molto meglio della risposta accettata - nessuna estensione dovrebbe richiedere nuovamente l'intestazione nella pratica. –

1

Un modo un po 'hackish (non ho idea se funziona sempre o solo a volte) è quello di guarda il contenuto della pagina. Lì troverai un elemento per il visualizzatore PDF di Chrome. Guarda su queste righe:

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

È possibile verificare che l'attributo "tipo" per vedere ciò che si sta trattando.

+1

Questo davvero ha fatto il trucco per me, grazie mille! È in qualche modo un hacker, ma sembra essere l'unico modo che funziona anche per gli URL "file: //" (a condizione che manifest.json dichiari che gli script inseriti devono essere inseriti in URL che corrispondono a un selettore "file: // *") . Ecco il codice che ho usato nello script iniettato: 'if (document.body.childElementCount === 1) { \t var embed = document.body.firstElementChild; \t if (embed.tagName === "EMBED" && embed.getAttribute ("tipo") === "application/pdf") {/ * fare qualcosa * /}} ' – robamler

0

Ho dovuto fare qualcosa di simile in una delle mie estensioni e ho fatto qualcosa di molto simile a the answer dato da @serg ma utilizzando invece una richiesta HEAD.In teoria, una richiesta HEAD dovrebbe essere identica a una richiesta GET ma senza inviare il corpo della risposta, che nel caso di un'immagine o di un file potrebbe essere un bel po 'di dati extra e di tempo in attesa.

Ho anche diviso e spostato l'intestazione per eliminare tutti i set di caratteri che potrebbero essere aggiunti al tipo di contenuto.

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(); 
} 
Problemi correlati