2015 年やったこと - Mozc 編
1 年遅れぐらいになりますが,OSS Mozc 関係で 2015 年にやったことのまとめです.
空き時間を利用したプロダクトチーム外からのコミットということで,新規機能に関しては引き続き何も行っていません.前年と同じく OSS プロジェクトとしての環境整備と技術的負債の解消に注力した年でした.
以下が主な活動内容です.
- Google Code (Subversion) から GitHub (git) への移行を完了
- コードの簡略化
- プロダクションに使われなかった実験的コードの削除
- サポートを終了した古い OS 向けコードの削除
- 積極的にコンパイラをアップグレードし,C++ 11 のライブラリでコードを書き換え
- Windows 環境は Visual C++ 2010 から 2013 を経て 2015 へ
- インストーラの Universal CRT 対応
- 非 Windows 環境は
GCC
からClang
/libc++
に移行 base/hash_tables.h
をstd::unordered_map
/std::unordered_set
に置き換えmozc::scoped_ptr<T>
をstd::unique_ptr<T>
に置き換え
- Windows 環境は Visual C++ 2010 から 2013 を経て 2015 へ
- Windows 10 向けの緊急性の高い問題の修正
コミット単位でみる作業まとめ
Windows XP 向けコードの削除
- Demove dead code that is never used in Windows Vista or later · google/mozc@b782c5a · GitHub
- Implicitly link to SlimReaderWriterLock APIs · google/mozc@6182d5e · GitHub
- Implicitly link to input.dll on Windows. · google/mozc@f470414 · GitHub
- Require Windows Vista SP2 or later · google/mozc@e373cda · GitHub
- Initialize NONCLIENTMETRICSW structure to be compatible with Windows … · google/mozc@d2e7239 · GitHub
以前は最低サポート環境が Windows XP であったため,Windows Vista 以降に追加された API は GetProcAddress
で動的にリンクするというスタイルで統一されていました.Windows XP 廃止後も同様のコードは動くことは動くのですが,コードが不必要に長くなるだけでなく,Loader Lock に代表されるような同期的モジュール解決の問題すらも不必要に呼び込んでしまいます.そこで,Windows Vista 以降に追加された API に関しても可能な限り暗黙的なリンク (Implicit Linking) に変更したのが主な変更内容です.
少し冒険してみた点としては,DLL の Import Library が提供されない input.dll
についても,ビルドルールを工夫して暗黙的にリンクするようにしてみたということでしょうか.基本的には DLL から「正しい」LIB ファイルを作るには と同じことを行っています.
Android 版の不要なコードの削除
- Rely on pthread to implement reader-writer lock for Android · google/mozc@7d03922 · GitHub
- Remove a workaround for sysconf w/ _SC_PHYS_PAGES · google/mozc@46440f3 · GitHub
サポートバージョンを上げたことにより不要になったコードを削除しました.
Visual C++ 2013 への移行
- Require Visual C++ 2013 to build Mozc for Windows · google/mozc@1423238 · GitHub
- Remove a workaround code for Visual C++ 2010 (KB813540) · google/mozc@091dc3b · GitHub
- Enforce NOMINMAX macro everywhere in Mozc. · google/mozc@2cc1a05 · GitHub
- Use VersionHelpers.h to simplify SystemUtil · google/mozc@812d5b8 · GitHub
- Use predefined constants when possible · google/mozc@c8fdbc9 · GitHub
- Use constants defined in the latest Windows SDK. · google/mozc@fd0f5b3 · GitHub
Mozc の Windows 向けビルドは,2015 年始めの時点では依然として Visual C++ 2010 を使用しており,これが C++ 11 移行の大きな障害となっていました.これをまずは Visual C++ 2013 段階までアップグレードするという試みです.これに付随して,Windows Kit (Windows SDK) 8.1 に追加されたライブラリや定数を使ったコードの簡略化も行いました.
この過程で遂に実現できたもののひとつに,NOMINMAX
マクロをプロジェクト全体に適用することに成功した,というものがあります.そうです,<windows.h>
を include するだけで,min
/max
というプリプロセッサマクロが定義されてしまうという問題が,commit 2cc1a055 によってついに過去のものとなったのでした.
Visual C++ 2015 への移行準備
- Pull google/googletest@82b11b8cfcca464c2ac74b623d04e74452e74f32 · google/mozc@d76bf78 · GitHub
- Import a subset of WTL 9.1.5321. · google/mozc@f149187 · GitHub
- Pull google/protobuf@b152d7feb9c0a739d7f227eb840858133a4111ef · google/mozc@d17c374 · GitHub
- Pull google/protobuf@d4569d1f5ede96238dbb87b0ecc1fdcfbd399f62 · google/mozc@0670fac · GitHub
- Support building Mozc with Visual C++ 2015 · google/mozc@9b97b61 · GitHub
- Use Visual C++ 2015 merge modules as needed · google/mozc@22b5334 · GitHub
- Support Visual C++ 2015 in post-build actions · google/mozc@07c50e3 · GitHub
- Pull google/protobuf@1a59a715dc5fa584340197aac0811ba3de9850b5 · google/mozc@c43fd81 · GitHub
- Pull google/protobuf@1a59a715dc5fa584340197aac0811ba3de9850b5 · google/mozc@c43fd81 · GitHub
2015 年の年末にかけて,さらに Visual C++ 2013 から Visual C++ 2015 への移行の下準備を行いました.移行の完成は 2016 年を待つことになりますが,2015 年の段階である程度の下準備 (Google Test
や Protocol Buffers
のアップデート等) を完了することができました.
C++ 11 対応
- Switch from stlport to libcxx in Android build · google/mozc@bf59692 · GitHub * Remove legacy base/hash_tables.h in favor of C++11 · google/mozc@6895df1 · GitHub
- Make error message from DISALLOW_COPY_AND_ASSIGN and DISALLOW_IMPLICI… · google/mozc@987b0e9 · GitHub
- Require Clang to build Linux host binaries · google/mozc@7df47a1 · GitHub
- Use Clang 3.4 to build host binaries · google/mozc@4cff93c · GitHub
- Enable C++11 features in gtest. · google/mozc@aff84de · GitHub
- Deprecate scoped_ptr part 1. · google/mozc@d56d5db · GitHub
- Deprecate scoped_ptr part 2. · google/mozc@b3330bb · GitHub
- Deprecate scoped_ptr part 3. · google/mozc@1ed3119 · GitHub
Visual C++ 2013 への移行でいよいよ C++ 11 対応の目途がたったことから,まずは全プラットフォームで C++ 11 が前提とできるようにビルドルールの変更等と行いました.この過程で STLPort
を利用した Android ビルドを非サポートとしたり,非 Windows 環境のデフォルトコンパイラを Clang に統一したりといった変更も行っており,全体としてはビルドルールの簡略化に貢献できたものを考えています.
その後,実際に C++ 11 の新しいライブラリを用いて以下のような置き換えを行いました.技術的に難しいところはないものの,単純に多数のファイルを変更する必要があるため,時間に余裕があるときでないとなかなか難しい作業です.
base/hash_tables.h
をstd::unordered_map
/std::unordered_set
に置き換えmozc::scoped_ptr<T>
をstd::unique_ptr<T>
に置き換え
実験的コードの削除
Remove unused code from mozc_tool · google/mozc@51b1f78 · GitHub
もしかしたら将来使うかも,と導入したものの,結局プロダクションで使われなかったコードの削除も行いました.例えば上記コミットで削除されているコードは,1,000 行以上もありながら Windows 専用かつプロダクションでは一度も使われていないという正真正銘デッドコードです.
ibus-mozc 廃止に向けた下準備
- Enable undo-commit iff IBUS_CAP_SURROUNDING_TEXT is set. · google/mozc@0796f51 · GitHub
- Stop working around a limitation in GTK IM-module. · google/mozc@9fbcdd5 · GitHub
- Remove dead code from mozc_server. · google/mozc@7a129e6 · GitHub
- Enable 'ibus_mozc_test'. · google/mozc@b71fe3d · GitHub
予定されていた ibus-mozc
の廃止は結局 2015 年中に行われませんでしたが,そのための下準備としていくつか ibus-mozc
関連のコードのクリーンアップを行っています.
一番入れたかった変更は commit 7a129e65 で,mozc_server
中にある ibus-mozc
専用コードを今のうちに削除しておくというものです.このコードは,IMR_QUERYCHARPOSITION や NSTextInputClient firstRect と同様の機能をなんとか Gtk+ IM Module 上に実現しようとしたものの名残で,クライアントコードはなるべく簡潔にするという Mozc の設計思想に基づき mozc_server
側にエミュレーションコードが実装されました.しかしながら,Mozc Issue #243 で議論されているように本質的に解決できないコーナーケースが存在すること,および ibus-mozc
以外では使用されていないこと,という 2 点の理由から,ibus-mozc
廃止前に完全に削除しておきたかったのでした.
GitHub への移行と Continuous Integration (CI) の整備
Google Code のサービスを終了にともない,OSS Mozc についても GitHub への移行を行うこととなりました.当時は私自身あまり git に慣れていなかったこともあり,Subversion から git への移行をあれこれ試行錯誤するのにずいぶんと時間を使ったように思います.
とはいえ移行が済んだあとは GitHub のエコシステムに感心するばかりでした.特に CI については最終的にサポートしている全プラットフォームについて自動ビルドをセットアップすることができ,マルチプラットフォーム対応に価値を置いているプロジェクトとしては本当に助かっています.
Travis CI のセットアップ
- Enable continuous build for OS X with Travis-CI. · google/mozc@7e20f88 · GitHub
- Enable Linux desktop build on Travis-CI. · google/mozc@0e0e5c2 · GitHub
- Enable NaCl build on Travis-CI. · google/mozc@6215113 · GitHub
- Enable Android build on Travis-CI. · google/mozc@0f5e8a0 · GitHub
- Enable unittest for Linux and OSX on Travis-CI. · google/mozc@c557fcd · GitHub
- Remove unnecessary '-r' option from 'ln' command. · google/mozc@b207fa6 · GitHub
- Reduce the test concurrency. · google/mozc@446b53b · GitHub
AppVeyor のセットアップ
- Enable continuous build for Window with AppVeyor. · google/mozc@6acd05e · GitHub
- Build all targets on AppVeyor. · google/mozc@f806322 · GitHub
gclient から git submodule への移行
- Follow repository migration of GYP from gyp.googlecode.com to chromiu… · google/mozc@57aa5c3 · GitHub
- Use the official zlib repository rather than Chromium's mirror · google/mozc@be8d070 · GitHub
- Import a subset of WTL 9.0 into third_party/wtl/. · google/mozc@d2b01f7 · GitHub
- Update repository URLs of third party libraries. · google/mozc@8a53a39 · GitHub
- Use system-installed jsr305.jar for Android build. · google/mozc@0f4b21b · GitHub
- Build Zinnia from source by default. · google/mozc@03c3155 · GitHub
- Replace gclient/DEPS with git sub-modules. · google/mozc@276fa5c · GitHub
Windows 10 対応
- Update status icon even for Windows Store Apps. · google/mozc@0989ef2 · GitHub
- Introduce a workaround for sandboxed applications. · google/mozc@a2c1d40 · GitHub
Windows 10 で状況が変わった点についてもいくつか緊急的な修正を行いました.
- 言語バーが Store App でも使われるようになったことへの対処
- サンドボックス下で実行されるアプリケーションから
mozc_server
プロセスを起動できないという制約が Windows 8.1 時代よりも目立つようになったため,いくつかの対症療法的な変更
不安定なテストの改善
- Make NamedEventTest deterministic. · google/mozc@68ae78f · GitHub
- Try to fix flaky session_handler_scenario_test. · google/mozc@d9d63a1 · GitHub
Travis CI 上で不安定だったテストについて安定化を試みました.
透明度付き PNG ファイルを PBGRA32 形式の Bitmap ファイルの変換するツールを作成
ちょうど 2015 年,会社のロゴが更新され,候補ウィンドウに表示される画像も変更する必要ができました.
Windows 版の mozc_renderer
は,会社ロゴの表示に GDI の AlphaBlend API を利用しています.問題はこの API はいわゆる乗算済みアルファ フォーマット (正確には PBGRA32 形式) を期待していることです.デザイナーさんから渡された PNG ファイルを PBGRA32 に変更する必要があったですが,適当なツールがみつからなかったので急遽作ったのがこちらのコードでした.
雑感
以前から興味のあった GitHub 上での作業や CI について一通り体験することができたのは非常に有意義でした.また,git filter-branch
や git rebase
を使ったコミット履歴の編集を学ぶ上でも良い機会でした.
一方,前年に引き続きメンテナンス作業に注力して実感したのは,ソフトウェアのメンテナンスというのは本当にコストがかかるというというものでした.OSS Mozc に関して言うと,以下の作業だけで年間 100 時間は軽くかかっています.
- コンパイラのバージョンを上げる
- 依存するライブラリのバージョンを上げる
- 丁寧にリリースノートを書く
- ドキュメントを最新の状態に維持する
- Issure Tracker に報告された問題に丁寧に答える
自分の場合これらの作業に有給休暇 10 日分以上を消費していることになるわけで,今後も同程度の貢献が継続可能かというと大変に疑問です.各種 Linux ディストリビューションで OSS Mozc が採用されるのはありがたい一方,最大の不安は期待値が高くなりすぎることです.将来のメンテナンスも含めて,あくまで無保証で提供されているという点を今一度思い出していただければという次第.
過去の関連エントリ
Android 7.1 に追加した API
github.com github.com github.com github.com
BaseInputConnection#commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle)
EditorInfo#contentMimeTypes
InputConnection#INPUT_CONTENT_GRANT_READ_URI_PERMISSION
InputConnection#commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle)
InputConnectionWrapper#commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle)
InputContentInfo#InputContentInfo(android.net.Uri, android.content.ClipDescription)
InputContentInfo#InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri)
InputContentInfo#describeContents()
InputContentInfo#getContentUri()
InputContentInfo#getDescription()
InputContentInfo#getLinkUri()
InputContentInfo#writeToParcel(android.os.Parcel, int)
InputContentInfo#CREATOR
Android 7.0 Nougat に追加した API
View#dispatchFinishTemporaryDetach()
View#dispatchStartTemporaryDetach()
View#isTemporarilyDetached()
InputConnection#closeConnection()
InputConnectionWrapper#closeConnection()
BaseInputConnection#closeConnection()
InputConnection#getHandler()
InputConnectionWrapper#getHandler()
BaseInputConnection#getHandler()
Settings#ACTION_KEYBOARD_LAYOUT_SETTINGS
TextView#getImeHintLocales()
TextView#setImeHintLocales()
LocaleSpan#LocaleSpan(LocaleList)
LocaleSpan#getLocales()
SuggestionSpan#getLocaleObject()
InputConnection#deleteSurroundingTextInCodePoints(int, int)
InputMethodManager#dispatchKeyEventFromInputMethod(View, KeyEvent)
InputMethodSubtype#getLanguageTag()
InputMethodSubtype.InputMethodSubtypeBuilder#setLanguageTag(String)
SpellCheckerSubtype#getLanguageTag()
EditorInfo#locales()
LocaleList#describeContents()
LocaleList#writeToParcel(Parcel, int)
LocaleList#CREATOR
Windows 10 Insider Preview Build 14332 実験ノート: ブラウザと IME のプライベートモード連携
Windows 10 Preview ビルド 14328 でお試しいただける日本語 IME の変更点について – Windows & Devices 開発統括部
入力履歴の管理が便利になりました。人に見られたくない履歴が候補リストに表示されて困った経験はありませんか?
プライベートモード(仮称)を使えば、その間に蓄積された入力履歴はモードの終了時には削除され、その後意図しない場面で表示されてしまうことを防ぐことができます。
プライベートモード(仮称)はIME のアイコンをクリックして表示されるメニューから「プライベートモード」を選択することでオン・オフすることができます。Edge や Internet Explorer で InPrivate ブラウズ機能をお使いの場合は、本機能が自動的に オン・オフ されます。
プライベートモード(仮称)で蓄積された入力履歴はプライベートモードの間だけ有効となり、モードの終了時には削除されます。それまでにプライベートモード以外で蓄積されていた入力履歴のデータには影響ありません。
ブラウザと IME のプライベートモード連携は,自分にとっても時間があったらやれたらいいなぁと思っていた機能だったこともあって,週末を利用して少し調べてみました,がどうも時間切れっぽいのでメモだけでも残しておきます.想定読者はブラウザ開発者,IME 開発者,および IME API 開発者という感じですが,正直に言えば自分用のメモです.
この機能,名前に (仮称) が付いているようにまだまだフィードバックしだいで色々変わりうる段階と思われます.というわけでまだちょっと調べたりないのですが,実験したい人向けにメモでも残しておく次第です.
疑問点
- そもそも Internet Explorer / Edge と MS-IME はどのようなプロトコルでこの動作を行っているのか?
- サードパーティ製のブラウザと MS-IME の組み合わせで同じことができるか?
- Internet Explorer / Edge とサードパーティー製の IME で同じことができるか?
今回の調査結果
そもそも Internet Explorer / Edge と MS-IME はどのようなプロトコルでこの動作を行っているのか?
時間内に絞り込み切れませんでした.無念……
サードパーティ製のブラウザと MS-IME の組み合わせで同じことができるか?
上の結果が確定しなかったため確たる結論に至れず.残念……
Internet Explorer / Edge とサードパーティー製の IME で同じことができるか?
公開 API のみで,InPrivate モードの検出が可能であることまでは確認.少なくとも見かけ上は可能.
調べたこと
ITfTextInputProcessorEx::ActivateEx
に指定されるflags
は,InPrivate かどうかで変化するか?ITfThreadMgr::GetGlobalCompartment
→ITfCompartmentMgr::EnumCompartments
の結果は InPrivate かどうかで変化するか?ITfThreadMgr::QueryInterface
→ITfCompartmentMgr::EnumCompartments
の結果は InPrivate かどうかで変化するか?ITfDocumentMgr::QueryInterface
→ITfCompartmentMgr::EnumCompartments
の結果は InPrivate かどうかで変化するか?ITfContext::QueryInterface
→ITfCompartmentMgr::EnumCompartments
の結果は InPrivate かどうかで変化するか?ITfContext::EnumProperties
で列挙されるITfProperty
に対応しそうなものはあるか?- Edge の設定する
InputScope
は InPrivate かどうかで変化するか? InputScope
の一種IS_PRIVATE
(== 61
) で MS-IME は動作を変化させるか?- Windows 10 Anniversary SDK Preview Build 14332 の API ヘッダの差分および InPrivate と付いた API に関連しそうなものはあるか?
得られた知見
- Build 14332 時点で,正式な InPrivate 連携 API が Text Services Framework (TSF) に存在するかどうかは疑わしい.InputScope を含め,TSF の API で観測可能な範囲内に InPrivate モードの有効無効を示唆するものは一切見つけられなかった.
- Build 14332 時点で,
InputScope
の一種IS_PRIVATE
によって MS-IME をプライベートモードにすることはできなかった. - Internet Explorer であれば,
ieframe.dll
のエクスポート関数IEIsInPrivateBrowsing
が依然として利用可能.ただしこの API は Edge のプロセスには読み込まれない. - Windows 10 SDK では,
ProcessInPrivateInfo
という列挙値がprocessthreadsapi.h
に追加されている (少なくとも 10.0.10586.0 SDK の時点で既に存在する).
typedef enum _PROCESS_INFORMATION_CLASS { ProcessMemoryPriority, ProcessMemoryExhaustionInfo, ProcessAppMemoryInfo, ProcessInPrivateInfo, ProcessInformationClassMax } PROCESS_INFORMATION_CLASS;
Build 14332 時点で,以下のコードは Internet Explorer および Edge 共に InPrivate モードのみ true を返す.
bool is_process_in_private() { BYTE value = 0; if (!::GetProcessInformation(GetCurrentProcess(), ProcessInPrivateInfo, &value, sizeof(value)) { return false; } return value != 0; }
フィードバックアイディア
ちょっと裏付け不足でまだ未登録なのですが,概ね以下の点についてもうちょい調べてみないとなーと思っております.
- プライベートモード連携に関しては,TSF の公開 API 内で完結させ,サードパーティー製ブラウザおよびサードパーティー製 IME との相互運用性に配慮して欲しい.ファーストパーティ製ブラウザおよびファーストパーティ製 IME の間のみで使われるプライベートプロトコルは好ましくない.
- ProcessInPrivateInfo は,現状取得のみが可能なように見える.これに該当する特殊プロセスの作成に非公開 API が必要なのであれば,ファーストパーティ製ブラウザのみがそれを使用可能という状況は好ましくない.
関連事例
(同一プロセスで動く IME で使うことを前提とした) Accessibility API を利用したプライベートモード検出
書くいう自分も,2013 年末ごろには MSAA を使ってプライベートモードの検出ができるかどうか実験したりしていました,がチームを移ったあとのごたごたで結局プロダクションでは使われてなかったりします.その辺のコードがいまもここに.
mozc/src/win32/base/browser_info.cc
BrowserInfo::IsInIncognitoMode
sufix
は typo ですすみません.あとで直します……
Chromium Bug 311180: Chrome OS: Incognito window is not really incognito for IME users
Chromium OS での同様の機能リクエスト.長いこと放置されていて辛い感じです.
Chromium Bug 601951: Android keyboard suggestions leak information typed in incognito window
Android 版 Chromium での同様の機能リクエスト.
この件については SwiftKey のサポートページにも以下のように書かれていたり.
Can I turn off learning in incognito mode with SwiftKey Keyboard for Android? – SwiftKey Support
Unfortunately, the keyboard actually does not know that you are in this special mode in the Chrome app because that is not something Google passes on to other apps.
改定履歴
- 2016-05-02:
ProcessInPrivateInfo
の追加時期について表現を変更.少なくとも 10.0.10586.0 SDK の時点で存在する.