ふとChromeのアドレスバーにURLを入力した時にどんな処理(主にURL文字列の処理について)がされているのか気になったため、Chromiumを読むことにした
- とりあえず、まずBardに質問
- ぼく「Chromiumのソースコード内で、Omniboxにテキストが入力された時の処理が書かれている箇所を、ファイルパス及びその周辺のソースコードとともに示してください。なお、GitHub上にあるミラーリポジトリ(https://github.com/chromium/chromium)を参照してください」
- Chromeのアドレスバー兼検索欄はOmniboxと呼ばれる
- Bard「Chromium のソースコードで、Omnibox にテキストが入力されたときに処理される場所は次のとおりです。ファイル:
chrome/browser/ui/views/location_bar/location_bar.cc、関数:OnInputChanged()」
- ぼく「Chromiumのソースコード内で、Omniboxにテキストが入力された時の処理が書かれている箇所を、ファイルパス及びその周辺のソースコードとともに示してください。なお、GitHub上にあるミラーリポジトリ(https://github.com/chromium/chromium)を参照してください」
- 調べてみましたが、
location_bar.ccはありませんでした!いかがでしたか? - とりあえず似ている
location_bar_view.ccを見る- なんかOmniboxについての言及が多かったので、そっちのコードを読んだほうが良さそう
- なんでOmniboxにたどり着いたのかは忘れた
- なんかOmniboxについての言及が多かったので、そっちのコードを読んだほうが良さそう
omnibox_view_views.hに移動- 色々見てると
HandleAfterKeyEvent()が目に止まったomnibox_view_views.cc:327でEnterキーが押されたときの挙動を規定してそう- Altキーが押されていたら新しいタブで開くようにしている(知らなかった)
model()->AcceptInput()が呼ばれているmodel()が返すのはOmniboxEditModel*
- 色々見てると
omnibox_edit_model.cc:495に移動、OmniboxEditModel::AcceptInput()を読んでいくGetInfoForCurrentText()でなんかAutocompleteMatch型の変数matchを設定している- おそらくOmniboxに入力した時に出てくる候補とかの選択状況とかを確認し、選択中の候補に対応するURLを取得してそう
- 引数、参照じゃなくてポインタなんですね
popup_->IsOpen()かつquery_in_progress()っていかにもそれっぽい- これがfalseのときに使われている、
AutocompleteClassifierFactory::GetForProfile(profile_)->Classify()は何?- Autocomplete~は「Singleton that owns all AutocompleteClassifiers and associates them with Profiles」らしいです(
autocomplete_classifier_factory.h:15) 知るか- ProfileはChromeの機能で、ケバブメニュー(Omnibarがある行の一番右にある︙)の横、自分のGoogleアカウントのアイコンが表示されているところから管理できるアレ
- 内部で
AutoCompleteResultなるものを取得しており、これは「All matches from all providers for a particular query. This also tracks what the default match should be if the user doesn’t manually select another match」らしい(autocomplete_result.h:19) - ここで
view_->GetText()を呼んでおり、これによってOmniboxViewViewsのtextfield_->text()を取得しているtextfield_->SetText(text);を呼んでいるのはOmniboxViewViews::SetTextAndSelectedRange()で、これはvoid OmniboxViewViews::SetWindowTextAndCaretPos()から呼ばれている- CaretPosは「Omnibox 内のカーソルの位置を表す」らしい(By Bard)
- Bardは「構造体」って言ってるけどsize_t型なんだよなあ
- CaretPosは「Omnibox 内のカーソルの位置を表す」らしい(By Bard)
SetWindowTextAndCaretPos自体はgtkやcocoa等、実際のフロントエンド実装部分から呼び出されてそう あとOmniboxView::SetUserText()
- まあどうあれ、ポップアップから自動補完・履歴などの候補を選択していなければ、ユーザーの入力が用いられるという解釈で良いのではないか
- Autocomplete~は「Singleton that owns all AutocompleteClassifiers and associates them with Profiles」らしいです(
- おそらくOmniboxに入力した時に出てくる候補とかの選択状況とかを確認し、選択中の候補に対応するURLを取得してそう
match.destination_urlがvalidじゃなければreturndestination_urlはGURL型GoogleURL?pyautolib.iというファイルで定義されている?- Pythonとの連携?
pyauto.py内にそれらしきものはなかった
- Pythonとの連携?
- まあURLのバリデーションだろう
matchがURLを持っていると考えて良いのかな
view_->OpenMatch()で多分実際に開く処理を行っているview_はOmniboxViewで、OpenMatch()内部でmodel_->OpenMatch()を呼んでいる- で、この
model_はOmniboxEditModelというオチOmniboxEditModelからOmniboxViewのOpenMatch()を呼んだと思っていたら、いつの間にかOmniboxEditModelのOpenMatch()になっていた……
- で、この
omnibox_edit_model.cc:534に移動、OmniboxEditModel::OpenMatch()を読んでいく- とりあえず引数として渡された
matchはAcceptInput()でつくったものと同一だから、これを使っている箇所だけ見ていこう- 627行目あたりがそれっぽい?
- 拡張機能のURLを指定してたら
ExtensionAppProvider::LaunchAppFromOmnibox()という関数を呼んでる- 本質じゃないから雑にしか読んでないけど、 この関数の最後で
application_launch::OpenApplication()を呼んでいるらしい
- 本質じゃないから雑にしか読んでないけど、 この関数の最後で
- URLが拡張機能でない、即ち普通のURLであれば、
match.destination_urlからGURL型のオブジェクトdestination_urlを作成して、controller_->OnAutocompleteAccept()に渡す- またautocomplete?
controller_はOmniboxEditController*型- そういや今までの型においてポインタ無視してたかもしれない まあいっか
OnAutocompleteAccept()の定義元をVSCodeに探してもらうと、LocationBarView::OnAutocompleteAccept()が出てきたLocationBarViewはOmniboxEditControllerを継承しているLocationBarViewGtkも出てきたけど一旦無視
- 拡張機能のURLを指定してたら
- 627行目あたりがそれっぽい?
- とりあえず引数として渡された
location_bar_view.cc:1093のOnAutocompleteAccept()を見る- 第1引数が
OpenMatch()の最後で作られたdestination_urlと同じURLだと思うので、これが使われているところを見る - といっても、urlがvalidなら
location_input_に代入してるだけ- これは
string16型UTF8ToUTF16(url.spec())としてから代入している
- これは
- そしてその後、
command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL);という処理が!command_updater_はCommandUpdater*型
- 第1引数が
command_updater.cc:44のExecuteCommand()- 引数としてもらった
int idをそのままCommandUpdater::ExecuteCommandWithDisposition()に渡してその戻り値をreturnしてるだけCommandUpdater::ExecuteCommandWithDisposition()も、idに対応するコマンドが使えるかどうかを確認してから、delegate_->ExecuteCommandWithDisposition()を呼んでるdelegate_は `CommandUpdaterDelegate*ExecuteCommandWithDisposition()の定義はいくつかあって、どれもswitch文でidに対応するコマンドを呼び出している- 最もそれらしきものは
BrowserCommandControllerのもので、これ以外(simple_web_view_dialogだのpanelだの)はIDC_OPEN_CURRENT_URLに対応するコマンドを用意していない BrowserCommandControllerは、idがIDC_OPEN_CURRENT_URLのときbrowser_commands.cc@OpenCurrentURL()を呼んでいる
- 最もそれらしきものは
- 引数としてもらった
browser_commands.cc:353のOpenCurrentURL()- 引数に
Browser*型のbrowserを受け取る browser->window()->GetLocationBarでlocation_barを取得し、location_bar->GetInputString()で取得した文字列からGURL型のオブジェクトurlを作成しているGetInputString()はlocation_barのlocation_input_を返しているだけ- そう、
LocationBarView::OnAutocompleteAccept()で代入されていたメンバですね 伏線回収だ~~~- これは
OmniboxEditModel::OpenMatch()で作られたdestination_urlと同一で、こっちはOmniboxEditModel::AcceptInput()で作られたmatchをもとにしていた- そういえば結局この
matchがあんまりよく分かってないような気がする……
- そういえば結局この
- これは
urlなどをもとにNavigateParams型のオブジェクトを作り、Navigate()に渡す- 多分これでオープン処理してそう
- もう読むのやめて良いような気がするな
- 引数に
- (蛇足?)
browser_navigator.cc:390のNavigate()- 523行目で
LoadURLInContents()を呼び出していて、この直前に「Perform the actual navigation, tracking whether it came from the renderer」とのコメントがあった- 引数として渡しているもので気になるのは
params->target_contents->web_contents()とurl- 後者については、基本的に
params->url(つまりアドレスバーの中身だろうな)を代入している - ただし、それが空っぽだった場合、プロフィールを参照してホームページのURLに置き換えている
- 前者について、481行目あたりに
params->target_contents = chrome::TabContentsFactory(...)という処理がある- 第2引数(
content::SiteInstance)に渡すオブジェクトを作るためにurlを用いている(tab_util::GetSiteInstanceForNewTab(params->browser->profile(), url)) - このGetSiteなんちゃらをたどると
site_instance_impl.cc:241のGURL SiteInstanceImpl::GetSiteForURL()にたどり着くことが出来て、ここでurlからoriginを取ってきたりしてるらしいですよ
- 第2引数(
- 後者については、基本的に
- 引数として渡しているもので気になるのは
- 523行目で
とりあえずURL入力後の処理はおおよそ掴めたような気がするけど、気になるところも残ってはいる
matchの正体とURLバリデーション- Pythonのライブラリっぽさがありそう?
- 実際にfetchしてるところがどこなのか
SiteInstanceを辿ったら良いのかなあ