JavaScript en AIR

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

AIR modifica de varias maneras el comportamiento típico de objetos comunes de JavaScript. Muchas de estas modificaciones tienen la finalidad de facilitar la escritura de aplicaciones seguras en AIR. Al mismo tiempo, debido a estas diferencias de comportamiento es posible que algunos patrones de codificación de JavaScript, así como las aplicaciones web existentes que utilicen esos patrones, no siempre se ejecutan de la forma prevista en AIR. Para obtener información sobre la corrección de este tipo de problema, consulte Cómo evitar errores de JavaScript relacionados con la seguridad .

Entornos limitados en HTML

AIR pone contenido en entornos limitados aislados en función del origen del contenido. Las reglas de entornos limitados son coherentes con la política de "mismo origen" que implementa la mayoría de los navegadores web, además de las reglas para entornos limitados implementados por Adobe Flash Player. Por otra parte, AIR proporciona un nuevo tipo de entorno limitado de la aplicación que contiene y protege el contenido de la aplicación. Para obtener más información sobre los tipos de entornos limitados que puede encontrar al desarrollar aplicaciones de AIR, consulte Entornos limitados de seguridad .

El acceso al entorno del motor de ejecución y las API de AIR solo está disponible para HTML y JavaScript cuando se ejecutan en el entorno limitado de la aplicación Al mismo tiempo, la ejecución y evaluación dinámica de JavaScript, en sus diversas modalidades, está en gran medida restringida en el entorno limitado de la aplicación por razones de seguridad. Estas restricciones rigen independientemente de si la aplicación carga información directamente desde un servidor o no. (Incluso el contenido de los archivos, las cadenas pegadas y la información introducida por el usuario pueden no ser fidedignos).

El origen del contenido de una página determina el entorno limitado al que se consigna. En el entorno limitado de la aplicación solo se pone el contenido cargado desde el directorio de la aplicación (el directorio de instalación al que remite el esquema app: de URL). El contenido cargado desde el sistema de archivos se pone en el entorno limitado local con sistema de archivos o local de confianza , que permite el acceso y la interacción con el contenido del sistema de archivos local, pero no con el contenido remoto. El contenido cargado desde la red se pone en un entorno limitado remoto que corresponde con su dominio de origen.

Para que una página de una aplicación pueda interactuar libremente con el contenido de un entorno limitado remoto, la página se puede asignar al mismo dominio que el contenido remoto. Por ejemplo, si es escribe una aplicación que muestra datos de mapas de un servicio de Internet, la página de la aplicación que descarga el contenido del servicio y lo presenta puede asignarse al dominio del servicio. Los atributos para asignar páginas en un entorno limitado remoto y un dominio son atributos nuevos que se añaden a los elementos de frame e iframe en HTML.

Para que el contenido de un entorno limitado ajeno a la aplicación pueda utilizar las funciones de AIR de forma segura, se puede establecer un puente de entorno limitado principal. Para que el contenido de la aplicación pueda llamar a métodos y tener acceso a propiedades del contenido de otros entornos limitados, se puede establecer un puente de entorno limitado secundario. La seguridad en este contexto significa que el contenido remoto no puede obtener accidentalmente referencias a objetos, propiedades o métodos que no están expuestos de forma explícita. Solo pueden pasar por el puente los tipos de datos, funciones y objetos anónimos sencillos. No obstante, aun así debe evitarse exponer explícitamente las funciones que sean potencialmente peligrosas. Por ejemplo: si expusiera una interfaz que permite que un contenido remoto lea y escriba archivos en cualquier parte del sistema del usuario, podría estar facilitando al contenido remoto los medios para causar graves daños al usuario.

Función eval() de JavaScript

Una vez que ha terminado de cargarse una página, el uso de la función eval() queda restringido al entorno limitado de la aplicación. Se admiten algunos usos para que datos en formato JSON puedan analizarse con seguridad, pero toda evaluación que arroje sentencias ejecutables producirá un error. En Restricciones de código del contenido en entornos limitados diferentes se describen los usos admitidos de la función eval() .

Constructores Function

