Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making Custom Browser

dynamis
February 08, 2019

Making Custom Browser

DroidKaigi 2019 の「カスタムブラウザの作り方 ー 実例から学ぶ Chrome と Firefox のカスタムビルド開発 ー」で使用したスライドです。
https://droidkaigi.jp/2019/timetable/70785

dynamis

February 08, 2019
Tweet

More Decks by dynamis

Other Decks in Technology

Transcript

  1. about:me Tomoya ASAI - dynamis webdino.org CTO Tech Speaker dynamis

    @ Community Twitter: @dynamitter facebook.com/dynamis I LOVE Firefox = Red Panda = Petit Panda = Lesser Panda 2 @
  2. about: WebDINO Japan Web, Browser, Open ( : ) (Chromium,

    Firefox ) ( : Gecko ) Web & Open Web IoT 2017 : Mozilla Japan WebDINO Japan https://www.webdino.org/ 3
  3. about: WebDINO Japan Web, Browser, Open ( : ) (Chromium,

    Firefox ) ( : Gecko ) Web & Open Web IoT 2017 : Mozilla Japan WebDINO Japan https://www.webdino.org/ 4
  4. Today's Topics Why Custom Browsers Firefox Building Firefox Customizing Firefox

    Chromium Building Chromium Customizing Chromium Conclusion 5
  5. Firefox for Android hg clone https://hg.mozilla.org/mozilla-central cd mozilla-central # mercurial

    をどうしても使いたくない場合は git ミラーから: # git clone https://github.com/mozilla/gecko- dev.git; cd gecko-dev # 開発環境のセットアップ ./mach bootstrap # ビルド、パッケージ作成、インストール、起動 ./mach build # artifact モードの場合は ./mach build mobile/android ./mach package ./mach install ./mach run https://developer.mozilla.org/docs/Mozilla/Developer_Guide/Build_Documentation/Simple_Firefox_for_Android_build 15
  6. ( ) mozcon g # Firefox for Android をビルドする: ac_add_options

    --enable-application=mobile/android ac_add_options --target=arm-linux-androideabi # Android SDK/NDK のパスをフルパスで設定: ac_add_options --with-android-sdk="/absolute/path/ to/.mozbuild/android-sdk" ac_add_options --with-android-ndk="/absolute/path/ to/.mozbuild/android-ndk-r11c" # ビルド結果の出⼒ディレクトリ: mk_add_options MOZ_OBJDIR=./objdir-droid https://developer.mozilla.org/docs/Mozilla/Developer_Guide/Build_Documentation/Simple_Firefox_for_Android_build 16
  7. Artifact mozcon g # Firefox for Android をビルドする: ac_add_options --enable-application=mobile/android

    ac_add_options --target=arm-linux-androideabi # Android SDK のパスをフルパスで設定 (NDK 不要): ac_add_options --with-android-sdk="/absolute/path/ to/.mozbuild/android-sdk" # Artifact モードでのビルドを指定: ac_add_options --enable-artifact-builds # ビルド結果の出⼒ディレクトリ: mk_add_options MOZ_OBJDIR=./objdir-frontend https://developer.mozilla.org/docs/Mozilla/Developer_Guide/Build_Documentation/Simple_Firefox_for_Android_build 17
  8. ( ) # まずは英語単⼀ロケールビルドを作成 ./mach build ./mach package # 各⾔語のファイルを⽣成

    export MOZ_CHROME_MULTILOCALE="ja zh-TW" for AB_CD in $MOZ_CHROME_MULTILOCALE; do ./mach build chrome-$AB_CD done # マルチロケールビルドとしてリパッケージ AB_CD=multi ./mach package Firefox 52 20
  9. mozharness # 対象リリースブランチのファイルをクローンして mozconfig を⽤意 hg clone https://hg.mozilla.org/releases/mozilla-esr60/ mozilla-central #

    対象リリースブランチの mozconfig と mozharness 設定テンプレを⼿元にコピー cp mozilla-central/mobile/android/config/mozconfigs/android-api-16/ l10n-nightly mozconfig cp mozilla-central/testing/mozharness/configs/developer_config.py config.py # 設定ファイルを編集。mozconfig は依存先にも注意。作りたいビルド設定を参考に書き換え: # mozharness/configs/multi_locale/mozilla-release_android.json nano mozconfig nano config.py # ⾔語リソースファイルを取得 mozilla-central/testing/mozharness/scripts/multil10n.py --cfg config.py --pull-build-source # ここでカスタマイズしたい内容に応じて各ファイルを編集 # ビルド (ビルド、英語版パッケージ、ロケール追加、マルチロケールビルド) を実⾏! mozilla-central/testing/mozharness/scripts/multil10n.py --cfg config.py 24
  10. ...

  11. Firefox (Yahoo, Yandex...) PC ( ...) FireTV UI Google FireTV

    YouTube YouTube Firefox ( Silk) Note: Android YouTube Google Firefox for FireTV: https://github.com/mozilla-mobile/firefox-tv 27
  12. : Firefox OS VIERA Firefox OS "My Home Screen" Firefox

    OS Firefox UK "powered by Firefox OS" "OS" AOSP Panasonic FreeBSD FxOS "OS" https://medium.com/@bfrancis/the-legacy-of-firefox-os-c58ec32d94f0 28
  13. Distribution Files ( ) { "Preferences": { "general.useragent.device_string": "XXXXXX %DEVICEID%

    Build/ Xxxxxx%DEVICEID%", "general.useragent.use_device": true }, "ApplicationPreferences": { "newtab.load_homepage": true }, "AndroidPreferences": { "distribution.read_partner_bookmarks_provider": true, "distribution.read_partner_customizations_provider": true, "homepage": "http://home.att.com", "suggestedSites.hidden": "https://www.xxxxxx.xxx/", "distribution.set_as_homepage": true, "startpane_enabled": false } } preferences.json 30
  14. : User Agent User Agent i-mode Firefox 41 OS (

    Top100+ ) UA nger printing https://developer.mozilla.org/ja/docs/Web/HTTP/Gecko_user_agent_string_reference 31
  15. Chromium for Android Firefox 4 5 200 300GB Firefox Artifact

    Google Corei7-4770 (3.9GHz 4core) 16GB HDD 駄 1 5 36
  16. Chromium Firefox CPU arch 1 (~2) API level 1 


    (arm64 ) Chromium CPU arch 2 API level 3 
 (x86 arch 3 ) 4-5 x 6 20-30 37
  17. UI UI C 翻 ( ) unsigned 64bit md5 ID

    ... https://ftagada.wordpress.com/2011/01/08/chromium-translations-explained-part-1/ 38
  18. Chromium #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" Item(IDS_PREFERENCES) Mac ( Android ...

    ) 39 <translation id="4345587454538109430">設定...</translation> chrome/app/resources/generated_resources_ja.xtb chrome/browser/ui/cocoa/main_menu_builder.mm chrome/app/generated_resources.grd <message name="IDS_PREFERENCES" desc="The Mac menu item to open the preferences window in the app menu."> Preferences... </message>
  19. Chrome i18n GRIT GRIT https://www.chromium.org/developers/tools- we-use-in-chromium/grit https://cs.chromium.org/chromium/src/tools/ grit/ OSS console

    (server) Google https://ftagada.wordpress.com/2011/01/08/chromium-translations-explained-part-1/ 40
  20. OSS

  21. ...

  22. Chromium # まずはツールクローンしてパスを通す git clone https://chromium.googlesource.com/ chromium/tools/depot_tools.git export PATH="$PATH:/path/to/depot_tools" mkdir

    ~/chromium && cd ~/chromium fetch --nohooks android # gn は configure のようなもの gn gen --args='target_os="android" is_chromecast=true' out/Default # ninja は make のようなもので auto は並列数 -j 調整 autoninja -C out/Default chrome_public_apk https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md 43
  23. # Make sure you are in 'src'. # This part

    should only need to be done once, but it won't # hurt to repeat it. (...以下略...何⾔ってんだこいつw) gclient sync --with_branch_heads --with_tags # You may have to explicitly 'git fetch origin' to pull branch-heads/ git fetch # Checkout the branch 'src' tree. git checkout -b branch_$BRANCH branch-heads/$BRANCH # Checkout all the submodules at their branch DEPS revisions. gclient sync --with_branch_heads --with_tags https://www.chromium.org/developers/how-tos/get-the-code/working-with-release-branches 44
  24. : VideoMark Browser http://vm.webdino.org/ Paravi, TVer, YouTube Chromium API (

    ) : https://github.com/videomark/videomark-browser 47 https://urls.jp/vm
  25. VM 48 ֶज़ݚڀ༻σʔλ
 ΍ௐࠪ෼ੳ݁ՌΛ
 Ұൠެ։ ૹ৴ ʲΫϥΠΞϯτ৘ใʳ w ୺຤छผ
 1$PSϞόΠϧ

     w ϒϥ΢βόʔδϣϯ w 04όʔδϣϯ౳ ஫ࢯ໊ɾॅॴ౳ͷݸਓ ಛఆ৘ใ͸ؚ·ͳ͍
 6TFS"HFOU͔Β൑அ ʲωοτϫʔΫ৘ใʳ w ௨৴ࣄۀࣾɾ*41 w ஍Ҭ ౎ಓ෎ݝ ౳ ஫ૹ৴ݩ*1ΞυϨεΛ ಗ໊Խ ຤ඌΦΫςοτ ࡟আ ޙʹ(FP*1Ͱਪఆ ʲ࠶ੜ඼࣭ύϥϝʔλʳ w ಈը৘ใϏοτϨʔτɺ ղ૾౓ɺϑϨʔϜϨʔτ౳ w ࠶ੜ৘ใ࠶ੜͷதஅɺόο ϑΝϦϯά౳ w ૢ࡞৘ใಈըͷγʔΫɺ Ұ࣌ఀࢭɾ࠶։౳ 8FC7JEFP.BSL֦ுػೳ΍ϒϥ΢βʔͰࢹௌ৘ใΛऔಘ ࢹௌͨ͠ಈըͷ ମײ඼࣭ 2P& Λ dͷ਺஋ͱͯ͠ ϑΟʔυόοΫ ಈըαʔϏεͷ ਪఆମײ඼࣭஋ 2P& 2VBMJUZPG&YQFSJFODF ಈը഑৴αʔϏεɾ $%/αʔόʔ 8FC 7JEFP.BSL αʔόʔ ࢹௌ৘ใΛ෼ੳ ௨৴ࣄۀऀɾ*41 αʔϏεվળ༻ʹ ௐࠪσʔλΛఏڙ ར༻ऀͷ ϒϥ΢βʔ ʂ ಈըࢹௌ࣌ͷ 2P&Λ֬ೝ ϓϥΠόγʔอޢॲཧ ֶज़ݚڀ༻σʔλ࡞੒ ಈը഑৴αʔϏε΁ΞΫηε )5.-ɺಈըϑΝΠϧ౳Λड৴ ಗ໊Խॲཧ
  26. # chrome/renderer/chrome_content_renderer_client.cc # ここで実⾏してください的なコードがあちこちにある: void ChromeContentRendererClient::RunScriptsAtDocumentEnd( content::RenderFrame* render_frame) { #if

    BUILDFLAG(ENABLE_EXTENSIONS) ChromeExtensionsRendererClient::GetInstance()- >RunScriptsAtDocumentEnd( render_frame); // |render_frame| might be dead by now. #endif # ここでコード挿⼊関数を呼び出そう! # InjectScript(render_frame) } https://cs.chromium.org/chromium/src/chrome/renderer/chrome_content_renderer_client.cc 51
  27. ( ) void InjectScript(content::RenderFrame* render_frame) { WebLocalFrame* frame = render_frame->GetWebFrame();

    GURL url = GURL(frame->GetDocument().Url()); if (render_frame->IsMainFrame()) { base::StringPiece source_piece = ui::ResourceBundle::GetSharedInstance() .GetRawDataResource(IDR_CONTENT_JS); base::StringPiece injector = ui::ResourceBundle::GetSharedInstance() .GetRawDataResource(IDR_INJECT_JS); std::string source = base::ReplaceStringPlaceholders(injector, std::vector<std::string>{source_piece.as_string()}, nullptr); blink::WebScriptSource source_in = blink::WebScriptSource(WebString::FromUTF8(source.data(), source.size())); frame->ExecuteScript(source_in); } } https://github.com/videomark/videomark-browser/blob/master/inject_sodium.diff 52
  28. ( ) // 先ほどの IDR_INJECT_JS の中⾝ let target = document.getElementsByTagName("body")

    [0]; let script = document.createElement("script"); script.setAttribute("type", "text/javascript"); // IDR_CONTENT_JS を script タグの中⾝に突っ込む script.innerText = "$1"; target.appendChild(script); // Web ページのコンテキストでコードを実⾏させる https://github.com/videomark/videomark-browser/blob/master/inject_sodium.diff 53
  29. Thank You! Any Questions? Feel free to contact me: dynamis

    webdino.org
 @dynamitter, facebook.com/dynamis Slide Upload: speakerdeck.com/dynamis by @4687koSourijun @