Chromiumにシークレット"タブ"を追加する

今回の目標

Chromeを使っていて、閲覧履歴を残したくない、というときありますよね。
そんなときに活躍するのが「シークレットウィンドウ」なのですが、 普通のブラウザとシークレットモードのブラウザを分けて開かなくてはなりません。
...不便じゃないですか?不便ですよね。はい。
ということで今回はChromiumにシークレット"タブ"を追加してみようと思います。

まずはシークレットウィンドウに関連する部分を探す

いきなり変更を加えると言ってもChromiumソースコードは膨大な量なのでどこから手を付けていいか見当も付きません。
まずは関係ありそうなところをChromium Code Searchで探ってみましょう。

シークレットモードは内部では"Incognito"と言うようなのでnewincognitowindowで検索してみると、
f:id:glycelery:20181025155432p:plain あった。(実は探すのめっちゃ苦労したけどそれは内緒)

見てみるとその下にはちょうどNewTabなんて関数も。
f:id:glycelery:20181025155944p:plain

この2つを組み合わせればシークレットタブを作れちゃうのでは?

NewWindowとNewIncognitoWindowを見比べてみると、プリプロセッサ指令の違いはあるものの大きな違いは
GetOriginalProfile()かGetOffTheRecordProfile()かの違い。

これを踏まえてNewIncognitoTabを作ってみる。

コードを書き換えていく

タブを開くときにbrowserのprofileごと書き換えちゃおうという強引な発想。
ただbrowserのprofileは書き換えられないようconst定義がされていたのでそれを外しついでにセッターを定義。

またこのままだと続けて開くタブが全てシークレットモードになってしまうためNewTabにGetOriginalProfile()の処理を追加。

そしてチェックを一つ外す。

さて、なかなか強引だができたんじゃなかろうか...?
ということで試しにシークレットウィンドウを開くボタンをシークレットタブに割り当てて実行してみる。

とりあえずテスト

...こんな適当な変更で動いてしまった。
履歴もしっかり残らないしログイン情報も残らない。

f:id:glycelery:20181026112949p:plain


今回はテスト的にシークレットウィンドウボタンに割り当てましたが
次回は"シークレットタブを開く"コマンドを追加して、見た目をそれっぽくしていきます。

Chromiumをgdbでデバッグする

Chromiumの動作を追う

以前Chromiumソースコードを読み解くツールとしてChromium Code Searchを紹介しました。

glycelery.hatenablog.com

しかし、名前に全く見当がつかなくて検索できない!ということもあると思います。
そんなときはデバッグで実際の動きを追ってやりましょう。
今回はgdbChromiumデバッグする際に有用なコマンドを紹介します。

プロセスを選んでデバッグする

まずはChromiumを起動した状態で、別のコンソールからその実行プロセスIDを調べてみましょう。

$ ps axf

f:id:glycelery:20181024163241p:plain

すると現在実行されているプロセスがツリー状に表示されます。その中にさっき起動したChromiumもありましたね。
今回は新しいタブを開く動作を追うために、試しに赤枠で囲ったプロセスを追ってみましょう。

$ gdb -p 9089

このように"-p"オプションにプロセスIDを指定することで目的のプロセスをデバッグすることができる。
プロセスIDはps axfでいう一番左の列ですね。

子プロセスを追う

gdbでマルチプロセスのアプリケーションを追う場合、通常の設定では子プロセスが発生した場合でも、gdbはもとの親プロセスを追い続けてしまう。
子プロセスでの動作を追いたいときには

> set follow-fork-mode child

と指定することにより、プロセスが分かれた際に子プロセスに追従が移るようになります。

シングルプロセスでデバッグする

上のやり方ではプロセスIDを指定するためどのプロセスで目的の動作が行われているかわかっている必要があった。
しかしプロセスが大量でどのプロセスが何なのかわからない、ということもあると思います。
そんなとき有効なのがシングルプロセスモード。

Chromiumでは以下のオプションが公式でサポートされている...

> r --single-process

f:id:glycelery:20181024163302p:plain

サポートされている...

[7117:7117:1024/155349.170354:ERROR:CONSOLE(1096)] "Uncaught TypeError: Cannot read property 'newTabPage' of undefined", source: chrome-search://local-ntp/local-ntp.js (1096)

されているはず...なんですが...サポートされていないオプションとして複数のエラーが発生する。。
アップデートで消えてしまったのでしょうか。

代わりに

