セキュリティ関連の JavaScript エラーの回避

Adobe AIR 1.0 およびそれ以降

セキュリティ制限により、サンドボックスで使用が制限されているコードを呼び出すと、ランタイムは JavaScript エラー「Adobe AIR security violation for JavaScript code in the application security sandbox.」を送出します。このエラーを回避するには、ここで説明するコーディングの手法を参考にしてください。

セキュリティ関連の JavaScript エラーの原因

アプリケーションサンドボックスで実行するコードでは、ドキュメントの load イベントが開始し、任意の load イベントハンドラーが終了すると、ストリングの評価および実行を伴うほとんどの操作が制限されます。潜在的に安全でないストリングを評価および実行する次のタイプの JavaScript ステートメントの使用を試みると、JavaScript エラーが発生します。

異なるサンドボックスへのアプリケーションコンテンツのマッピング

ほとんどの場合、アプリケーションを書き直したり再構築したりすることで、セキュリティ関連の JavaScript エラーを回避できます。しかし、書き直しまたは再構築時ができない場合には、 アプリケーションコンテンツの非アプリケーションサンドボックスへの読み込み で説明する方法で、アプリケーションコンテンツを別のサンドボックスに読み込めます。該当のコンテンツからも AIR API にアクセスする必要がある場合、 サンドボックスブリッジインターフェイスの設定 で説明するようにして、サンドボックスブリッジを作成できます。

eval() 関数

アプリケーションサンドボックスでは、 eval() 関数は、ページの load イベントの前または load イベントハンドラー実行中にのみ使用できます。ページが読み込まれた後、 eval() を呼び出してもコードは実行されません。しかし、次の場合は、コードを書き直すことで eval() の使用を避けることができます。

プロパティのオブジェクトへの割り当て

ストリングを解析してプロパティアクセサを構築する次のようなコードにしないでください。

eval("obj." + propName + " = " + val);

次のように角括弧表記でプロパティにアクセスします。

obj[propName] = val;

コンテキストで使用可能な変数を持つ関数の作成

次のようなステートメントは、

function compile(var1, var2){ 
    eval("var fn = function(){ this."+var1+"(var2) }"); 
    return fn; 
}

次のように置き換えます。

function compile(var1, var2){ 
    var self = this; 
    return function(){ self[var1](var2) }; 
}

クラス名をストリングのパラメーターとして使用するオブジェクトの作成

次のコードで定義する仮定の JavaScript クラスを考えます。

var CustomClass =  
    { 
        Utils: 
        { 
            Parser: function(){ alert('constructor') } 
        }, 
        Data:  
        { 
         
        } 
    }; 
var constructorClassName = "CustomClass.Utils.Parser";

インスタンスを最も簡単に作成するには、次のように eval() を使用します。

var myObj; 
eval('myObj=new ' + constructorClassName +'()')

しかし、クラス名の各コンポーネントを解析し、角括弧表記を使用して新規のオブジェクトを作成すれば、 eval() の呼び出しを避けることができます。

function getter(str) 
{ 
    var obj = window; 
    var names = str.split('.'); 
    for(var i=0;i<names.length;i++){ 
        if(typeof obj[names[i]]=='undefined'){ 
            var undefstring = names[0]; 
            for(var j=1;j<=i;j++) 
                undefstring+="."+names[j]; 
            throw new Error(undefstring+" is undefined"); 
        } 
        obj = obj[names[i]]; 
    } 
    return obj; 
}

インスタンスを作成するには、次のようにします。

try{ 
    var Parser = getter(constructorClassName); 
    var a = new Parser(); 
    }catch(e){ 
        alert(e); 
}

setTimeout() および setInterval()

関数参照またはオブジェクトと共にハンドラー関数として渡されるストリングを置き換えます。次に例を示します。

setTimeout("alert('Timeout')", 100);

次のように置き換えます。

setTimeout(function(){alert('Timeout')}, 100); 

または、関数に必要な this オブジェクトが呼び出し元によって設定される場合に、次のようなステートメントを

this.appTimer = setInterval("obj.customFunction();", 100);

次のステートメントに置き換えます。

var _self = this; 
this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100);

Function コンストラクター

new Function(param, body) の呼び出しは、インライン関数宣言に置き換えるか、ページの load イベントの処理が完了する前にのみ使用します。

javascript: URL

javascript: URL スキームを使用してリンクに定義されるコードは、アプリケーションサンドボックス内では無視されます。安全でない JavaScript エラーは生成されません。javascript: URL を使用するリンクを置き換えることができます。次に例を示します。

<a href="javascript:code()">Click Me</a>

次のように置き換えます。

<a href="#" onclick="code()">Click Me</a>

innerHTML および outerHTML ステートメントの onevent 属性によって割り当てられるイベントコールバック

innerHTML または outerHTML を使用してドキュメントの DOM にエレメントを追加するとき、 onclick または onmouseover などのステートメント内で割り当てられたイベントコールバックは無視されます。セキュリティエラーは生成されません。代わりに、 id 属性を新しいエレメントに割り当て、 addEventListener() メソッドを使用してイベントハンドラーコールバック関数を設定できます。

例えば、次のようなドキュメントのターゲットエレメントがあるとします。

<div id="container"></div>

次のようなステートメントを置き換えます。

document.getElementById('container').innerHTML =  
    '<a href="#" onclick="code()">Click Me.</a>';

次のように置き換えます。

document.getElementById('container').innerHTML = '<a href="#" id="smith">Click Me.</a>'; 
document.getElementById('smith').addEventListener("click", function() { code(); });

アプリケーションインストールディレクトリの外部からの JavaScript ファイルの読み込み

アプリケーションサンドボックス外部からのスクリプトファイルの読み込みは許可されていません。セキュリティエラーは生成されません。アプリケーションサンドボックス内で実行されるすべてのスクリプトファイルがアプリケーションディレクトリにインストールされている必要があります。ページ内で外部スクリプトを使用するには、ページを別のサンドボックスにマップする必要があります。 アプリケーションコンテンツの非アプリケーションサンドボックスへの読み込み を参照してください。

document.write() および document.writeln()

document.write() または document.writeln() の呼び出しは、ページの load イベントの処理が完了した後は無視されます。セキュリティエラーは生成されません。代わりに、新しいファイルを読み込むか、DOM 操作のテクニックを使用してドキュメントの body を置き換えることができます。

load イベントの前または load イベントハンドラー実行中に同期する XMLHttpRequests

ページの load イベントまたは load イベントハンドラー実行中に開始された同期の XMLHttpRequests はコンテンツを返しません。非同期の XMLHttpRequests を開始することはできますが、 load イベントの後まで制御が戻りません。 load イベントの処理が完了した後は、同期の XMLHttpRequests は正常に動作します。

動的に作成されるスクリプトエレメント

innerHTML や document.createElement() メソッドなどで動的に作成されたスクリプトエレメントは無視されます。