【コラム】

ダイナミックObjective-C

41 インプットマネージャから侵入

    木下誠  [2006/06/28]

    今回は、ハックの話をしよう。Objective-Cの動的な機構と、Cocoaアプリケーションの仕組みを利用する事で、簡単に強力なハックを行える。

    ポージングを使ったハッキング

    本連載の第12回で、Objective-Cのポージング機能を紹介した。新しく作ったクラスで、既存のクラスを「乗っ取る」ことができる仕組みだ。乗っ取りは、自分で作成したオブジェクトだけでなく、システムが作ったものに対しても行えるので、非常に強力である。過去の記事では、例として、アプリケーションで使うすべてのウィンドウを半透明化する方法を紹介した。

    だが、この機能を実際に使ってみると、すぐに次の疑問が浮かぶだろう。自分で作成したアプリケーションだけではなく、既にあるアプリケーションでもこの半透明化を行えないだろうか?

    これを実現するには、作成したポージングを行うクラスを、目的のアプリケーションランタイムに読み込ませる必要がある。クラスをランタイムに侵入させる事にさえ成功すれば、あとはこちらのもの。Objective-Cランタイムが動的に提供してくれる、豊富なクラス情報のおかげで、ハックし放題だ。

    果たして、このような侵入口はあるのか? 実は、ある。昔から良く知られている入り口がある。それは、インプットマネージャだ。

    インプットマネージャとは

    インプットマネージャは、我々日本人がコンピュータを扱うにあたって誰もが意識する、文字入力システムを管理するものだ。日本語や、その他の文字を入力するための、インプットサーバを作成し、それをアプリケーションから利用できるようにする。また、複数のインプットサーバを切り替える事もできる。

    だが実のところ、文字入力に関する事はどうでもいい。ハックという観点から見て、インプットマネージャの重要な特質は、次の点である。Cocoaのランタイムは、利用可能なインプットマネージャを調べるために、アプリケーションを起動する際、~/Library/InputManagersの下にあるバイナリを読み込む。この読み込みは、そのバイナリが文字入力に関係あろうが無かろうが、すべてのファイルに対して行われる。

    アプリケーションが自動的にクラスの読み込みを行うフォルダ。そう。ここが絶好の侵入口になっているのだ。

    インプットマネージャから侵入

    では、実際にここから読み込ませてみよう。2つのファイルを用意する必要がある。

    まず、アプリケーションに動的に読み込んでもらうバイナリ。これを、必要なリソースとともにパッケージした、バンドルというファイルタイプで用意する。そして、そのバンドルの情報を記したファイル。これは、Mac OS Xで使われている、プロパティリストフォーマットで記述する。

    今回はサンプルとして、第12回でも実験した、ウィンドウの半透明化をそのまま使おう。ウィンドウを表すNSWindowクラスのサブクラスを作り、ポージングをして元々のNSWindowを乗っ取るのだ。ソースコードは前回紹介したものを、そのまま利用する事にする。

    ただし、今回は最終的にバンドルの形に仕上げなくてはいけない。そこで、開発環境であるXcodeで「Cocoa Bundle」のプロジェクトを作成し、上記のソースコードを含めてビルドする。これで、アプリケーションに読み込ませる、侵入ファイルの出来上がりだ。

    次に、このバンドルの情報を記述したファイルを作成する。テキストエディタか、プロパティリストフォーマットを編集するProperty List Editorを使って、次のように書く。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>BundleName</key>
        <string>TransparentWindow.bundle</string>
        <key>LoadBundleOnLaunch</key>
        <string>YES</string>
        <key>NoMenuEntry</key>
        <string>YES</string>
    </dict>
    </plist>

    BundleNameに対する値のところに、作成したバンドルファイルの名前を指定する。ここでは、TransparentWindow.bundleという名前にしている。このファイルを、Infoという名前で保存する。よく使われる、Info.plistという名前とは違うので、注意して欲しい。

    この、バンドルファイルとInfoファイルを、1つのフォルダに入れる。そして、~/Libraryの下にある、InputManagersフォルダにコピーする。このフォルダがない場合は、自分で作成しよう。

    TransparentWindowのインストール

    これで完了だ。この状態でCocoaアプリケーションを起動すると、InputManagersの下にある、TransparentWindow.bundleを自身のランタイムに読み込む。このバンドルが含むTransparentWindowクラスは、NSWindowをポージングして、すべてのウィンドウを半透明にしてしまう。

    すべてのアプリケーションが半透明

    上の図のように、Safariも、QuickTime Playerも、iPhotoも、すべて半透明になる。Cocoaを利用しているアプリケーションならば、すべて半透明になる。もちろん、大変使いにくい。だが、ハックによって引き起こされた結果は強力に実感できるだろう。

    バンドルは、次のリンクからダウンロードできる。InputManagersフォルダにインストールすれば有効になり、取り出せば無効になる。取り扱いには、十分に注意してほしい。

    TransparentWindow.zip

    新着記事

    特設サイトの情報

      求人情報

      人気記事

      一覧

      イチオシ記事

      新着記事

      特別企画

      転職ノウハウ

      あなたの仕事適性診断

      4つの診断で、自分の適性を見つめなおそう!

      Heroes File ~挑戦者たち~

      働くこと・挑戦し続けることへの思いを綴ったインタビュー

      はじめての転職診断

      あなたにピッタリのアドバイスを読むことができます。

      転職Q&A

      転職に必要な情報が収集できます

      スカウト転職する

      企業からアプローチのメッセージが届きます。

      マイナビニュースマガジン