> r -X

上のようなコマンドでシングルプロセスモードを指定することができます。
こちらはエラーもなくデバッグすることが可能。
これにより指定したブレークポイントを逃さず実行することができちゃいます。

最適な方法を

ここまで様々な方法を紹介しましたが、ときにより有効な手立ては違うでしょう。
最適なデバッグ方法を選べると良いですね。

Chromiumのコードを探る

Chromiumのソースを見てみたい

ソースコードになにか変更を加えてみたい!というとき、
まずはどこに何が書いてあるか調べなきゃいけないですよね。
でも自分で逐一ファイルを見ていくのは流石に手間がかかりすぎる。。

そんなときに役立つ便利な公式サイトを紹介します。

Chromium Code Search

https://cs.chromium.org/

こちらはChromiumソースコードの中から自由に検索ができるサイト。
膨大なソースコードからすぐに検索を行うことができる強力な検索ツールです。

f:id:glycelery:20181025183437p:plain

ソースコードを表示する画面では、

  • クリックで関数の定義にジャンプ
  • ファイル内検索
  • 対象OSの変更

などなど様々な機能が用意されています。

f:id:glycelery:20181025184013p:plain

気になる機能があるときはまず適当に検索にかけてみるのが発見への近道かも。

Design Document

www.chromium.org

こちらもChromium Project内で開発者向けに公開されているドキュメント。
主要な機能を司る部分の構造などが解説されています。
その部分がどのような意図に基づいて書かれているのか、などが解説されている場合が多いので
不可解に見える構造のコードでもデザインドキュメントに一度目を通してみると理解できるかも(?)

大規模だからこそ

Chromiumなどの大規模なソースコードを読み解くためには
まずデバッグするよりも検索ツールを利用したほうが有効だったりもするんですね。

ChromiumをGitでバージョン管理する

お馴染みのバージョン管理ツールGit

Chromiumをバージョン管理する上でもGitを使いたいところですが、Chromiumはcommitするにも一苦労。

Chromiumには先人のGit情報が

Chromiumをビルドするときにgclientのfetchを使ってソースをダウンロードしてきたのを覚えているでしょうか?

glycelery.hatenablog.com

gclientはgitベースのツールですので、持ってきたディレクトリの中にはgit管理されていた名残がたくさん残っています。
gitは差分を記録する方式なので、このままcommitしようとすると、一部のファイルのみしかcommitされません。。

Chromiumをcommitするには

なのでcommitするには中のgit情報を削除する必要があります。
ディレクトリの各所に存在する.gitフォルダをすべて削除してしまいましょう。
検索して一つ一つ削除していってもいいですが、 、

端末を起動してchromiumの親ディレクトリに移動し

$ find ./ -name ".git" -exec rm -rf {} \;

を実行してしまえばディレクトリ内すべての.gitを削除できます。

その後

$ git add .
$ git commit -m "your comment" -a

でcommitすればchromiumソース全体をバージョン管理することができます。
変更を保存するときはぜひ利用しましょう。

ChromiumをWSL(Windows Subsystem for Linux)上でビルドしたい

お手軽WSL

April Updateで正式に追加されたbash on Windows改めWindows Subsystem for Linux、通称WSL。気軽にLinux環境が使えるということで期待が高まります。
Windows上でのビルドは時間がかかりすぎる...のでChromiumのビルドもWSL上でできたら時間も短縮できて良さそうですよね。
ということで試してみました。

WSLの導入方法に関しては過去の記事をを参考にしてください。

glycelery.hatenablog.com

いよいよビルドしてみる

ビルドの詳しい手順に関しては以前の記事を参照してください。

glycelery.hatenablog.com

さて、順調に手順をすすめていったところ...

