X-0012 XPIパッケージでユーザープロファイル毎にインストールする

PROFILE_CHROMEフラグの使い方

チュートリアルなどの資料では、 install.js 中でファイルをインストールする場合は registerChrome(SKIN, ...); のように CONTENT, LOCALE, SKIN の各フラグを指定するということになっています。が、これらのフラグを指定しただけだと、ユーザー別のインストールはできません。マルチユーザーの OS などでは、管理者権限が必要になります。

現在のユーザープロファイルに対しファイルをインストールするには、 registerChrome(SKIN | PROFILE_CHROME, ...); のように PROFILE_CHROME フラグを付け加えれば OK です。

最も単純な例は、以下のようなものです。ここでは getFolder() 関数でユーザープロファイルのディレクトリを取得し、そこにファイルをコピーした後、インストールを行っています。

var err     = initInstall('hogehoge', 'hogehoge', '1.0'),
    UChrome = getFolder('Current User', 'chrome');

setPackageFolder(UChrome);

addFile('gashu.org', 'hogehoge.jar', UChrome, '');
registerChrome(SKIN | PROFILE_CHROME, getFolder(UChrome, 'hogehoge.jar'), '');

if (err == SUCCESS) performInstall(); else cancelInstall(err);

これで、 InstallTriger.installChrome() でスキンなどをインストールするのと同じ結果になります。

PROFILE_CHROMEフラグとDELAYED_CHROMEフラグは同時に指定してはいけません。同時に指定するとファイルの登録が行われなくなってしまいます。この二つは互いに排他的に使う必要があります。

注意点

Mozilla 1.3 およびそれ以前のバージョン(含むNetscape 7.0 )では、ファイルのコピー・登録はできるものの overlayinfo が認識されないという大きな問題があります。古いmozilla用のインストールスクリプトでは、スキンや独自の XUL アプリケーションなど overlayinfo を利用する必要がないパッケージの場合にのみ、PROFILE_CHROMEを使うようにしましょう。

参考:デフォルトの設定ファイルの置き場所

通常、prefs.jsに記憶するタイプの設定は、デフォルトの値を以下の書式で定義し、Mozillaをインストールしたフォルダのdefaultsフォルダ内・prefフォルダにmy_app.jsのような名前で置いておくことで、自動認識させることが出来ます。

pref("my_app.global.count", 0);
pref("my_app.func1.enable", true);
pref("my_app.func2.enable", true);
pref("my_app.dir",          "c:\\temp\\");

ただしこのフォルダには、管理者権限がないとファイルをインストールできません。ユーザー権限でインストーラを実行する場合、他のファイルはプロファイルディレクトリにインストールすればOKですが、このデフォルトの設定ファイルだけはインストールできないことになってしまいます。

デフォルトの設定ファイルをユーザー権限でのインストール内容に含める場合、デフォルトの設定ファイルもプロファイルディレクトリ内に置き、以下の要領で自力で内容を読み込む必要があると思われます。

function loadDefaultPrefs() 
{
  // インストールしたデフォルトの設定ファイルの位置を得る
  // ユーザープロファイルディレクトリのchromeディレクトリにあるものと仮定
  const DIR = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties);
  var dir = DIR.get('UChrm', Components.interfaces.nsILocalFile);

  var tempLocalFile = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
  tempLocalFile.initWithPath(dir.path);

  var uri;
  const IOService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
  try {
    uri = IOService.newFileURI(tempLocalFile).spec;
  }
  catch(e) { // [[interchangeability for Mozilla 1.1]]
    uri = IOService.getURLSpecFromFile(tempLocalFile);
  }

  if (!uri.match(/\/$/)) uri += '/';
  uri += 'my_app.js';


  // ファイルの内容をテキスト(UTF-16)として読み込む
  try {
    var fileHandler = IOService.getProtocolHandler('file').QueryInterface(Components.interfaces.nsIFileProtocolHandler);
    tempLocalFile = fileHandler.getFileFromURLSpec(uri);
  }
  catch(e) { // [[interchangeability for Mozilla 1.1]]
    try {
      tempLocalFile = IOService.getFileFromURLSpec(uri);
    }
    catch(ex) { // [[interchangeability for Mozilla 1.0.x]]
      tempLocalFile = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
      IOService.initFileFromURLSpec(tempLocalFile, uri);
    }
  }
  if (!tempLocalFile.exists()) return;

  var defPref = '';
  var stream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
  try {
    stream.init(tempLocalFile, 1, 0, false); // open as "read only"

    var scriptableStream = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);
    scriptableStream.init(stream);

    var fileSize = scriptableStream.available();
    var fileContents = scriptableStream.read(fileSize);

    scriptableStream.close();
    stream.close();

    defPref = fileContents;
  }
  catch(e) {
    return;
  }


  // 設定ファイルの内容を解釈するための関数を用意する
  const DEFPREF = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefService).getDefaultBranch(null);
  function pref(aPrefstring, aValue) {
    switch (typeof aValue)
    {
      case 'string':
        var nsISupportsString = ('nsISupportsWString' in Components.interfaces) ? Components.interfaces.nsISupportsWString : Components.interfaces.nsISupportsString;
        var string = ('@mozilla.org/supports-wstring;1' in Components.classes) ?
            Components.classes['@mozilla.org/supports-wstring;1'].createInstance(nsISupportsString) :
            Components.classes['@mozilla.org/supports-string;1'].createInstance(nsISupportsString);
        string.data = aValue ;
        DEFPREF.setComplexValue(aPrefstring, nsISupportsString, string);
        break;
      case 'number':
        DEFPREF.setIntPref(aPrefstring, parseInt(aValue));
        break;
      default:
        DEFPREF.setBoolPref(aPrefstring, aValue);
        break;
    }
  }


  // 内容を解釈する
  eval(defPref);
}