2011-02-07 22 views

Respuesta

4

No se puede obtener usando afaik de API de Chrome actual. Lo que puede hacer es cargar esta página nuevamente a través del XHR y verificar el encabezado de tipo de contenido devuelto. Algo como esto:

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

Para los archivos PDF regresaron tipo de contenido debe ser application/pdf. Algo a tener en cuenta es que el encabezado de tipo de contenido también podría contener codificación: text/html; charset=UTF-8.

+1

Gracias, creo que eso funcionaría. Pero me temo que no lo usaré porque cada página se cargará dos veces. – Orny

+0

@Orny Estoy de acuerdo, solo verificaría la extensión de PDF, debería ser suficiente para el 99% de los casos – serg

+0

Estaba buscando algo como esto, y porque lo usaré solo al abrir la ventana emergente de extensión, creo (espero) que la solicitud usará la página en caché en la mayoría de los casos. – Omiod

10

Emitir una nueva solicitud solo para obtener el tipo MIME es un poco pesado, y no es confiable. Por ejemplo, si la página que se muestra actualmente es el resultado de un envío de formulario POST, la emisión de una solicitud GET generalmente no conducirá a la misma página.

Si está desarrollando una extensión que con frecuencia necesita acceso a esta información, use la API chrome.webRequest para rastrear las respuestas. La siguiente extensión de demostración muestra el tipo de contenido al hacer clic en el botón del navegador:

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

Notas:

  • Esta extensión sólo se muestra el resultado de pestañas que se cargan después se carga la extensión.
  • Esto solo funciona en páginas http/https. ftp :, file :, filesystem :, blob :, data: no es compatible.
  • Cuando el servidor no especifica ningún tipo MIME o cuando el tipo MIME es text/plain, Chrome vuelve a MIME sniffing a menos que se configure X-Content-Type-Options: nosniff. En el primer caso, el tipo MIME detectado podría ser cualquier cosa. En este último caso, el tipo MIME predeterminado es text/plain.

Para completar, aquí es un archivo manifest.json que se puede utilizar para probar el código anterior:

{ 
    "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

Tu respuesta es muy detallada y útil. ¡Gracias! –

+2

Muy útil. Esto es mucho mejor que la respuesta aceptada: ninguna extensión debe volver a solicitar el encabezado en la práctica. –

1

Una forma un tanto hacker (no tengo ni idea de si funciona siempre o sólo a veces) es mira el contenido de la página. Allí encontrará un elemento para el visor de PDF de Chrome. Se ve a lo largo de estas líneas:

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

Puede verificar ese atributo "tipo" para ver a qué se enfrenta.

+1

Esto realmente fue el truco para mí, ¡muchas gracias! Es un tanto hackiano, pero parece ser la única manera que funciona también para las URL "file: //" (siempre que manifest.json declare que los scripts inyectados deben ir a las URL que coinciden con un selector "file: // *") . Aquí está el código que utilicé en el script inyectado: 'if (document.body.childElementCount === 1) { \t var embed = document.body.firstElementChild; \t if (embed.tagName === "EMBED" && embed.getAttribute ("type") === "application/pdf") {/ * haz algo * /}} ' – robamler

0

Tuve que hacer algo similar en una de mis extensiones e hice algo muy similar a the answer dado por @serg pero usando una solicitud HEAD en su lugar.En teoría, una solicitud HEAD debe ser idéntica a una solicitud GET, pero sin enviar el cuerpo de respuesta, que en el caso de una imagen o archivo podría ser un poco extra de datos y tiempo de espera.

También divido y cambio el encabezado para descartar cualquier conjunto de caracteres que pueda agregarse en el tipo de contenido.

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(); 
} 
Cuestiones relacionadas