$ gclient runhooks
Syncing projects: 100% (206/206), done.
Running hooks:   5% ( 4/75) nacltools
________ running '/usr/bin/python src/build/download_nacl_toolchains.py --mode nacl_core_sdk sync --extract' in '/home/ybn/chromium'
INFO: Extracting package (nacl_arm_glibc) to directory: /home/***/chromium/src/native_client/toolchain/linux_x86/nacl_arm_glibc
INFO: Extracting binutils_arm_x86_64_linux.tgz (1/6)
|------------------------------------------------|
..................................................
INFO: Extracting gcc_arm_x86_64_linux.tgz (2/6)
|------------------------------------------------|
..................................................
INFO: Extracting gcc_libs_arm.tgz (3/6)
|------------------------------------------------|
.................................................
INFO: Extracting gdb_x86_64_linux.tgz (4/6)
|------------------------------------------------|
.................................................
INFO: Extracting glibc_arm.tgz (5/6)
|------------------------------------------------|
.................................................
Traceback (most recent call last):
  File "src/build/download_nacl_toolchains.py", line 59, in <module>
    sys.exit(Main(sys.argv[1:]))
  File "src/build/download_nacl_toolchains.py", line 55, in Main
    return package_version.main(args)
  File "/home/***/chromium/src/native_client/build/package_version/package_version.py", line 1289, in main
    return COMMANDS[arguments.command].do_cmd_func(arguments)
  File "/home/***/chromium/src/native_client/build/package_version/package_version.py", line 856, in _DoSyncCmd
    quiet=arguments.quiet)
  File "/home/***/chromium/src/native_client/build/package_version/package_version.py", line 562, in ExtractPackageTargets
    pynacl.file_tools.MoveAndMergeDirTree(temp_src_dir, destination_dir)
  File "/home/***/chromium/src/native_client/pynacl/file_tools.py", line 204, in MoveAndMergeDirTree
    MoveAndMergeDirTree(source_item, destination_item)
  File "/home/***/chromium/src/native_client/pynacl/file_tools.py", line 214, in MoveAndMergeDirTree
    Retry(os.rename, source_item, destination_item)
  File "/home/***/chromium/src/native_client/pynacl/file_tools.py", line 250, in Retry
    op(*args, **kwargs)
OSError: [Errno 13] Permission denied
Error: Command '/usr/bin/python src/build/download_nacl_toolchains.py --mode nacl_core_sdk sync --extract' returned non-zero exit status 1 in /home/***/chromium
Hook '/usr/bin/python src/build/download_nacl_toolchains.py --mode nacl_core_sdk sync --extract' took **.** secs

以上のようなエラーが発生。何度やっても同じ場所でエラーが出てしまう。
chmodなども試しましたが解決しませんでした。。

実は...

このエラー、実は各所で報告されているエラーのようです。
まだWSLの日が浅いので報告数も少なく、いろいろ探し回りましたが今のところ有効な解決策も見つかっていません。

結論

つまり、WSL上でChromiumをビルドするのは諦めましょう。

Windows Subsystem for Linux(WSL)の導入方法

お手軽Linux

Linuxを使ってみたい!けどパーティション...?とかよくわかんないしデータを飛ばしたくない!
っていう人は多いと思います。そんな人におすすめなのがこのWindows Subsystem for Linux(通称WSL)!
簡単にWindows上でLinuxライクな環境を動かすことができます。

WSLとは

以前から限定的に利用されていたBash on Windowsが2018年のApril Updateによって正式にリリースされWSLとして生まれ変わり、Windows10なら誰でも利用できるようになりました。
UbuntuDebianなど配信されている中から環境を選ぶこともできちゃうんです。すごいですね。

導入方法

ではさっそく導入していきましょう。

下準備

まずはWSLが利用できるように機能を有効化します。

コントロールパネルの「Windowsの機能の有効化または無効化」を開きます。
f:id:glycelery:20181024104901p:plain]

するとその中に「Windows Subsystem for Linux」の項目があると思いますのでチェックを有効にします。
f:id:glycelery:20181024105034p:plain

再起動を求められたらそのまま再起動しましょう。
はい、準備完了です。

環境をインストール

好みの環境を入手しましょう。

Microsoft Storeを開き画像のように検索すると,,,
f:id:glycelery:20181024105302p:plain

入手可能な環境が表示されるのであとはクリックしてインストールするだけ。
f:id:glycelery:20181024105415p:plain

起動も入手してきたアプリを開けばOK。なんて簡単なんでしょう。

しかし問題点も

とってもお手軽にLinux環境を入手できて良いのですが、完全にLinuxと同じことができる、というわけでもなさそうです。

glycelery.hatenablog.com

Windowsのユーザーの下に環境を作ることによって権限が与えられない箇所があるようで、 致命的なエラーにつながることもあるので、できないことがあっても手軽さに免じてまあ許してあげましょう。

Chromiumを自分でビルドしてみよう

自分でChromeの機能を作りたい

Chromeってとっても便利ですよね。
でも使っていると、「こんな機能ほしいな...」と思うことがたまにあります。
拡張機能を探してもそれらしいのが見つからない...。

