飴屋

WPF/日記10

テキストの入力を受け付ける

GridやStackPanelといったレイアウト要素を使ってユーザインターフェイスがそれっぽく見えるようになりましたので、続いてユーザの入力を受け付ける方を進めてみたいと思います。前回も既に、ラジオボタンのチェックに応じてテキストの色を変えるような動作をつけてみましたが、選択色はcurrentColorというメンバ変数に保持するように変更を加えました。

private String currentColor = "Black";
private void ChangeColor(object sender, RoutedEventArgs e)
{
Input.Foreground = ((RadioButton)sender).Foreground;
currentColor = Input.Foreground.ToString();
}

そして、TextBoxのキー入力に対してイベントを発生させることにしました。

<TextBox x:Name="Input" Padding="4" KeyDown="EnterInput"></TextBox>

TextBoxは単一行の入力を受け付けるようにして、Enterキーが押されたら、メッセージをサーバに送信することにしました。

private void EnterInput(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
string message = Input.Text;
//ここにサーバへの送信処理を書く
//message + currentColor + 自分のID
Input.SelectAll();
}
}

これでEnterキーの入力後、TextBoxの中身と現在の選択色を一緒にチャットサーバに送り、TextBoxの方は続けて入力できるように、現在の入力内容が全部選択されている状態になります。・・・肝心の送信処理については、次に書いていくことにします。

リモートアクセス

ここで一度、私は調べても調べても解決策が見当たらないという状態にはまります。要するに、チャットサーバにクエリを投げて、最新のメッセージ一覧を取得するという筋書きを書いていたのですが、まず、クエリの投げ方がわからなかったのでした。適切なURIをリクエストすれば事足りると思っていたのですが、XMLDocumentオブジェクトやURIオブジェクトを作成する段階でよくわからないエラーが発生するのです。エラーログにはチラホラと「...Security...」なんて単語が散見されるので大体察しはついたのですが、具体的な解決策が見当たりませんでした。WPFは現段階では(2008/5)比較的若い技術なのでそもそも参考になる記述がみつけにくいのですが、問題がXBAPがらみとなるとその難度は飛躍的に上昇するようです。XBAPよりもSilverlightの方がむしろ今ホットなので、よく取り上げられているのかもしれません。国内外のサイトのフォーラムを長時間眺めて、やっと自分なりの答えがみつかりました。

部分信頼(Partial Trust)

このプロジェクトを立ち上げる前にXBAPのことを調べていると、よく「部分信頼」という言葉を耳にしました。正直初めて聞く単語だったので、また変な機械翻訳かと思っていたのですが、そんなことはありませんでした。インターネットでのセキュリティ意識は年々高まっているのはわかっていましたが、こんな単語が生まれるまでに成熟をみせていたとは、不勉強でした。
クロスサイトスクリプティングやフィッシングサイトといった手法で、不正にユーザの情報を略取することが昨今多くなってきましたが、ブラウザのバージョンアップに伴って、それらのうちのいくつかは非常にやり辛い環境が整ってきたと思います。これらのノウハウは、もちろん新しい技術が生まれるときには最初から盛り込まれていてしかるべき、ということでWEBベースのアプリケーションには、いくつかセキュリティの要請から制限が加えられることになりました。私がこの制限に初めて直面したのが、まだJavaのアプレットとか作ってた時代だったでしょうか。フリーウェアを配布してローカルのファイルを操作できて当たり前だと思っていた自分は、Javaのアプレットでは(一部の例外を除いては)それができないという事実にすごく戸惑ったものでした。
ですが、そんなことは当然なのです。当時はまだ電話回線でネットにつないでいましたから、変なサイトにアクセスしたらいつの間にかダイアルQ2に電話をかけられて、身に覚えのない電話代を請求されるなんて事件が普通に発生していました。WEBアプリに自由を与え過ぎると、何も知らずに訪問したユーザが何をされるかわからないという状況が生まれます。
しかし、ユーザの安全とひきかえにWEBアプリはその利便性を失いました。ほとんど画面を装飾するためだけの使い方が多かったように思います。その流れを汲むのがFlashだったのかもしれませんね。WPFの真ん中の「P」にもその系譜がみてとれる気がします。
便利なアプリはVectorとか窓の杜から「ダウンロード」して、「インストール」するというのが、セオリーになっていました。この手順を踏むか踏まないかで、ローカルファイルへのアクセス権限があったりなかったりするというのですから、プログラマとしては腑に落ちないという方もいらしたかもしれません。
ただ、「ダウンロード」と「インストール」という一連の手続きの中で、ユーザの合意が形成されているというのが法律的には十分意義があるのだと思います。これだけ、手続き踏んだのだから、このプログラムはユーザから相当信頼されていると推定できます。これが「完全信頼(Full Trust)」のはしりなんじゃないかな、というのが私の見解です。
これに対して、WEBアプリなんていうお手軽なやつは「部分的にしか信頼できない」ということで、WPFではXBAPに予め制限事項を設けたのでしょう。

