株式会社クリアコード > ククログ

ククログ


Firefoxの独自ビルドにおける、より高度なノーブランド化の手順

概要

Firefoxの独自ビルドの作成手順(2015年版)において、「Firefox」ブランドを使用しない「ノーブランド版Firefox」の作成方法を解説しました。 この記事ではその補足情報として、より完全なノーブランド化の手順と、その際の注意点を解説します。

ノーブランド化の必要性

まず最初におさらいとして、何故ノーブランド化の必要があるのか(どのような場合にノーブランド化しなくてはならないのか)を改めて説明します。

Mozilla FirefoxのソースコードはMPL2.0というフリーソフトウェアライセンスの元で公開されているため、誰でも利用や再配布が可能となっています。 しかし、「Firefox」という名前についてはMozilla Corporationが商標としての権利を保有しており、Mozilla自身が「これをFirefoxと呼ぶ」とお墨付きを与えたバイナリ以外の物に「Firefox」の名前を付けて頒布することはできません。

そのため、何らかの設定を変更したりアドオンを同梱したり、あるいは改造したりした物を第三者に対して頒布したい場合には、「Firefox」という商標を使用しない別の名前を付ける必要があります。 これが「ノーブランド化」です。

ノーブランド化には2つの段階があります。 先の記事で紹介した「見た目の名前の変更」と、この記事で新たに紹介する「アプリケーションの内部名まで含めた変更」です。

  • 「見た目の名前の変更」は、簡単に行えるのが利点ですが、Mozilla公式のFirefoxと併用する場合には様々な注意が必要となります。 企業内での標準ブラウザとしての使用のように、実行環境を管理者が100%決め打ちできる場合にはこの方法で十分な場合が多いと考えられます。
  • 「内部名まで含めた変更」は、コードの編集時に細心の注意が必要となりますが、公式のFirefoxとの併用時も含めて実際の利用時の注意はほとんど必要ないという利点があります。 広く一般向けに頒布する場合など、どのような環境で実行されるのかが事前に分からない場合にはこの方法の方が安全と考えられます。

この記事で、それぞれを順番に解説します。

「名前を変える」の具体的な方法

先の記事で解説している通り、「ノーブランド化」とは実際の所は「ソースコードの書き換え」です。 とはいえ、必要なファイルすべてをテキストエディタで開いて編集して……という事を繰り返していて手間がかかりすぎます。 可能な限り作業を自動化するために、「変更が必要なファイルをgrepで検索し、sedで内容を書き換える」という方法をとるのがお薦めです。

Mozilla Buildでこれを行う時には、2つの点に気をつける必要があります。

  • Mozilla BuildはMinGWを使ったUnix風のコンソールで操作を行いますが、MinGWに同梱されているsed-iオプションを使うと、ファイルのパーミッションが意図せず変更されてしまうという問題が起こります。 MinGW 上の sed による置換で permission denied を回避するにはで解説されている手順を参考に、あらかじめC:\mozilla-sourceおよびその配下のすべてのファイルについてUsersにフルコントロールの権限を与えておきましょう。
  • Gitではgit grepを使うことが多そうな場面ですが、Mercurialではhg grepとすると現在のリビジョンではなく履歴に対する検索となるため、リビジョンによっては検索漏れが出てしまいます。 なので、hg grepではなく通常のgrepの方を使いましょう。

見た目の名前を変える

まず、比較的手軽なノーブランド化手法柄である、見た目の名前の変更の方法です。 先の記事で解説しているのはこちらの方法ですが、復習も兼ねて改めて解説します。

ノーブランド化に際して、アプリケーションの長い名前(正式名)と短い名前(省略名)、ベンダ名とWebサイトのURLを以下の通り決めたと仮定します。

  • アプリケーションの長い名前(正式名):My Custom Browser
  • アプリケーションの短い名前(省略名):Browser
  • ベンダ名:My Company
  • ベンダのWebサイトのURL:http://mycompany.example.com/

様々な都合のため、短い名前には空白文字を含められません。 略語にする、頭字語にするなどして、空白文字を含まない十分に短い名前とするようにして下さい。

この時の一括置換の操作のコマンド列の例は、Bashスクリプトとして表すと以下のようになります。

base="/c/mozilla-source"
firefox_source="mozilla-esr38"
locale="ja"
name="My Custom Browser"
shortname="Browser"
vendorname="My Company"
vendorurl="http://mycompany.example.com/"