En el entorno limitado de la aplicación pueden utilizarse constructores de función antes de que se termine de cargar una página. Una vez que han terminado todos los controladores de eventos load de la página, no se pueden crear funciones nuevas.

Carga de scripts externos

Las páginas en HTML del entorno limitado de la aplicación no pueden utilizar la etiqueta script para cargar archivos JavaScript desde fuera del directorio de la aplicación. Para que una página de la aplicación cargue un script desde fuera del directorio de la aplicación, la página debe asignarse a un entorno limitado externo.

Objeto XMLHttpRequest

AIR proporciona un objeto XMLHttpRequest (XHR) que pueden utilizar las aplicaciones para realizar peticiones de datos. El ejemplo siguiente ilustra una petición de datos sencilla:

xmlhttp = new XMLHttpRequest(); 
xmlhttp.open("GET", "http:/www.example.com/file.data", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
        //do something with data... 
    } 
} 
xmlhttp.send(null); 

A diferencia de los navegadores, AIR permite que el contenido que se ejecuta en el entorno limitado de la aplicación solicite datos de cualquier dominio. El resultado de una petición XHR que contiene una cadena JSON puede producir objetos de datos, a menos que el resultado también contenga código ejecutable. Si hay sentencias ejecutables en el resultado de la XHR, se emite un error y el intento de evaluación falla.

Para evitar la inyección accidental de código desde fuentes remotas, las XHR sincrónicas devuelven un resultado vacío si se realizan antes de haberse terminado de cargar la página. Las XHR asíncronas siempre devuelven un resultado después de haberse cargado una página.

De forma predeterminada, AIR bloquea las peticiones XMLHttpRequest entre dominios en los entornos limitados ajenos a la aplicación. Una ventana principal en el entorno limitado de la aplicación puede optar por permitir las peticiones entre dominios en un fotograma secundario que contenga contenido en un entorno limitado ajeno a la aplicación definiendo allowCrossDomainXHR -un atributo que añade AIR- en true en el elemento frame o iframe contenedor:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    allowCrossDomainXHR="true" 
</iframe>
Nota: si conviene, la clase URLStream de AIR también puede utilizarse para descargar datos.

Si se distribuye una petición XMLHttpRequest a un servidor remoto desde un fotograma o iframe que contenga contenido de la aplicación que se ha asignado a un entorno limitado remoto, asegúrese de que la URL de asignación no oculte la dirección del servidor que se utiliza en la XHR. Tomemos por ejemplo la siguiente definición de iframe, que asigna contenido de la aplicación a un entorno limitado remoto para el dominio example.com:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/" 
    allowCrossDomainXHR="true" 
</iframe>

Debido a que el atributo sandboxRoot reasigna la URL raíz de la dirección www.example.com, todas las peticiones se cargan desde el directorio de la aplicación y no desde el servidor remoto. Las peticiones se reasignan independientemente de si derivan de haber visitado distintas páginas o de una petición XMLHttpRequest.

Para evitar bloquear accidentalmente las peticiones de datos al servidor remoto, asigne sandboxRoot a un subdirectorio de la URL remota y no a la raíz. No es necesario que exista el directorio. Por ejemplo, para permitir que las peticiones a www.example.com se carguen desde el servidor remoto en lugar del directorio de la aplicación, cambie el iframe anterior a:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/air/" 
    allowCrossDomainXHR="true" 
</iframe>

En este caso, solo se carga localmente el contenido del subdirectorio air .

Para obtener más información, consulte Elementos frame e iframe de HTML y Seguridad HTML en Adobe AIR .

Cookies

En las aplicaciones de AIR solo el contenido de los entornos limitados remotos (contenido cargado desde fuentes http: y https:) puede utilizar cookies (la propiedad document.cookie ). En el entorno limitado de la aplicación, existen otros medios para almacenar datos persistentes, incluyendo las clases EncryptedLocalStore, SharedObject y FileStream.

Objeto Clipboard

La API Clipboard del WebKit funciona con los eventos copy , cut y paste . El objeto de evento que se pasa en estos eventos proporciona acceso al portapapeles a través de la propiedad clipboardData . Para leer o escribir datos en el portapapeles, utilice los siguientes métodos del objeto clipboardData :

Método

Descripción

clearData(mimeType)

