ページ

2009年10月19日月曜日

Safari用独自プラグインを作る(5) - class-dump

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Safari用独自プラグインを作る(4) - Method Swizzling を試す

前回まででメソッドの置換(交換)方法がわかった。さて、ここまでは良かったがこれからどうすれば良いのだろうか。はたと困ってしまった。

ここで一度プラグインの動作イメージを確認してみることにした。

動作イメージとしては、 (1)何らかの方法によってユーザからの指示を受け付けて (2)表示中のWebページのキャプチャを実行,画像をファイルへ保存する、ということがやりたい。(3)またプリファレンスを用意する必要があるかもしれない。

整理するとこんな機能が必要。

(1) ユーザインタラクション(入力)
(2) キャプチャ(出力)
(3) プリファレンス(設定)


(1)は、メインメニューやツールバーボタン、コンテキストメニューなどが考えられる。Safari へ新規にメニューを追加することは比較的容易にできそうだが、ツールバーボタンはちょっとわからない。それ以外に独自の U/I を追加することも考えられる(ビュー上にボタンを表示してしまうとか)。

(2)は、キャプチャ処理自体は過去にさんざんやってきたので問題ない。ただどうやって表示中の WebViewなどを手に入れるか、それが課題。

(3)は、最悪無くてもかまわない。必要になったら考えよう。


上記を念頭におきつつ、メソッド置換を行う対象のクラスとメソッドを決める必要がある。
そこで Safariのクラスを調べることにした。

クラスの定義を知るには class-dump という便利なコマンドラインツールが使える。このツールを使うと指定したアプリケーションの中で使われているクラスのヘッダファイル(*.h)を生成することができる。

Code the Code - Projects - class-dump

(参考)木下さんの紹介記事
【コラム】ダイナミックObjective-C (1) CocoaとObjective-Cと動的なオブジェクト指向 - Cocoaハックの第1歩 | エンタープライズ | マイコミジャーナル


SIMBL向けのプラグインのソースを見るとたいてい Safari.h というファイルがXCodeプロジェクトに含まれているが、恐らく class-dump(もしくは同等のツール)を使って生成したものと思われる


class-dump を使い、Safariのヘッダファイルを作ってみよう。


まずダウンロードしてきて適当なフォルダへコピーする。ターミナル.appで動作確認。

$ ./class-dump 
class-dump 3.3.1 (32 bit)
Usage: class-dump [options] <mach-o-file>

  where options are:
        -a             show instance variable offsets
        -A             show implementation addresses
        --arch <arch>  choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64)
        -C <regex>     only display classes matching regular expression
        -f <str>       find string in method name
        -H             generate header files in current directory, or directory specified with -o
        -I             sort classes, categories, and protocols by inheritance (overrides -s)
        -o <dir>       output directory used for -H
        -r             recursively expand frameworks and fixed VM shared libraries
        -s             sort classes and categories by name
        -S             sort methods by name
        -t             suppress header in output, for testing
        --list-arches  list the arches in the file, then exit
$


Safariをターゲットにして実行してみる。

(実行環境)Mac OS X 10.5.8 (PowerPC G4) / Safari 4.0.3

./class-dump /Applications/Safari.app/Contents/MacOS/Safari  > Safari.h

生成された Safari.h はこんな感じ。

Safari.h
/*
 *     Generated by class-dump 3.3.1 (32 bit).
 *
 *     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2009 by Steve Nygard.
 */

#pragma mark Named Structures

struct AlignedBuffer<128ul, 4ul> {
    char buffer[128];
};

struct BlackButtonLayer;

struct Bookmark {
    void **_field1;
    int _field2;
     :
     :
     :
struct CGRect {
    struct CGPoint _field1;
    struct CGSize _field2;
};

struct CGSize {
    float _field1;
    float _field2;
};
     :
     :
@interface BarBackground : NSView
{
    BOOL _hasTopBorder;
    BOOL _hasBottomBorder;
    BOOL _mouseDownCanMoveWindow;
    BOOL _scopeBarAppearance;
    NSColor *_backgroundColor;
    NSColor *_tintColor;
    NSColor *_bottomBorderColor;
    NSView *_firstChildKeyView;
     :
     :

最初に構造体の定義があり、@protocol, @interface と定義が続く。AppKit や Foudation.framework など Safari固有でない定義も全部書き出されている。

試しに -H オプションをつけてみた。
./class-dump -H -o headers /Applications/Safari.app/Contents/MacOS/Safari

headers/ フォルダの下に定義毎に分解されたヘッダファイルが生成される。

$ ls headers
ABAddressBook-BrowserExtras.h
ABHomePagesController.h
ABPerson-BrowserExtras.h
AcceptedCookies.h
AcceptedDatabases-FileInternal.h
AcceptedDatabases.h
AcceptedServices.h
AccessibilityButtonInfo.h
AccessibilityChildInfo.h
   :
WebFrame-HistoryTextCache.h
WebHTMLRepresentation-CreditCardAutoFillExtras.h
WebIconMenuItem-FileInternal.h
WebIconMenuItem.h
WebSearchField-FileInternal.h
WebSearchField.h
WebSearchFieldCell.h
WebSecurityOrigin-SafariExtras.h
WebStringTruncator-BrowserExtras.h
WebView-SafariSnapshotGeneration.h
WebViewPlus-FileInternal.h
WebViewPlus.h
Window.h
WindowController.h
WindowDelegate-Protocol.h
WindowReopener.h

全部で 452ファイルが作られていた。
実際に使う場合はこれらの中から必要なものだけチョイスするという感じだろうか。

とりあえずこれらを眺めてみることにする。

(続く)