123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "weblayer/browser/browser_controls_navigation_state_handler.h"
- #include "base/feature_list.h"
- #include "build/build_config.h"
- #include "components/security_state/content/content_utils.h"
- #include "components/security_state/core/security_state.h"
- #include "content/public/browser/navigation_controller.h"
- #include "content/public/browser/navigation_entry.h"
- #include "content/public/browser/navigation_handle.h"
- #include "content/public/browser/render_frame_host.h"
- #include "content/public/browser/render_process_host.h"
- #include "content/public/browser/render_widget_host.h"
- #include "content/public/browser/render_widget_host_view.h"
- #include "content/public/browser/web_contents.h"
- #include "content/public/common/url_constants.h"
- #include "weblayer/browser/browser_controls_navigation_state_handler_delegate.h"
- #include "weblayer/browser/controls_visibility_reason.h"
- #include "weblayer/browser/weblayer_features.h"
- namespace weblayer {
- namespace {
- // The time that must elapse after a navigation before the browser controls can
- // be hidden. This value matches what chrome has in
- // TabStateBrowserControlsVisibilityDelegate.
- base::TimeDelta GetBrowserControlsAllowHideDelay() {
- if (base::FeatureList::IsEnabled(kImmediatelyHideBrowserControlsForTest))
- return base::TimeDelta();
- return base::Seconds(3);
- }
- } // namespace
- BrowserControlsNavigationStateHandler::BrowserControlsNavigationStateHandler(
- content::WebContents* web_contents,
- BrowserControlsNavigationStateHandlerDelegate* delegate)
- : WebContentsObserver(web_contents), delegate_(delegate) {}
- BrowserControlsNavigationStateHandler::
- ~BrowserControlsNavigationStateHandler() = default;
- bool BrowserControlsNavigationStateHandler::IsRendererControllingOffsets() {
- if (IsRendererHungOrCrashed())
- return false;
- return !web_contents()->GetPrimaryMainFrame()->GetProcess()->IsBlocked();
- }
- void BrowserControlsNavigationStateHandler::DidStartNavigation(
- content::NavigationHandle* navigation_handle) {
- is_crashed_ = false;
- if (navigation_handle->IsInPrimaryMainFrame() &&
- !navigation_handle->IsSameDocument()) {
- forced_show_during_load_timer_.Stop();
- SetForceShowDuringLoad(true);
- }
- }
- void BrowserControlsNavigationStateHandler::DidFinishNavigation(
- content::NavigationHandle* navigation_handle) {
- if (navigation_handle->IsInPrimaryMainFrame()) {
- if (!navigation_handle->HasCommitted()) {
- // There will be no DidFinishLoad or DidFailLoad, so hide the topview
- ScheduleStopDelayedForceShow();
- }
- delegate_->OnUpdateBrowserControlsStateBecauseOfProcessSwitch(
- navigation_handle->HasCommitted());
- }
- }
- void BrowserControlsNavigationStateHandler::DidFinishLoad(
- content::RenderFrameHost* render_frame_host,
- const GURL& validated_url) {
- if (render_frame_host->IsInPrimaryMainFrame())
- ScheduleStopDelayedForceShow();
- }
- void BrowserControlsNavigationStateHandler::DidFailLoad(
- content::RenderFrameHost* render_frame_host,
- const GURL& validated_url,
- int error_code) {
- if (render_frame_host->IsInPrimaryMainFrame()) {
- ScheduleStopDelayedForceShow();
- UpdateState();
- }
- }
- void BrowserControlsNavigationStateHandler::DidChangeVisibleSecurityState() {
- UpdateState();
- }
- void BrowserControlsNavigationStateHandler::PrimaryMainFrameRenderProcessGone(
- base::TerminationStatus status) {
- is_crashed_ = true;
- UpdateState();
- }
- void BrowserControlsNavigationStateHandler::OnRendererUnresponsive(
- content::RenderProcessHost* render_process_host) {
- UpdateState();
- }
- void BrowserControlsNavigationStateHandler::OnRendererResponsive(
- content::RenderProcessHost* render_process_host) {
- UpdateState();
- }
- void BrowserControlsNavigationStateHandler::SetForceShowDuringLoad(bool value) {
- if (force_show_during_load_ == value)
- return;
- force_show_during_load_ = value;
- UpdateState();
- }
- void BrowserControlsNavigationStateHandler::ScheduleStopDelayedForceShow() {
- forced_show_during_load_timer_.Start(
- FROM_HERE, GetBrowserControlsAllowHideDelay(),
- base::BindOnce(
- &BrowserControlsNavigationStateHandler::SetForceShowDuringLoad,
- base::Unretained(this), false));
- }
- void BrowserControlsNavigationStateHandler::UpdateState() {
- const cc::BrowserControlsState renderer_availability_state =
- CalculateStateForReasonRendererAvailability();
- if (renderer_availability_state != last_renderer_availability_state_) {
- last_renderer_availability_state_ = renderer_availability_state;
- delegate_->OnBrowserControlsStateStateChanged(
- ControlsVisibilityReason::kRendererUnavailable,
- last_renderer_availability_state_);
- }
- const cc::BrowserControlsState other_state = CalculateStateForReasonOther();
- if (other_state != last_other_state_) {
- last_other_state_ = other_state;
- delegate_->OnBrowserControlsStateStateChanged(
- ControlsVisibilityReason::kOther, last_other_state_);
- }
- }
- cc::BrowserControlsState BrowserControlsNavigationStateHandler::
- CalculateStateForReasonRendererAvailability() {
- if (!IsRendererControllingOffsets() || web_contents()->IsBeingDestroyed() ||
- web_contents()->IsCrashed()) {
- return cc::BrowserControlsState::kShown;
- }
- return cc::BrowserControlsState::kBoth;
- }
- cc::BrowserControlsState
- BrowserControlsNavigationStateHandler::CalculateStateForReasonOther() {
- // TODO(sky): this needs to force SHOWN if a11y enabled, see
- // AccessibilityUtil.isAccessibilityEnabled().
- if (force_show_during_load_ || web_contents()->IsFullscreen() ||
- web_contents()->IsFocusedElementEditable()) {
- return cc::BrowserControlsState::kShown;
- }
- content::NavigationEntry* entry =
- web_contents()->GetController().GetVisibleEntry();
- if (!entry || entry->GetPageType() != content::PAGE_TYPE_NORMAL)
- return cc::BrowserControlsState::kShown;
- if (entry->GetURL().SchemeIs(content::kChromeUIScheme))
- return cc::BrowserControlsState::kShown;
- const security_state::SecurityLevel security_level =
- security_state::GetSecurityLevel(
- *security_state::GetVisibleSecurityState(web_contents()),
- /* used_policy_installed_certificate= */ false);
- switch (security_level) {
- case security_state::WARNING:
- case security_state::DANGEROUS:
- return cc::BrowserControlsState::kShown;
- case security_state::NONE:
- case security_state::SECURE:
- case security_state::SECURE_WITH_POLICY_INSTALLED_CERT:
- case security_state::SECURITY_LEVEL_COUNT:
- break;
- }
- return cc::BrowserControlsState::kBoth;
- }
- bool BrowserControlsNavigationStateHandler::IsRendererHungOrCrashed() {
- if (is_crashed_)
- return true;
- content::RenderWidgetHostView* view =
- web_contents()->GetRenderWidgetHostView();
- if (view && view->GetRenderWidgetHost() &&
- view->GetRenderWidgetHost()->IsCurrentlyUnresponsive()) {
- // Renderer is hung.
- return true;
- }
- return web_contents()->IsCrashed();
- }
- } // namespace weblayer
|