Borra los datos del portapapeles. Defina el parámetro mimeType en el tipo MIME de los datos a borrar.

getData(mimeType)

Obtiene los datos del portapapeles. Este método solo se puede llamar en un controlador del evento paste . Defina el parámetro mimeType en el tipo MIME de los datos a devolver.

setData(mimeType, data)

Copia datos en el portapapeles. Defina el parámetro mimeType en el tipo MIME de los datos.

El código JavaScript que esté fuera del entorno limitado de la aplicación solo tiene acceso al portapapeles a través de estos eventos. No obstante, el contenido del entorno limitado de la aplicación tiene acceso directo al portapapeles del sistema a través de la clase Clipboard de AIR. Por ejemplo, se puede utilizar la siguiente sentencia para obtener datos en formato de texto del portapapeles:

var clipping = air.Clipboard.generalClipboard.getData("text/plain", 
                                air.ClipboardTransferMode.ORIGINAL_ONLY);

Los tipos de datos MIME válidos son:

Tipo MIME

Valor

Texto

"text/plain"

HTML

"text/html"

URL

"text/uri-list"

Mapa de bits

"image/x-vnd.adobe.air.bitmap"

Lista de archivos

"application/x-vnd.adobe.air.file-list"

Importante: únicamente el contenido del entorno limitado de la aplicación tiene acceso a los datos de archivo que hay en el portapapeles. Si un contenido ajeno a la aplicación intenta acceder a un objeto de archivo desde el portapapeles, se emite un error de seguridad.

Para obtener más información sobre el uso del portapapeles, consulte Copiar y pegar y Using the Pasteboard from JavaScript (Uso del Pasteboard de JavaScript) (Centro de desarrollo de Apple) .

Arrastrar y colocar

Los gestos de arrastrar y colocar hacia dentro y hacia fuera de HTML producen los siguientes eventos del DOM: dragstart , drag , dragend , dragenter , dragover , dragleave y drop . El objeto de evento que se pasa en estos eventos proporciona acceso a los datos arrastrados a través de la propiedad dataTransfer . La propiedad dataTransfer hace referencia a un objeto que proporciona los mismos métodos que el objeto clipboardData asociado con un evento clipboard. Por ejemplo, se puede utilizar la siguiente función para obtener datos en formato de texto de un evento drop :

function onDrop(dragEvent){ 
    return dragEvent.dataTransfer.getData("text/plain",  
            air.ClipboardTransferMode.ORIGINAL_ONLY); 
}

El objeto dataTransfer tiene los siguientes miembros importantes:

Miembro

Descripción

clearData(mimeType)

Borra los datos. Defina el parámetro mimeType en el tipo MIME de la representación de datos a borrar.

getData(mimeType)

Obtiene los datos arrastrados. Este método solo se puede llamar en un controlador del evento drop . Defina el parámetro mimeType en el tipo MIME de los datos a obtener.

setData(mimeType, data)

Defina los datos a arrastrar. Defina el parámetro mimeType en el tipo MIME de los datos.

types

Un conjunto de cadenas que contiene los tipos MIME de todas las representaciones de datos que están disponibles actualmente en el objeto dataTransfer .

effectsAllowed

Especifica si los datos arrastrados se pueden copiar, mover o vincular, o una combinación de estas operaciones. Defina la propiedad effectsAllowed en el controlador del evento dragstart .

dropEffect

Especifica qué efectos de arrastrar admitidos se pueden utilizar con un destino de arrastre. Defina la propiedad dropEffect en el controlador del evento dragEnter . Durante la operación de arrastrar el cursor cambia para indicar qué efecto se produciría si el usuario soltara el ratón. Si no se especifica nada para dropEffect , se elige un efecto para la propiedad effectsAllowed . El efecto de copia tiene prioridad sobre el efecto de mover, que a su vez tiene prioridad sobre el efecto de vinculación. El usuario puede modificar la prioridad determinada con el teclado.

Para obtener más información sobre cómo ampliar la compatibilidad con arrastrar y colocar en una aplicación de AIR, consulte Operación de arrastrar y colocar en AIR y Using the Drag-and-Drop from JavaScript (Uso de arrastrar y colocar de JavaScript) (Centro de desarrollo de Apple) .

