2006年 11月 03日

Creammonkey いぢりで Cocoa Webkit をまなぶ

--- /Volumes/Creammonkey/Source/CMController.m	2006-07-05 23:28:50.000000000 +0900
+++ CMController.m	2006-11-03 02:49:19.000000000 +0900
@@ -8,6 +8,13 @@
 #import "CMUserScript.h"
 
 @implementation CMController
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
+- (NSString*) helloHackWebkit:(NSString*) arg
+{
+	return [@"Hello" stringByAppendingString: arg];
+}
+
+
 - (NSArray*) scripts
 {
 	return scripts_;
@@ -233,12 +240,18 @@
 		[webView stringByEvaluatingJavaScriptFromString: @"document.body.__creammonkeyed__ = true;"];
     }
 	
+	if (isDebug) [self reloadUserScripts: nil];
+		
+	WebScriptObject* scriptObject= [webView windowScriptObject];
+	[scriptObject setValue:self forKey:@"__creammonkey_obj"];
+	
     // Eval!
 	NSArray* ary = [self matchedScripts: url];
 	int i;
 	for (i = 0; i < [ary count]; i++) {
         [webView stringByEvaluatingJavaScriptFromString: [ary objectAtIndex: i]];
 	}
+	[scriptObject setValue:nil forKey:@"__creammonkey_obj"];
 }
 
 #pragma mark Action
@@ -252,6 +265,13 @@
     [self saveScriptsConfig];
 }
 
+- (IBAction) toggleDebug: (id) sender
+{
+	isDebug = !isDebug;
+	[sender setState: isDebug ? NSOnState : NSOffState];
+
+}
+
 - (IBAction) uninstallSelected: (id) sender
 {
 	CMUserScript* script = [[scriptsController selectedObjects] objectAtIndex: 0];
@@ -305,6 +325,8 @@
 	scripts_ = nil;    
     targetPages_ = [[NSMutableSet alloc] init];
 	
+	isDebug = FALSE;
+	
 	[NSBundle loadNibNamed: @"Menu.nib" owner: self];
 	
 	return self;

Objctive-C 側のメソッドを JS 側からよんでみる。うえのように書き換えた上で

alert(__creammonkey_obj.helloHackWebkit_("test"));

とかやると Hello test が alert される。

GM_xmlhttprequest を作りたくてどうやるか調べ途中。うえの書き換えだと、eval 後に使ったやつは nil をセットしているけど、これでちゃんと消えてくれるのか (サイト側からそれにアクセスできないのか) が気になる。試せよって感じだけど……

あと上のはファイル分けたりするのがめんどうくさいから self を渡しているけど、専用のクラス/インスタンスを作ってそれを渡すべき。例えば __creammonkey_obj.orderFrontAboutPanel_() とかやると確実に落ちる。

Objctive-C と JS とのデータのやりとりはてきとうにやってくれるっぽい。デフォルトのメソッド名変換は Ruby/Cocoa の正式名と同じ感じ。