cd $base

grep -E -e "\b(Nightly|Firefox)\b|\"(Mozilla|mozilla\\.org|https?://((www|support)\\.mozilla\\.org|mozilla\\.jp)/?\"|(vendorShortName[^=]*=[^=]*)Mozilla" -r $locale/browser $locale/toolkit $firefox_source/browser/branding | \
  grep -v "Binary" | \
  cut -d ":" -f 1 | sort | uniq | \
  while read path; do sed -i -r -e "s/Mozilla Firefox/$name/g" \
                                -e "s/((MOZ_APP_DISPLAYNAME|Shorter).*)(Nightly|Firefox)/\1$shortname/g" \
                                -e "s/((Short|Full).*)(Nightly|Firefox)/\1$name/g" \
                                -e "s/\bFirefox\b/$shortname/g" \
                                -e "s/\bNightly\b/$name/g" \
                                -e "s/Mozilla $name/$name/g" \
                                -e "s/\"(Mozilla|mozilla\\.org)\"/\"$vendorname\"/g" \
                                -e "s;\"https?://((www|support)\\.mozilla\\.org|mozilla\\.jp)/?\";\"$vendorurl\";g" \
                                -e "s/(vendorShortName[^=]*=[^=]*)Mozilla/\1$vendorname/g" \
                        "$path"; done

「Mozilla Firefox」という長い名前や「Firefox」という短い名前が書かれている箇所の置換は容易ですが、「Nightly」と書かれている部分は、それが長い名前なのか短い名前なのかが場合によってまちまちです。 なので、ここでは確実に短い名前と断定できる部分(例えばMOZ_APP_DISPLAYNAMEbrandShorterNameの値など)は短い名前にして、それ以外は長い名前にしています。

上記コマンド列による一括置換の他に、about:rightsの補完アイコン等の画像の差し替えも場合に応じて行います。

  • 「about:rights」には、使用者自身の権利に関する情報、具体的にはプライバシーポリシーであったり、ノーブランド版のFirefoxと組み合わせて使用するWebサービスそのものの利用規約であったりが表示される事になっています。 この情報は初期状態ではプレースホルダ的な内容になっているため、自分で書き換える必要があります。

    about:rightsの内容を変えるには、toolkit/content/aboutRights-unbranded.xhtmlの位置にあるファイル(Firefox 38ESRでも同じ位置にあります)を直接書き換えるか、そこで参照しているエンティティを定義している言語リソースの項目を書き換えます。

  • 特定言語のビルドしか提供しないのであれば、aboutRights-unbranded.xhtmlだけを直接書き換えれば十分でしょう。 なお、文章に日本語などの非ASCII文字を含める場合は、ファイルの文字エンコーディングはUTF-8にする必要があります。

  • ブランドに関する画像はFirefox本体のリポジトリのbrowser/branding/nightly以下にある物が使われます。 独自のアイコンなどを使いたい場合は、これらの画像も差し替えておきます。

この方法でノーブランド化したビルドは、公式のFirefoxのバージョン(エディション)違いに相当する、言うなればリリース版Firefoxに対するベータ版やNightlyに相当する物となります。 実行時には自分で決めた名前で表示されますが、アプリケーションとしての内部名はFirefoxと同一なので、公式のFirefoxを同時にインストールしていると以下のような事が起こります。

  • Firefoxが動作している時にノーブランド版を起動しようとしても、ノーブランド版は起動せず、既に起動しているFirefoxで新しいタブが開かれるだけとなる。
    • その逆に、ノーブランド版が動作している時にFirefoxを起動しようとしても、公式のFirefoxは起動せず、既に起動しているノーブランド版で新しいタブが開かれるだけとなる。
  • ユーザープロファイルが公式のFirefoxと共用される。そのため、公式のFirefoxとノーブランド版のバージョンが一致していないと、お互いを起動する度に設定の移行処理が行われる(Firefoxをアップグレードまたはダウングレードしたのと同じ扱いになる)。