Propiedades innerHTML y outerHTML

AIR impone restricciones de seguridad en el uso de las propiedades innerHTML y outerHTML para contenido que se ejecuta en el entorno limitado de la aplicación. Previo al evento de cargar la página, así como durante la ejecución de un controlador de eventos de carga, el uso de las propiedades innerHTML y outerHTML es irrestricto. Sin embargo, una vez cargada la página solo se puede utilizar una propiedad innerHTML o outerHTML para añadir contenido estático al documento. Se pasa por alto toda sentencia en la cadena asignada a innerHTML o outerHTML que produzca código ejecutable. Por ejemplo, si se incluye un atributo callback de evento en la definición de un elemento, no se añade el detector de eventos. Asimismo, no se evalúan las etiquetas <script> . Para obtener más información, consulte Seguridad HTML en Adobe AIR .

Métodos Document.write() y Document.writeln()

El uso de los métodos write() y writeln() no está restringido en el entorno limitado de la aplicación previo al evento load de la página. Sin embargo, una vez cargada la página, al llamar a cualquiera de estos dos métodos la página no se borra ni se crea una nueva. En un entorno limitado ajeno a la aplicación, al igual que con la mayoría de los navegadores web, cuando se llama a document.write() o writeln() tras haberse terminado de cargar una página, la página actual se borra y se abre una nueva página en blanco.

Propiedad Document.designMode

Defina la propiedad document.designMode en on para que todos los elementos del documento sean editables. Entre las funciones integradas del editor se encuentran las de editar texto, copiar, pegar, y arrastrar y pegar. Definir designMode en on equivale a definir la propiedad contentEditable del elemento body en true . La propiedad contentEditable puede utilizarse en la mayoría de los elementos HTML para definir qué secciones de un documento son editables. Para obtener más información, consulte Atributo HTML contentEditable .

Eventos unload (para objetos body y frameset)

En la etiqueta de nivel superior frameset o body de una ventana (incluida la ventana principal de la aplicación) no se debe utilizar un evento unload para responder a la acción de cerrar la ventana (o aplicación). En su lugar, utilice el evento exiting del objeto NativeApplication (para detectar cuándo se cierra una aplicación). O bien, utilice el evento closing del objeto NativeWindow (para detectar cuándo se cierra una ventana). Por ejemplo, el siguiente código JavaScript presenta un mensaje ( "Goodbye." ) cuando el usuario cierra la aplicación:

var app = air.NativeApplication.nativeApplication; 
app.addEventListener(air.Event.EXITING, closeHandler); 
function closeHandler(event) 
{ 
    alert("Goodbye."); 
}

No obstante, los scripts sí pueden responder satisfactoriamente al evento unload provocado por la navegación por el contenido de un fotograma, iframe o ventana de nivel superior.

Nota: es posible que estas limitaciones se eliminen en una versión futura de Adobe AIR.

Objeto Window en JavaScript

El objeto Window (ventana) sigue siendo el objeto global en el contexto de la ejecución de JavaScript. En el entorno limitado de la aplicación, AIR añade nuevas propiedades al objeto Window de JavaScript para facilitar el acceso a las clases integradas de AIR, además de importantes objetos host. Por otra parte, algunos métodos y propiedades se comportan de distinta manera, según se encuentren o no en el entorno limitado de la aplicación.

Propiedad Window.runtime
La propiedad runtime permite instanciar y utilizar las clases runtime integradas desde el entorno limitado de la aplicación. Estas clases incluyen las API de AIR y Flash Player (pero no, por ejemplo, la arquitectura de Flex). Por ejemplo, la sentencia siguiente crea un objeto de archivo de AIR:
var preferencesFile = new window.runtime.flash.filesystem.File();

El archivo AIRAliases.js , incluido con el SDK de AIR, contiene definiciones de alias que permiten abreviar estas referencias. Por ejemplo, cuando se importa AIRAliases.js en una página, se puede crear un objeto File con la sentencia siguiente:

var preferencesFile = new air.File();

La propiedad window.runtime solo se define para contenido que se encuentra en el entorno limitado de la aplicación, y solo para el documento principal de una página con fotogramas o iframes.

