4

セットアップ

  • Mac OS X 10.8.2
  • OSが提供するバージョンのWebKitフレームワークに対してリンクする通常のCocoaアプリ。具体的には、次の内容です/System/Library/Frameworks/WebKit.framework/Versions/A/Resources/version.plist
    <plist version = "1.0">
    <dict>
        <key> BuildVersion </ key>
        <string> 5 </ string>
        <key> CFBundleShortVersionString </ key>
        <string> 8536 </ string>
        <key> CFBundleVersion </ key>
        <string> 8536.26.14 </ string>
        <key> ProjectName </ key>
        <string> WebKit </ string>
        <key> SourceVersion </ key>
        <string> 7536026014000000 </ string>
    </ dict>
    </ plist>

WebViewに通常のHTMLフォームを含むHTMLドキュメントをロードするWebKitベースのCocoaアプリがあります。HTMLフォームには、次のようなファイルチューザー入力フィールドが含まれています。

<form name="foo">
    <input type="file" name="bar">
</form>

このファイルチューザーの値をプログラムで設定したいのですが(可能であればObjective-Cからですが、うまくいくことは何でもします)。

私の知る限り、この方法は機能していません。

DOMHTMLInputElement *inputEl = ... // fetch input element
[inputEl setValue:@"some/file.txt"];

WebKitには、これが機能しないようにするセキュリティ制限/ポリシーがあると思います。これはWebKitの意図的なセキュリティ機能であり、バグではないと思います。


ただし、OS X 10.7 Lionでは、少しハックすることでこの制限を回避することができました。

Lionでは、プログラムで要素をクリックできます。input

#pragma mark -
#pragma mark WebFrameLoadDelegate

- (void)webView:(WebView *)wv didFinishLoadForFrame:(WebFrame *)frame {
    if (frame != [wv mainFrame]) return;

    DOMAbstractView *win = (id)[frame windowObject];
    DOMDocument *doc = [win document];
    DOMHTMLFormElement *formEl = (id)[[doc forms] namedItem:@"foo"];
    DOMHTMLInputElement *inputEl = (id)[[formEl elements] namedItem:@"bar"];
    [inputEl click];
}

これにより、への呼び出しが生成され-[WebUIDelegate webView:runOpenPanelForFileButtonWithResultListener:]ます。次に、そのデリゲートメソッドを実装して、結果リスナーの値をプログラムですぐに設定できます。

#pragma mark -
#pragma mark WebUIDelegate

- (void)webView:(WebView *)wv runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)listener {
    [listener chooseFilename:@"some/file.txt"];
}

これは醜いハックでしたが、完璧に機能しました。inputこれには、ファイルアップロード要素の値をすぐに設定するという望ましい効果がありました。「開いているパネル」は画面に表示されません。


10.8に同梱されていたバージョンでは、WebKitがこれを許可しなくなったのではないかと思います。変更された部分は次のとおりです。

[inputEl click];

これにより、10.8で出荷されるWebKitの要素でクリックイベントが生成されなくなりました。

10.7で機能した他のクリック方法を試しましたが、10.8では機能しなくなりました。

DOMUIEvent *evt = (id)[doc createEvent:@"UIEvents"];
[evt initUIEvent:@"click" canBubble:YES cancelable:YES view:win detail:1];
[inputEl dispatchEvent:evt];

これらのメソッドは10.7で機能しましたが、10.8では機能しません。


それで、10.8でこのファイルチューザーの値をプログラムで設定する方法はありますか?

:アプリにカスタムバージョンのWebKitを同梱したくありません。それ以外は、どんな提案(ObjCやJSなど)でも構いません。

10.8に同梱されているWebKitのファイルチューザーの値をプログラムで設定するにはどうすればよいですか?

ここにあなたの便宜のために利用可能なサンプルテストプロジェクト(縮小されたテストケース)があります:http://tod.nu/FileUploadTest.zip

4

1 に答える 1

7

これは、AppKit イベント システムを介してイベントをディスパッチする場合に機能します。何かのようなもの:

NSView *docView = [[[webView mainFrame] frameView] documentView];
NSRect docFrame = [docView frame];

NSPoint point = [el boundingBox].origin;
point.y = docFrame.size.height - point.y;

NSEvent *evt = [NSEvent mouseEventWithType:NSLeftMouseDown location:point modifierFlags:0 timestamp:[[NSDate date] timeIntervalSinceReferenceDate] windowNumber:[self.webView.window windowNumber] context:0 eventNumber:0 clickCount:1 pressure:0];
[self.webView.window sendEvent:evt];

evt = [NSEvent mouseEventWithType:NSLeftMouseUp location:point modifierFlags:0 timestamp:[[NSDate date] timeIntervalSinceReferenceDate] windowNumber:[self.webView.window windowNumber] context:0 eventNumber:0 clickCount:1 pressure:0];
[self.webView.window sendEvent:evt];

座標系の変換を行うためのより良い方法がおそらくありますが、それは実際には重要な部分ではありません。

于 2013-01-18T21:02:04.440 に答える