よし、自分で作ってしまえばいいんだ。

ChromeChromium

とはいってもChromeGoogleの著作物なのでソースを勝手に書き換えちゃお~とかはできません。
そこで登場するのが「Chromium」。一言で言ってしまえばソースコードがすべて公開されてるChrome

詳しく知りたい人は公式サイトを見てみるといいでしょう。 www.chromium.org

さっそくビルドしてみよう

  • 用意するもの

以上。初回ビルドにはとにかく時間がかかります。心してかかりましょう。
WindowsMacでもできないことはないですが、おそらく30時間程かかります。
linux上でやることを強くオススメします。私はUbuntu16.04とUbuntu18.04で行っていました。
また、WSL(Windows Subsystem for Linux、旧bash on windows)は今のところ使えません。

ちなみに、ここに書いてあることはきっとすぐに古くなるでしょう。 もしうまく行かなかったら公式のドキュメントを確認してください。

Checking out and building Chromium on Linux

ビルド準備

必要なパッケージはだいたい同梱されているので、事前準備としてはpython, build-essential, git, vimがあればいいはず。

$ sudo apt-get install python build-essential git vim

depot_toolsの取得

まずはビルドに必要なツール「depot_tools」をcloneしてくる。depot_toolsにはgclientを始めChromiumを管理するツールがたくさん含まれています。
gclientの扱いなんかで困ったら公式サイトに使い方があるので見てみよう。

www.chromium.org

$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

今後の操作はこの中のツールを使って行うので必ずpathを通しておく。

相対パスを用いるとdepot_toolsがうまく読み込まないので、絶対パスを使うか

$ export PATH="$PATH:/path/to/depot_tools"

$HOMEを使って

$ export PATH="$PATH:${HOME}/depot_tools"

直接実行したり.bashrcに追加したりしましょう。

ソースの取得

ソースを保存したいディレクトリに移動しdepot_tools内のfetchを使い、ソースを持ってくる。この際デフォルトではバージョン履歴がついてくるが無くすと時間を短縮できるので--no-historyオプションを推奨します。

$ fetch --nohooks --no-history chromium

これには早くても15分ほどはかかります。ソースコードのcheckoutが完了するとsrcができているので移動する。

$ cd src

続いてUbuntuの場合、依存性を解決してくれるシェルスクリプトが用意されているので実行する。

$ sudo build/install-build-deps.sh

hooksを実行する準備ができたのでパッケージを入手。

$gclient runhooks

これでビルド準備は完了です。

ninjaでビルド

depot_tools内のninjaツールを使ってビルドしていきます。
ninjaはC++ベースで作られているオープンソースのビルドツールで...詳細は公式サイト。

Ninja, a small build system with a focus on speed

まずビルドのためにディレクトリを作成します。

$ gn gen out/Default

Defaultを任意に書き換えることでビルド環境を分けられる。
このままビルドすることもできるがいくつかビルドオプションを加えることでビルド時間を短縮できる。

$ gn args out/Default

実行するとvimが起動するのでオプションを改行区切りで記述する。
vimを普段使わない人向けに書くと、Insertで入力を始め、保存するときにはEscを押して入力を離脱したあと:wqと打ちEnterを押すと上書き保存&終了することができます。
その際の内容はout/Default/args.gnに保存されるのであとから変更したいときはそこを変更すればいい。

以下、おすすめするオプションをご紹介。

Jumbo build

use_jumbo_build=true

複数のソースファイルを一緒にコンパイルする。公式によるとChromiumはヘッダファイルが共通してるソースが多いから早くなるらしい。よくわからないけど実際早くなる。
Jumbo buildに関して詳しく知りたい人はこっち。 Jumbo / Unity builds

NaClの無効化

enable_nacl=false

多くの場合NaCl(Native Client)はなくても問題ない。無効化しちゃおう。
Welcome to Native Client - Google Chrome

他にデバッグシンボル系が多く存在するが今回はデバッグもしたいのでいじらない。 ビルドオプションに凝りたい人は公式サイトを読んでみよう。
www.chromium.org

ついにビルド

$ autoninja -C out/Default chrome

chromiumのビルドだけど名前はchromeなので間違えないようにね。
早くても2時間ほどはかかるので気長に待ちましょう。

とりあえず実行してみよう

$ out/Default/chrome

warningがたくさん出るかもしれないが無事に起動すればビルドは成功。
f:id:glycelery:20181024162804p:plain