Android Chromium 沉浸式地址栏

地址栏是如何与网页联动的

地址栏在chromium内核中只是一个虚拟的概念,通过Android的开发者模式来观察Chrome浏览器的地址栏我们会发现,地址栏是一个原生的控件,他与网页是无关的,chromium在内核中根据用户的滑动手势,动态的调整网页viewport的偏移同时将偏移位置通知到应用层,应用层基于此偏移动态的调整地址栏控件的偏移位置(margin or translation)从而达到地址栏与网页根据用户手势沉浸式联动的效果。

BrowserControlsOffsetManager是内核中地址栏概念的管理类,它的主要职责有:

markdown 复制代码
1. 管理当前地址栏的模式(仅显示、仅隐藏、自动)
2. 根据网页滑动事件计算当前地址栏的偏移
3. 当用户手势抬起后决定是否启用动画展示或者隐藏地址栏

网页滑动时代码处理流程如下:

plaintext 复制代码
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Renderer |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
viewport.ScrollBy
  |-->ShouldBrowserControlsConsumeScroll [If Result True]
    |-->ScrollBrowserControls
      |-->host_impl_->browser_controls_manager()->ScrollBy
        |-->BrowserControlsOffsetManager.ScrollBy [Compute Scroll Delta For TopControls]

BrowserControlsOffsetManager依据网页滚动计算偏移用于:
1、通知偏移值到Browser,从而通知地址栏更新位置
2、记录偏移值,再松手后决定是显示还是隐藏地址栏

自动动画显示或者隐藏时代码处理流程如下:

收到滑动事件结束后BrowserControlsOffsetManager准备动画,在下一帧绘制时重新计算偏移

plaintext 复制代码
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Renderer |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BrowserControlsOffsetManager.ScrollEnd
  |-->StartAnimationIfNecessary
  |-->SetupAnimation

在Render收到绘制指令时BrowserControlsOffsetManager通过动画插值器计算偏移,同时根据动画状态决定是否继续触发下一次绘制

plaintext 复制代码
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Renderer |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SynchronousCompositorProxy.BeginFrame
  |-->SynchronousLayerTreeFrameSink.BeginFrame
    |-->viz::ExternalBeginFrameSource[begin_frame_source.cc].onBeginFrame
      |-->FilterAndIssueBeginFrame
        |-->BeginFrameObserver.OnBeginFrame
        |-->BeginFrameObserBase[extends BeginFrameObserver].OnBeginFrame
          |-->BeginFrameObserBase[begin_frame_source.cc].OnBeginFrameDerivedImpl
          |-->Scheduler[extends BeginFrameObserverBase].OnBeginFrameDerivedImpl
            |-->BeginImplFrameSynchronous
              |-->BeginImplFrame
                |-->SchedulerClient.WillBeginImplFrame
                |-->ProxyImpl[extends SchedulerClient].WillBeginFrame
                  |-->LayerTreeHostImpl.WillBeginImplFrame
                    |-->Animate
                      |-->AnimateInternal
                        |-->AnimateBrowserControls
                          |-->BrowserControlsOffsetManager.Animat [计算偏移]
                          |-->viewport.ScrollBy [滚动网页窗口]

基于Chromium内核实现一个地址栏

前面说了BrowserControlsOffsetMnanager管理了地址栏的偏移,那么他是如何通知到Android层的呢,代码流程如下:

plaintext 复制代码
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Renderer |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SynchronousCompositorProxy.DemandDrawHwAsync [Browser发起绘制]
  |-->DemandDraw
    |-->SynchronousLayerTreeFrameSink.DemandDrawHw
      |-->InvokeComposite
        |-->LayerTreeFrameSinkClient.onDraw
        |-->LayerTreeHostImpl[extends LayerTreeFrameSinkClient].onDraw
          |-->LayerTreeHostImplClient.OnDrawForLayerTreeFrameSink
          |-->ProxyImpl[extends LayerTreeHostImplClient].OnDrawForLayerTreeFrameSink
            |-->Scheduler.OnDrawForLayerTreeFrameSink
              |-->OnBeginImplFrameDeadline
                |-->ProcessScheduledActions
                  |-->DrawIfPossible
                    |-->SchedulerClient.ScheduledActionDrawIfPossible
                    |-->ProxyImpl[extends SchedulerClient].ScheduledActionDrawIfPossible
                      |-->DrawInternal
                        |-->LayerTreeHostImpl.DrawLayers
                          |-->GenerateCompositorFrame
                            |-->MakeRenderFrameMetadata [设置最新的地址栏偏移参数]
                            |-->RenderFrameMetadataObserver.OnRenderFrameSubmission
                            |-->RenderFrameMetadataObserverImpl[extends RenderFrameMetadataObserver].OnRenderFrameSubmission
                              |-->cc::mojom::blink::RenderFrameMetadataObserverClient.OnRenderFrameMetadataChanged [IPC调用,通知Browser] ----|
                                                                                                                                            |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Browser |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                   |
                                                                                                                                            |
RenderFrameMetadataProviderImpl.OnRenderFrameMetadataChanged ---------------------------------mojom-----------------------------------------|
  |-->RenderFrameMetadataProvider::Observer.OnRenderFrameMetadataChangedBeforeActivation
  |-->RenderWidgetHostViewAndroid[extends RenderFrameMetadataProvider::Observer].OnRenderFrameMetadataChangedBeforeActivation
    |-->UpdateControls [按需更新地址栏偏移]
      |-->ViewAndroid.OnTopControlsChanged
        |-->Java_ViewAndroidDelegate_onTopControlsChanged
        |-->ViewAndroidDelegate.onTopControlsChanged [通知到Java端]

因此想要实现一个自己的地址栏效果,我们只需要根据ViewAndroidDelgate中的onTopControlsChanged偏移参数,动态的调整地址栏的偏移

至此,我们了解了地址栏的生效流程,并且也可以基于此完成一个基于chromium内核的定制化地址栏,需要注意一点的是它的设计仅仅是与chromium或者chrome的整体架构兼容的,原生的地址栏偏移通知是滞后一帧的,针对这种情况我们只需要在做偏移的时候,从内核中同步取出准确的地址栏偏移即可,同时还需要处理好事件分发时的坐标偏移。

相关推荐
知花实央l7 小时前
【Web应用实战】 文件上传漏洞实战:Low/Medium/High三级绕过(一句话木马拿webshell全流程)
前端·学习·网络安全·安全架构
华仔啊7 小时前
JavaScript + Web Audio API 打造炫酷音乐可视化效果,让你的网页跟随音乐跳起来
前端·javascript
鸡吃丸子7 小时前
SEO入门
前端
檀越剑指大厂8 小时前
【Nginx系列】Tengine:基于 Nginx 的高性能 Web 服务器与反向代理服务器
服务器·前端·nginx
是你的小橘呀8 小时前
深入理解 JavaScript 预编译:从原理到实践
前端·javascript
uhakadotcom8 小时前
在使用cloudflare workers时,假如有几十个请求,如何去控制并发?
前端·面试·架构
风止何安啊8 小时前
栈与堆的精妙舞剧:JavaScript 数据类型深度解析
前端·javascript
用户47949283569158 小时前
Chrome DevTools MCP:让 AI 助手直接操作浏览器开发工具
前端·javascript·chrome
Rysxt_8 小时前
Vuex 教程 从入门到实践
前端·javascript·vue.js
by__csdn9 小时前
Node.js版本与npm版本的对应关系
前端·npm·node.js