ですので、この状態のノーブランド版は以下のような制限を設けて運用する必要があります

  • ノーブランド版と公式のFirefoxを併用しない
  • ノーブランド版と公式のFirefoxを併用する場合は、ノーブランド版専用のプロファイルを使用する
    • ノーブランド版起動用のショートカットのリンク先には、"C:\Program Files (x86)\My Custom Browser\firefox.exe" --profile "%AppData%\MyCustomBrowser" -no-remoteという要領で、専用プロファイルのパスと-no-remoteオプションを明示する。
    • このショートカットからの多重起動(ウィンドウを見失った時などに、とりあえず起動用ショートカットをダブルクリックしたら、既に開かれていたウィンドウが最前面に出てくる、というような使い方)はできない。

アプリケーションの内部名を変える

上記のような制限事項は、表示名の変更によって作成されたノーブランド版が、内部的には公式のFirefoxのバージョン(エディション)違いに相当する物であるという事により生じています。

一方、OSに対して通知するプロセス名や実行ファイル名なども含めて、内部的なアプリケーション名を完全に変更すれば、このような制限がないノーブランド版を作る事ができます。 このようにして作成したノーブランド版は、Firefoxに対するThunderbirdやSeamonkeyのように、公式のFirefoxとは全く別のアプリケーションとして動作します。 そのため、公式のFirefoxとの併用時にも、色々な事に気をつける必要はありません。

とはいえ、Firefoxのソースコード中にある「Firefox」や「firefox」といった文字列を無差別に書き換えるのは得策ではありません。 文字列の置換は、PCの上で別アプリケーションとして動作させるために必要な部分に限定して行うのがお薦めです。 以下に、その対象を考える際の判断材料を列挙します。

  • Firefox 38ESRの場合、置換対象は以下のファイル群のみで十分です。
    • configure.in:ビルドの設定
    • browser/:ブラウザとしてのフロントエンドに関するコード
    • ipc/:プロセス分離に関するコード
  • Firefoxのリポジトリには上記以外にも「Thunderbirdなどと共通の基盤のコード」「Android版Firefox用のコード」「Firefox OS用のコード」なども含まれていますが、それらに手を加える必要はありません。
    • 共通の基盤のコードは、現在でも既にThunderbirdやSeamonkeyなどでそのまま使われています。 これはつまり、ノーブランド版を公式のFirefoxとは別アプリケーションとして動かす上でこれらの部分はそのまま使えるという事を意味します。
    • Android版やFirefox OS用のコードは、デスクトップアプリケーションであるノーブランド版Firefoxのビルドには関わってきませんので、無視して問題ありません。
  • 「アドオン用のアプリケーションID」(公式のFirefoxでは{ec8030f7-c20a-464f-9b0e-13a3a9e97384})は、変えない方が良いでしょう。 というのも、このIDはアドオンが対応アプリケーション(Firefox、Thunderbird、Seamonkeyなど)を識別するために使われるため、IDを変えてしまうと、既存のFirefox用アドオンが全く使えなくなってしまうからです。
  • 実行ファイル名のfirefox.exe以外の部分における小文字のfirefoxは、極力変更しない方が良いでしょう。 小文字のfirefoxはファイル名のパスに多用されているため、不用意に変更すると、あるはずのファイルが見つからないという問題が起こり得ます。
  • "Mozilla""Firefox""Mozilla Firefox"のように大文字小文字交じりのリテラルとして定義されている物は、置換しても安全である場合が多いです。 これらはソースコード中で定数として定義されている事が多いため、定義している箇所を書き換えれば他の部分もそれに自動的に追従する結果となります。
  • レジストリキーに関する項目も、置換しておくことで公式のFirefoxとの衝突の可能性が低減されます。

以上を踏まえた、Firefoxのソースコード中に埋め込まれた文字列を置換して内部名から別アプリケーション化するコマンド列の例をシェルスクリプト形式(※前項のスクリプトの続きとして読んで下さい)で示すと、以下のようになります。

shortname_lc=$(echo $shortname | tr A-Z a-z)

cd $base

grep -E -e "firefox\.exe|\"(Firefox|Mozilla|Mozilla Firefox)\"|(Software\\\\?)?Mozilla\\\\?(Firefox)?" -r $firefox_source/browser $firefox_source/build $firefox_source/config $firefox_source/configure.in $firefox_source/ipc | \
  grep -v "Binary" | \
  cut -d ":" -f 1 | sort | uniq | \
  grep -v "test" | \
  while read path; do sed -i -r -e "s/firefox\.exe/$shortname_lc.exe/g" \
                                -e "s/\"Firefox\"/\"$shortname\"/g" \
                                -e "s/\"Mozilla\"/\"$vendorname\"/g" \
                                -e "s/\"Mozilla Firefox\"/\"$name\"/g" \
                                -e "s/(Software\\\\?)?Mozilla(\\\\?)Firefox/\1$vendorname\2$shortname/g" \
                                -e "s/(Software\\\\?)Mozilla/\1$vendorname/g" \
                        "$path"; done

