ククログ

株式会社クリアコード > ククログ > Chromium Embedded Frameworkへのコントリビュート体験談

Chromium Embedded Frameworkへのコントリビュート体験談

最近、ChronosというChromiumベースのWebブラウザの開発をしている橋田です。仮想化ソリューションと組み合わせて、Windows環境で動作する仮想化アプリとして提供するプロダクトです。

Chronosでは、Chromiumブラウザを自作のアプリケーションに組み込むためのフレームワークである「Chromium Embedded Framework」を使っています(以降「CEF」と表記)。

先日、Chronosの開発を通じて、CEFに簡単な機能追加のパッチを提供しました。 今回はその体験を元に、CEFへのコントリビュートの流れを紹介します。

後半には、さらによくわかる特別コンテンツ(?)もありますのであわせてどうぞ。

経緯

簡単な経緯です。あわせて、関連リンクも付けます。

  1. きっかけは、Chronosで「ファイルのダウンロードに失敗すると、その後ダウンロードができなくなる」問題を検知したこと。

  2. その原因調査の最中、CEFが管理しているダウンロードステータスに、「中断(Interrupted)」というステータスが存在しないことに気付いた。Chromiumとしては中断された状態なのだが、CEFではその「中断」ステータスを参照していない様子であった。

  3. CEFとして「ダウンロードが中断されたか」をどう判定するか不明だったので、CEFのフォーラムで質問した。

  4. すると「中断ステータスを取得するメソッドをCEFに追加するのが良い」「Feature RequestのIssueを立てて欲しい、プルリクエストでパッチ提供も歓迎」との返答があった。

  5. クリアコードとしては、可能な限り問題をアップストリームで直す1ことを理念としている。今回もその理念に沿ってパッチ提供をした。

CEFプロジェクトに関する基本情報

CEFプロジェクトにコントリビュートするための基本的な情報をまとめます。

  • ソースコードはBitbucketで管理されている。
  • プルリクエストはBitbucket上で行う。
    • GitHubのCEFプロジェクトは上記Bitbucketのミラーの扱いのため、修正を取り込んでもらうにはBitbucketのリポジトリへとフィードバックする必要がある。
  • Issue TrackerにはGitHubのIssuesを使用している。バグレポートや機能追加要求はそちらで行う。
  • 使い方などの質問はCEFのサポートフォーラムに投稿する。

流れの紹介は以上となります。

「そこkwsk」なインタビュー

突然ですが、2023年1月に入社しました屋代です。 橋田さんと同じチームでChronos開発業務に携わっています。

この件についてミーティング等で随時聞いてはいました。けれども、話がするすると進みすぎていて、正直なところついていけてなかったです。

そこでブログ記事化するこのタイミングで時間を取ってもらい、前段に書かれた経緯の「すき間」を中心に「そこもう少し詳しく!」をあれこれ聞いてみました。

以下、一問一答形式で記述します。

フォーラムへのレポートまで

(ヤシロ)――「一度失敗するとファイルダウンロードができなくなる」Chronosの問題を調査されていて、「CEFでは中断ステータスを参照していない様子であった」とのお話でした。もう少しかみくだいて教えてほしいんですが、どうやってわかったんですか?

(橋田)「CEFのダウンロードのステータスには「実行中」、「完了」、「キャンセル」の3つがあったのですが、事象を再現させて確認すると、そのいずれのステータスでもなかったので。ドキュメントではIsCanceled(キャンセルステータス)に失敗などによる中断も含まれるとあったのですが、実際にはキャンセルステータスにもなっていませんでした」

(以下発言者省略)

――grepしてもヒットしないな、という感じですか?

「そんなところです」

――ドキュメントって、どこを見たんですか?

「ググってこのへんから、ですかね」
Chromium Embedded Framework (CEF) Documentation

――ドキュメントってコード以上に見つけにくい印象があります

「今回どこかにあるだろうとは予想してました」

――というのは?

「APIとして公開されているので、そのドキュメントもどこかに公開されているはずですから」

――なるほど。で「アップストリームで直す」プロセスを発動させたわけですが、CEFプロジェクトへのフィードバックって、前にされたことはあるんですか?

「いえ、初めてでした」

――どこへコンタクトを取ればいいかっていうのはどうやって知ったんですか?

「それもググると出てきました」

――あ、そうなんですね(ビギナーにはハードル高そう……)。ちなみにどんなキーワードで検索したんですか?

「うーん、あんまりよく覚えてませんけど、調査の時にChromium IsCanceledとかhow to detect interrupted downloadとかをChromium Embedded Frameworkと組み合わせて検索したのかな。それでドキュメントやフォーラムのページも一緒にヒットしたんで、あ、そういうのがあるのかと気には留めていました」

――その時のリンクをたどって、How to detect interrupted downloads in OnDownloadUpdated?をフォーラムに投稿されたんですね

「そうです」