Consulte el apartado Uso del archivo AIRAliases.js .

Propiedad Window.nativeWindow
La propiedad nativeWindow proporciona una referencia al objeto de ventana nativa subyacente. Con esta propiedad se pueden programar funciones y propiedades de ventanas como posición en la pantalla, tamaño y visibilidad, así como controlar eventos de ventanas como cerrar, redimensionar y trasladar. Por ejemplo, la sentencia siguiente cierra la ventana:
window.nativeWindow.close();
Nota: las funciones de control de ventanas que ofrece el objeto NativeWindow coinciden en parte con las funciones que brinda el objeto Window de JavaScript. En estos casos, se puede utilizar el método que más convenga.

La propiedad window.nativeWindow solo se define para contenido que se encuentra en el entorno limitado de la aplicación, y solo para el documento principal de una página con fotogramas o iframes.

Propiedad Window.htmlLoader
La propiedad htmlLoader proporciona una referencia al objeto HTMLLoader de AIR que contiene el contenido HTML. Con esta propiedad se puede programar el aspecto y comportamiento del entorno HTML. Por ejemplo, se puede utilizar la propiedad htmlLoader.paintsDefaultBackground para determinar si el control pinta un fondo blanco predeterminado:
window.htmlLoader.paintsDefaultBackground = false;
Nota: el objeto HTMLLoader en sí tiene una propiedad window que hace referencia al objeto Window de JavaScript del contenido HTML que contiene. Esta propiedad puede utilizarse para acceder al entorno JavaScript a través de una referencia al HTMLLoader contenedor.

La propiedad window.htmlLoader solo se define para contenido que se encuentra en el entorno limitado de la aplicación, y solo para el documento principal de una página con fotogramas o iframes.

Propiedades Window.parentSandboxBridge y Window.childSandboxBridge
Las propiedades parentSandboxBridge y childSandboxBridge permiten definir una interfaz entre un fotograma principal y uno secundario. Para obtener más información, consulte Uso de scripts entre contenidos en diferentes entornos limitados de seguridad .

Funciones Window.setTimeout() y Window.setInterval()
AIR impone restricciones de seguridad en el uso de las funciones setTimeout() y setInterval() en el entorno limitado de la aplicación. Cuando se llama a setTimeout() o setInterval() , el código a ejecutarse no se puede definir en forma de cadena, sino que se debe utilizar una referencia a una función. Para obtener más información, consulte el apartado setTimeout() y setInterval() .

Función Window.open()
Cuando lo llama un código que se ejecuta en un entorno limitado ajeno a la aplicación, el método open() solo abre una ventana si la llamada es el resultado de una interacción del usuario (por ejemplo, tras haber pulsado una tecla o el botón del ratón). Además, el título de la ventana tiene como prefijo el título de la aplicación (para evitar que las ventanas abiertas por contenido remoto se hagan pasar por ventanas abiertas por la aplicación). Para obtener más información, consulte Restricciones para llamar al método window.open() JavaScript .

Objeto air.NativeApplication

El objeto NativeApplication facilita información sobre el estado de la aplicación, distribuye varios eventos importantes a nivel de aplicación y ofrece funciones de utilidad para controlar el comportamiento de la aplicación. Se crea automáticamente una única instancia del objeto NativeApplication, a la que se tiene acceso a través de la propiedad NativeApplication.nativeApplication definida por la clase.

Para acceder al objeto desde el código JavaScript se puede usar:

var app = window.runtime.flash.desktop.NativeApplication.nativeApplication;

O bien, si se ha importado el script AIRAliases.js , se puede utilizar la forma abreviada:

var app = air.NativeApplication.nativeApplication;

Solo se tiene acceso al objeto NativeApplication desde el entorno limitado de la aplicación. Para obtener más información sobre el objeto NativeApplication, consulte Trabajo con información sobre el motor de ejecución de AIR y el sistema operativo .

Esquema URL de JavaScript

La ejecución del código definido en un esquema URL de JavaScript (por ejemplo, en href="javascript:alert('Test')" ) está bloqueada en el entorno limitado de la aplicación. No se emite ningún error.