for shortname_file in "$firefox_source/browser/confvars.sh" \
                      "$firefox_source/browser/installer/windows/nsis/defines.nsi.in" \
                      "$firefox_source/browser/metro/metroapp.ini.in" \
                      "$firefox_source/ipc/app/plugin-container.exe.manifest"
do
  sed -i -r -e "s/Firefox/$shortname/g" \
            -e "s/=Mozilla$/=\"$vendorname\"/g" \
    "$shortname_file"
done

for shortname_lc_file in "$firefox_source/browser/app/macbuild/Contents/Info.plist.in" \
                         "$firefox_source/browser/app/macbuild/Contents/MacOS-files.in" \
                         "$firefox_source/browser/confvars.sh"
do
  sed -i -r -e "s/firefox/$shortname_lc/g" "$shortname_lc_file"
done

sed -r -e "s/>Firefox</>$shortname</g" \
       -e "s/Firefox/$name/g" \
  $firefox_source/browser/app/firefox.exe.manifest \
  > $firefox_source/browser/app/$shortname_lc.exe.manifest

sed -i -r -e "s/Firefox Launcher/$name Launcher/g" \
          -e "s/Firefox/$shortname/g" \
  $firefox_source/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.exe.manifest

これらの置換操作を行った結果のソースからビルドしたノーブランド版は、以下の挙動になる事を確認できています。

  • 公式のFirefoxと並行起動できる。
  • 既定のユーザープロファイルは %AppData%\ベンダ名\Profiles\アプリケーション名\xxxx.default に作成される。
  • その環境にインストール済みのFirefox用NPAPIプラグイン(Adobe Flash、Javaなど)をそのまま認識する。
    • HKEY_LOCAL_MACHINE\Software\Wow6432Node\MozillaPlugins経由での登録以外の方法で認識されるNPAPIプラグインについては個別の対応が必要。
  • Firefox用のアドオンをインストールできる。
  • レジストリキーが公式のFirefoxとは別に管理されており、FirefoxやThunderbirdのレジストリと混ざらない。
    • 各種の情報は HKEY_LOCAL_MACHINE\Software\Wow6432Node\ベンダ名 以下に保存される
  • 自動アップデートは行われない。
    • Mozilla公式のサーバにアップデート情報を問い合わるが、「そのような名前のアプリケーションのアップデート情報は存在しない」という結果になる。
    • 自動アップデートを行いたい場合、自分で自動アップデート用の情報を提供し、且つ、アップデート情報の問い合わせ先を自分のサーバに変更する必要がある。
  • Firefox Syncを使うと、各種データが公式のFirefoxと相互に同期される。

繰り返しになりますが、Bashスクリプトの形で示した上記の置換操作の例は、あくまでFirefox 38ESRのソースを対象にした物です。 他のバージョンのFirefoxを対象にする場合、置換のし残しが発生したり、置換してはいけない部分まで置換してしまったりして、そのままでは期待通りの結果を得られない可能性があります。 未知のバージョンを相手にする際は、前述の「判断材料」に基づいて慎重に置換対象を見極める必要がありますので、くれぐれも注意して下さい。

まとめ

内部的なアプリケーション名の変更まで含めた、Firefoxのより高度なノーブランド化の方法を解説しました。

Firefoxの動作に影響を与えるソースコードの書き換えは、失敗するとビルドや起動ができなくなってしまう事もあります。 そのような時は、Mercurialでアレを元に戻す108の方法 - TIM Labsなどを参考にして、変更を取り消してやり直すとよいでしょう。 筆者も、この記事を書くにあたってhg update -Cを多用しました。

ソースコードのスナップショットをダウンロードして使うのではなく、Mercurialのリポジトリをcloneして使う事には、こういう利点もあります。 バージョン管理システムを使った事がないという人も、これを機にGitやMercurialを試してみてはいかがでしょうか。

タグ: Mozilla
2015-10-26

«前の記事: Firefoxのメモリ消費の状況を定期的に監視する 最新記事 次の記事: WerckerのDockerベーススタックへの移行»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|