| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/content_settings/request_desktop_site_web_contents_observer_android.h" |
| |
| #include "base/android/build_info.h" |
| #include "base/command_line.h" |
| #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "components/content_settings/core/common/content_settings_utils.h" |
| #include "components/content_settings/core/common/pref_names.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/common/content_features.h" |
| #include "services/metrics/public/cpp/ukm_builders.h" |
| |
| namespace rds_web_contents_observer { |
| // Keep in sync with UserAgentRequestType in tools/metrics/histograms/enums.xml. |
| enum class UserAgentRequestType { |
| RequestDesktop = 0, |
| RequestMobile = 1, |
| }; |
| } // namespace rds_web_contents_observer |
| |
| RequestDesktopSiteWebContentsObserverAndroid:: |
| RequestDesktopSiteWebContentsObserverAndroid(content::WebContents* contents) |
| : content::WebContentsObserver(contents), |
| content::WebContentsUserData< |
| RequestDesktopSiteWebContentsObserverAndroid>(*contents) { |
| Profile* profile = |
| Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
| host_content_settings_map_ = |
| HostContentSettingsMapFactory::GetForProfile(profile); |
| pref_service_ = profile->GetPrefs(); |
| } |
| |
| RequestDesktopSiteWebContentsObserverAndroid:: |
| ~RequestDesktopSiteWebContentsObserverAndroid() = default; |
| |
| void RequestDesktopSiteWebContentsObserverAndroid::DidStartNavigation( |
| content::NavigationHandle* navigation_handle) { |
| // A webpage could contain multiple frames, which will trigger this observer |
| // multiple times. Only need to override user agent for the main frame of the |
| // webpage; since the child iframes inherit from the main frame. |
| if (!navigation_handle->IsInMainFrame()) { |
| return; |
| } |
| |
| const GURL& url = navigation_handle->GetParentFrameOrOuterDocument() |
| ? navigation_handle->GetParentFrameOrOuterDocument() |
| ->GetOutermostMainFrame() |
| ->GetLastCommittedURL() |
| : navigation_handle->GetURL(); |
| content_settings::SettingInfo setting_info; |
| ContentSetting setting = host_content_settings_map_->GetContentSetting( |
| url, url, ContentSettingsType::REQUEST_DESKTOP_SITE, &setting_info); |
| bool desktop_mode = setting == CONTENT_SETTING_ALLOW; |
| // For --request-desktop-sites, always override the user agent. |
| bool always_request_desktop_site = |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kRequestDesktopSites); |
| desktop_mode |= always_request_desktop_site; |
| bool is_global_setting = setting_info.primary_pattern.MatchesAllHosts(); |
| |
| // RDS Window Setting support. |
| if (!base::android::BuildInfo::GetInstance()->is_automotive() && |
| pref_service_->GetBoolean(prefs::kDesktopSiteWindowSettingEnabled) && |
| desktop_mode && !always_request_desktop_site && is_global_setting) { |
| int web_contents_width_dp = |
| web_contents()->GetContainerBounds().size().width(); |
| if (web_contents_width_dp > 0 && |
| web_contents_width_dp < content::kAndroidMinimumTabletWidthDp) { |
| desktop_mode = false; |
| } |
| } |
| |
| // Override UA for renderer initiated navigation only. UA override for browser |
| // initiated navigation is handled on Java side. This is to workaround known |
| // issues crbug.com/1265751 and crbug.com/1261939. |
| if (navigation_handle->IsRendererInitiated()) { |
| navigation_handle->SetIsOverridingUserAgent(desktop_mode); |
| } |
| |
| // Only record UKM for site settings and primary main frame. |
| if (is_global_setting || !navigation_handle->IsInPrimaryMainFrame()) { |
| return; |
| } |
| rds_web_contents_observer::UserAgentRequestType user_agent_request_type; |
| if (desktop_mode) { |
| user_agent_request_type = |
| rds_web_contents_observer::UserAgentRequestType::RequestDesktop; |
| } else { |
| user_agent_request_type = |
| rds_web_contents_observer::UserAgentRequestType::RequestMobile; |
| } |
| ukm::SourceId source_id = ukm::ConvertToSourceId( |
| navigation_handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID); |
| ukm::builders::Android_NonDefaultRdsPageLoad(source_id) |
| .SetUserAgentType(static_cast<int>(user_agent_request_type)) |
| .Record(ukm::UkmRecorder::Get()); |
| } |
| |
| WEB_CONTENTS_USER_DATA_KEY_IMPL(RequestDesktopSiteWebContentsObserverAndroid); |