リモートアクセス制限

ローカルファイルへのアクセスができないのは当然として、自分以外の他所のサイトへのアクセスも何が起こるかわからないということで、リモートアクセスにも制限がついていました。このサイトのドメイン「soft.candychip.net」にXBAPファイルを置いた場合、アクセスできるファイルも「soft.candychip.net」上に存在しなければいけません。ただ、適切なプロキシを用意することでこの問題は回避できると思います。(プロキシによるサーバへの負荷は検討の余地があるかもしれませんが。)

リモートファイルの取得

.NETのバージョンが3.5になって、XBAPからのリモートアクセスにはWCFという選択肢が増えたらしいです。ただ、WCFの方に話を広げるつもりはないので、ここでは取り上げません。(というか、よく知りませんから話の広げようがありませんでした。)

とりあえず、前段階としてチャットサーバにアクセスしたときに返ってくる「最新のメッセージ一覧」レスポンスをXML形式のファイルとして準備してみました。

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ChatActions xmlns="">
<Speech>
<Speaker>myavatar</Speaker>
<Color>#ffff0000</Color>
<Content>こんにちは、世界!</Content>
<DateTime>2008-05-02 16:00:00</DateTime>
</Speech>
</ChatActions>

一つのメッセージ(Speech)に話者(Speaker)と声色(Color)と内容(Content)と発話時間(DateTime)を含めてみました。これは受け取ったメッセージを元にチャットサーバが成形して吐き出すという予定ですが、チャットサーバができていないのでこの静的ファイルでとりあえずよしとします。DateTimeなんかはサーバ側で記録する部分になると思います。ちなみにチャットサーバ自体はWPFとは関連しないので、特にここで詳細を綴るつもりはありません。

XBAPは部分信頼で動いているので、アクセスできるリモートホストは限られています。

Uri uri = new Uri("http://soft.candychip.net/test.xml");

なんて感じでURIを書いてもダメなようです。じゃあ、どうするのかと散々探し回ってでた結論は以下のような感じでした。

using System.Windows.Resources;
using System.IO;

Uri sourceuri = new Uri("pack://siteoforigin:,,,/xml/test.xml");
StreamResourceInfo info = Application.GetRemoteStream(sourceuri);
StreamReader reader = new StreamReader(info.Stream);
MessageBox.Show(reader.ReadToEnd());

こうしてやることで、ローカルでのデバッグでも、WEBサーバへアップロードした後もちゃんとメッセージボックスにファイルの内容が表示されるようになりました。

セキュリティの設定

これらのリモートアクセスについて調べている中で発見したことがいくつかあります。まずは、ソリューションエクスプローラ上からプロジェクトを右クリックして「プロパティ」を選択します。そこで、プロパティ一覧中の「セキュリティ」タブを選択しますと、部分信頼に関する設定ができるようなのです。ただし、XBAPの権限を越えるような設定にしても直ちに制限が消えるわけではないのでしょう。暇なときにでも設定をいじってみて、何がどうなるのか試してみてもいいかもしれません。この画面中の「詳細設定」ボタンを押すとアプリケーションのデバッグ時の挙動に関する設定ができるようなので、多分設定するのがいいのだと思います。(自分は設定したら何がどうなったのか、まだ把握できていませんが。)

あとはリモートアクセスに絡めて、WPFアプリケーションのデータファイルの分類について参考になったサイトがあったので、掲載しておきます。

http://msdn.microsoft.com/ja-jp/library/aa970494(VS.80).aspx

WPFを始めた当初はこんなことは考えずに何となくSolidBrushに画像リソースを読み込んでいましたが、「リソースファイル」、「コンテンツファイル」、「起点サイトファイル」と分類してみるとなんだか頭がすっきりしました。今回のXMLの読み込みは「起点サイトファイル」として読み込んだということになります。多分。「pack:」や「siteoforigin」という単語にめぐり合うのにすごい苦労したのが思い出されました。欲しい情報がすぐ引き出せる日本語の文献が欲しいなぁ、と切に思いました。

WPF

Last-Modified