Issueオープン・PR作成まで

――橋田さんがオープンしたスレッドを見ますと、返事する側はなんというか、軽いですね

「そうですね。機能追加要望よろしく。出来るならPRもウェルカム。みたいな」

――言葉は悪いですけど、ドキュメントが「嘘」だったのに

「ええ、まあ……。でも、そういうことはよくあるので。個人的に、ドキュメントに間違いがあることにネガティブな印象はないですね」

――へぇ、そんなもんっすか……。ということで、橋田さんがファイルダウンロードのIsCanceled部分をカバーするメソッドを追加したと

「いや。正確に言うと、中断IsInterruptedになるケースですね」

――そうでしたか。訂正ありがとうございます。

CEFビルドのこと

――当然ですが、たとえ小規模の修正でも、ちゃんと確認した上でパッチ提供しないといけませんよね

「ですね。動作の確認には手元でCEFをビルドする必要がありました」

――知らないんですけど、CEFのビルドって簡単にできるもんなんですか?

CEFのWikiビルドの手順が載っていて、その通りにできました。そこはなんも問題なかったです」

「ただマシンスペックがないと、時間がかかりますね。私が使ったのは昨年調達したそれなりにハイスペックなマシンだったんで、そこまででもなかったですが」

――具体的に、ビルド時間はどれぐらいでしたか?

「3時間くらいでした」

――え!それでもそんなにかかるんですか。ビルドが終わるまで「シャイニング」1回半鑑賞できますね

「そこで観なくてもいいと思いますけど(笑)」

CEFテストのこと

――テストコードはどうされたんですか?

「CEFにはceftestsというのがあって、そこへテストケースを追加する必要がありました」

――具体的にはどこですか?

tests/ceftests/download_unittest.ccに、IsInterrupted()のケースを足しました」

――どうなったらOKなんですか?

「本当は全てのテストケースがパスすることを確認すべきですが、今回は修正内容が限定的であったこともあり、修正を加えたテストファイルのテストが全て通ればOKと判断しました」

「初めてパッチ提供するビギナーである旨も伝えたので、何か問題があったらPRレビューで指摘がされるだろうと、わりと楽観的でした」

PR作成からマージまで

――プルリクエスト:Add IsInterrupted and GetInterruptReason for CefDownloadItemを見ますと、実際何点かコメントがあって、反映されてました

「はい」

――リクエスト自体は残念ながら(?)最終的に「Declined」になってます

「そうですね。別途同様の修正をして、取り込んだみたいです」

――「manually merged with minor changes in master revision」となってましたね

――橋田さんのリクエストをそのままマージしなかったのってどうしてなんでしょうね。別のIssueと競合したとか、ですかね?

「だと思います。そこまでは見れてないですが」

――CEFとしてはこれで反映されたってことなんでしょうか?

「ですね。masterに入ったんで、次期バージョンのリリースで反映されてると思います」

――反映されたバージョンのCEFを組み込んでChronosを動作させるよう、注意しないといけませんね

「いえいえ。仮にCEFの動作が従来どおりであってもChronos側に影響しないように、Chronosのダウンロード動作を改修しましたから」

――あ、そう言えばそう報告されてたような(記憶が怪しい……)。具体的にはどのように?

「もし、OnDownloadUpdatedの中で「実行中」でも「完了」でもなかったら、キャンセルもしくは中断と判断するようにしました。こちらです」
Fix a bug that download doesn't work after failing to download

――なるほど

感想

――今回の経験を通じて、どう感じましたか?

「BitbucketのUIが、ふだん使っているGitLabやGitHubとは違ったので、そこは少し慣れがいりました」

「けれどもCEFはドキュメントが充実していて、初めてPRを出すのも比較的やりやすかった気がします。その点は自社のプロジェクトでも見習わないとな、と」

――ありがとうございます

まとめに代えて

屋代の感想です。

入社前の感覚だと、オープンソースソフトウェアってas isでそのまま使うもので、何か働きかけるって発想がほとんどなかったです。

「いつでも問題をアップストリームで直す」を行動指針とするクリアコードに入社した今もなお、オープンソースへの「コントリビューション」っていくぶんハードルが高いなと感じています。日常生活でそんなワードも聞かないし。

けれども今回、橋田さんが業務の一環として実施されてきたことを近くで見聞きして、もし今後似たケースに遭遇したらこのように進めればいいんだなと、かなり具体的にイメージできました。前回参加をためらってしまったOSS Gateのオンラインワークショップにも申し込みました。

発見した問題は報告し、可能なら修正パッチを提供することで、同じ問題にぶつかる人を地球規模で減らせます。その意味で、ほんの少しだけ世界平和にも貢献できます。

そんなところです。

  1. Chronos側で対応するのではなく、CEFに機能追加することで、Chronos以外のCEFユーザーも追加された機能を使用できる。そちらの方が理想的である。