「Google Lensで画像を検索」機能の呼び出し過程を追う
https://gyazo.com/991fafcb8b8b0f767b45e86de22a1982
ブラウザの右パネルを活用し始めた傾向がみられ、このUIも気になるのでコードを読んでいく daiiz.icon
画像上でコンテキストメニューがクリックされた後、どういう流れを経て右パネルで検索結果が表示されるか
予想 daiiz.icon
タブのスクリーンショットを撮る
画像の領域情報を保持する
正解 (現時点での理解)
コンテキストメニューがクリックされた画像ノードを取得する
画像のビットマップからPNG形式のサムネイル画像をつくる
画像データそのものがGoogle Lens APIに渡される
未整理の調査メモ
「lens」で検索してみる
components/lens/lens_features.cc
おなじみのkで始まる定数の宣言
https://gyazo.com/4fdb61a6e79de8e390fd5436fbf86fe9
enable-side-panel
components/lens/lens_entrypoints.cc
GetLensQueryParametersMap(lens::EntryPoint ep, bool is_side_panel_request)
エントリポイントとサイドパネルの有効化状況に応じてQueryParams Mapを組み立てる
https://gyazo.com/2c6cc91d70b6475ac7b8984a31382b62
https://gyazo.com/d4cb0cf3b2440f9041001a750e9b58c8
kStartTimeQueryParameter: st
base::Time::Now().ToJavaTime();
kChromeSearchWithGoogleLensContextMenuItem: "ccm"
オプションを与えているだけで画像や領域情報は含まれていない
AppendOrReplaceQueryParametersForLensRequest内部で呼び出される
「AppendOrReplaceQueryParametersForLensRequest」で検索
気になる
chrome/browser/ui/views/lens/lens_side_panel_controller.cc
chrome/browser/ui/views/side_panel/lens/lens_unified_side_panel_view.cc
chrome/browser/ui/views/lens/lens_side_panel_controller.cc
void LensSidePanelController::LoadResultsInNewTab()
Open the latest URL visible on the side panel. This accounts for when the user uploads an image to Lens via drag and drop. This also allows any region selection changes to transfer to the new tab.
たぶんこのボタンが押されたときの挙動だ
https://gyazo.com/869b7da43e1f9c6bc18418f011234b99
今回深堀りしたい場所ではないので一旦撤退
コンテキストメニューから追っていく必要がある?
https://gyazo.com/ab2b81bdfced34c09e5b62a005120d66
「で画像を検索」で検索
chrome/app/resources/generated_resources_ja.xtb
https://gyazo.com/8bb231ed017b5142f8a16b3d25382e97
「VISUAL_SEAERCH_PROVIDER」
components/lens/lens_features.cc
Enables using Google as the visual search provider instead of Google Lens.
Google Lensの代わりにGoogleを使うオプション
https://gyazo.com/e25f2600b467c773ad291a6d6d5b3be7
関係ない
components/lens/lens_features.cc
https://gyazo.com/8491fabaeca8f35061052b5bab7f023d
chrome/browser/ui/tab_contents/core_tab_helper.cc
https://gyazo.com/f1fd1f8c6783213084cdb18c64d02752
chrome/browser/ui/tab_contents/core_tab_helper.h
https://gyazo.com/9c289bfb63e9f14e57eb85785825ab93
https://gyazo.com/1a7b7d4469bf0b3c243e6131b52d2f9f
DoSearchByImageInNewTab (chrome/browser/ui/tab_contents/core_tab_helper.cc)
Handles the image thumbnail for the context node, composes a image search request based on the received thumbnail and opens the request in a new tab.
https://gyazo.com/65ae72cec173aee409c3662631f1df8b
search_args.image_thumbnail_content に検索対象の画像データが格納されていそう
components/search_engines/template_url.h にもそれらしいコメントがある
https://gyazo.com/7d4004bee975ce64edae104295c69add
search_args.image_thumbnail_content はどうやって作られる?
DoSearchByImageInNewTab関数の引数として const std::vector<uint8_t>& thumbnail_data が渡されている
この時点ですでに領域でのクロップは済んでいるはず?
PostContentToURL (chrome/browser/ui/tab_contents/core_tab_helper.cc)
https://gyazo.com/004be966f4911368172108332b13e004
Google Chrome Brandingの場合のみSidePanelにLensのリクエストを表示する
EdgeやBraveなどChrome以外のChromium製のブラウザでは使えない?
最終的にどちらかの下記の関数のどちらかでURLを開く
lens::OpenLensSidePanel(chrome::FindBrowserWithWebContents(web_contents()), open_url_params);
web_contents()->OpenURL(open_url_params);
修行が足りずこの2つの関数はどちらも全体像が見えてこない daiiz.icon
lens::OpenLensSidePanel
chrome/browser/ui/lens/lens_side_panel_helper.h
https://gyazo.com/208a8fac730f6f259c68ba9e33bda8d7
chrome/browser/ui/views/lens/lens_side_panel_helper.cc
https://gyazo.com/4a6d2d7fca4c24374d6ad7379ff64f4f
OpenWithURL(url_params) も見ておくか
browser_view->lens_side_panel_controller()->OpenWithURL(url_params)
browser_view->lens_side_panel_controller()
https://gyazo.com/59a0f7de838b6427ee6aeba831bc6dbc
chrome/browser/ui/views/lens/lens_side_panel_controller.h
https://gyazo.com/e2bb1f65ab7faafaa34b2285f8b2b5e8
chrome/browser/ui/views/lens/lens_side_panel_controller.cc
https://gyazo.com/52b702e5c320e18e7238ae652a6d145b
最後の LoadURLWithParams() も見る
side_panel_view_->GetWebContents()->GetController().LoadURLWithParams
content/browser/renderer_host/navigation_controller_impl.cc
https://gyazo.com/0609541e96a50cf11a89850ec21b791b
→ NavigateWithoutEntry(params)
SearchWithLensInNewTab (chrome/browser/ui/tab_contents/core_tab_helper)
https://gyazo.com/7e1687d465c4bee1522c6cd5fb08c312
https://gyazo.com/86e1dc008f1e4cbce2a5baef44f8ae80
SearchByImageInNewTabImpl
https://gyazo.com/7aabe02e432fba29d779afe4d7a08044
→ thumbnail_capturer_proxy->RequestImageForContextNode を介して、DoSearchByImageInNewTabが実行されるぽい
BindOnceとは?
難しそう。Passing Parameters As A unique_ptrの例と近いことやっている?
RequestImageForContextNode (chrome/common/chrome_render_frame.mojom)
https://gyazo.com/76c5793c11979172d919805c6cfccd79
実装は chrome/renderer/chrome_render_frame_observer.cc ?
code:cc
void ChromeRenderFrameObserver::RequestImageForContextNode(
int32_t thumbnail_min_area_pixels,
const gfx::Size& thumbnail_max_size_pixels,
chrome::mojom::ImageFormat image_format,
RequestImageForContextNodeCallback callback) {
SkBitmapとか出てきているのでたぶんSKIA 完全にレンダリング層に来てしまった?
https://gyazo.com/7b2a8c326e678755b55386487c7e2fc0
大雑把な流れ
WebNode context_node = render_frame()->GetWebFrame()->ContextMenuImageNode();
WebElement web_element = context_node.To<WebElement>();
web_element.ImageContents()
SkBitmap image = web_element.ImageContents();
必要に応じてこれをDownScaleしたものがSkBitmap thumbnail
ImageContents関数読みたいな daiiz.icon
SkBitmap bitmap;
thumbnailを元にしてあれこれ経て作られる
必要に応じて要求されたフォーマットに変換する
std::vector<unsigned char> data;
https://gyazo.com/7df53ed4240ee109e1378d2156461cc8
browserプロセスに返すimage_dataができあがる
std::move(callback).Run(image_data, original_size, image_extension);
最後の行でoriginalSizeとともにcallbackに渡す
chrome/browser/lens/region_search/lens_region_search_controller.h
Creates and runs the drag and capture flow. When run, the user enters into a screenshot capture mode with the ability to draw a rectagular region around the web contents. When finished with selection, the region is converted into a PNG and sent to Lens.
領域のスクリーンショットがPNG画像としてLensに渡されることは分かった
drag操作を待ち受けるっぽいのでこれも違う?
画像の上で右クリックしたときに、その画像のバイナリデータを送るのではなく、タブのスクリーンショットを撮ってその画像の領域 (で切り抜いた結果?) をLens APIに渡している?daiiz.icon
違うっぽかった
普通にimageElmenentにアクセスできていた
components/lens/lens_entrypoints.h
https://gyazo.com/10dce096ba1685dab16c449cea83da58
CHROME_SEARCH_WITH_GOOGLE_LENS_CONTEXT_MENU_ITEM
LWDは何のことか分からない
chrome/browser/renderer_context_menu/render_view_context_menu.cc
https://gyazo.com/479b184a1abd4f67f870bbf911e9bd1e
chrome/browser/renderer_context_menu/render_view_context_menu.cc
https://gyazo.com/7be4773a969e4341c381a3dd5790113f
脱線
tools/metrics/actions/actions.xml 面白い
機能ごとにowner (担当開発者) が列挙されている
https://gyazo.com/f6e8a864b1911c28007c4e6a0c9d932d
commitをウォッチしておこう
説明も用意されているのでこのファイルを眺めるだけで実験中の機能とかも把握できるのではないか
機能が実行されたことを記録している
https://gyazo.com/f1ab82ab5b2f7a064acd3aae3af411da
chrome/browser/ui/browser_finder.cc
WebContent == タブ的なニュアンスなのかな
https://gyazo.com/9da6facc71268afc3c9cdf313499333c
web_contents()->OpenURL()
実装はcontent/browser/web_contents/web_contents_impl.ccにある
web_contents()->OpenURL()
content/browser/web_contents/web_contents_impl.cc
https://gyazo.com/92c48ee9383b3b39d151692b3c019e0b
→ LoadURLWithParams()
NavigationControllerImpl::NavigateWithoutEntry
content/browser/renderer_host/navigation_controller_impl.cc
長い
→ CreateNavigationRequestFromLoadParams
CreateNavigationRequestFromLoadParams
content/browser/renderer_host/navigation_controller_impl.cc
https://gyazo.com/702faa63fa82631c73d695aad0bea819
params.post_dataに格納されているPOSTしたいデータもここで渡されている
またmojomだ