概要
今回はSchemeHandlerについて書きます。
webアプリを組み込んだネイティブアプリでwebからネイティブに何かを通知する方法は複数ありますが、最も一般的だと思われるのがカスタムURLスキームを利用する方法です。
CefにもカスタムURLスキームを利用してブラウザから通知を受ける仕組みが提供されています。
カスタムURLスキームについて
hoge://fugafuga
みたいなやつです。
スマホのブラウザからgoogle map開いたりアプリストア開いたりできるのはこれのおかげです。
OSにデフォルトで定義されている挙動もありますが、Cefではその前の段階で挙動をハンドリングすることができます。
ISchemeHandlerFactoryについて
カスタムURLスキームのハンドリングにはISchemeHandlerではなくIResourceHandlerを利用します。
URLは<scheme>://<host>/<path&query>
となっていて、スキームごとにCefにハンドラを登録することができるのですが、直接ハンドラを登録するのではなくて、スキームのハンドラのファクトリをプロパティに持つカスタムスキームクラスをCefSettingsに登録する必要があって、手順が少し複雑です。
カスタムスキームとして"sample"を利用する場合には↓のようなコードになります。(sample://hogeみたいなurlに遷移しようとするとハンドラが呼び出される)
var CefSettings = new CefSettings();
var customScheme = new CefCustomScheme();
customScheme.SchemeName = "sample";
customScheme.SchemeHandlerFactory = new SchemeHandlerFactory();
cefSettings.RegisterScheme(customScheme);
Cef.Initialize(cefSettings);
ISchemeHandlerFactoryの実装
ISchemeHandlerFactoryは、リクエストがあったときにそれに対応するハンドラを生成するCreateメソッドのみを実装すればOKです。
urlのホスト部で大きく処理を変えることが多いはずなので、ホスト部の処理ごとにハンドラを用意しておくのがいいと思います。
class SchemeHandlerFactory : ISchemeHandlerFactory
{
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
return new SchemeHandler();
}
}
SchemeHandlerについて
カスタムスキームのハンドリングするためのSchemeHandlerやそのインターフェースであるISchemeHandlerといったものは存在せず、IRequestHandlerを実装したクラスをカスタムスキームのハンドラとして利用します。
ありがたいことにIResourceHandlerにはデフォルトの実装をもったResourceHandlerクラスが存在するので、それを拡張してハンドラを実装しましょう。
実装する必要がある個所はProcessRequestAsyncのみです。
class SchemeHandler : ResourceHandler
{
public override bool ProcessRequestAsync(IRequest request, ICallback callback)
{
// 何かrequest.Urlを見たりして処理する
return false;
}
}
falseを返しておけばリクエストがキャンセルされるので基本的にfalseを返しておけばいいと思います。
7/26追記
内部でasyncな処理とかをしてる時はfalseを返すと即座に処理が中断されちゃうので、trueを返したうえでasyncな処理が終わったタイミングでcallback.Cancel()を呼ぶのが正しいようです(リクエストをキャンセルする場合)。