1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h"
6 
7 #include <string>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/check.h"
12 #include "base/location.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_process_platform_part.h"
16 #include "chrome/browser/chromeos/login/wizard_controller.h"
17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
18 #include "chrome/browser/net/system_network_context_manager.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/prefs/pref_service.h"
24 #include "content/public/browser/storage_partition.h"
25 #include "net/http/http_response_headers.h"
26 #include "services/network/public/cpp/resource_request.h"
27 #include "services/network/public/cpp/simple_url_loader.h"
28 #include "services/network/public/mojom/url_loader_factory.mojom.h"
29 #include "url/gurl.h"
30 
31 namespace chromeos {
32 namespace {
33 
34 constexpr const char kAccept[] = "accept";
35 constexpr const char kBack[] = "back";
36 constexpr const char kRetry[] = "retry";
37 
38 }  // namespace
39 
40 // static
GetResultString(Result result)41 std::string TermsOfServiceScreen::GetResultString(Result result) {
42   switch (result) {
43     case Result::ACCEPTED:
44       return "Accepted";
45     case Result::DECLINED:
46       return "Declined";
47     case Result::NOT_APPLICABLE:
48       return BaseScreen::kNotApplicable;
49   }
50 }
51 
TermsOfServiceScreen(TermsOfServiceScreenView * view,const ScreenExitCallback & exit_callback)52 TermsOfServiceScreen::TermsOfServiceScreen(
53     TermsOfServiceScreenView* view,
54     const ScreenExitCallback& exit_callback)
55     : BaseScreen(TermsOfServiceScreenView::kScreenId,
56                  OobeScreenPriority::DEFAULT),
57       view_(view),
58       exit_callback_(exit_callback) {
59   DCHECK(view_);
60   if (view_)
61     view_->SetScreen(this);
62 }
63 
~TermsOfServiceScreen()64 TermsOfServiceScreen::~TermsOfServiceScreen() {
65   if (view_)
66     view_->SetScreen(nullptr);
67 }
68 
OnDecline()69 void TermsOfServiceScreen::OnDecline() {
70   exit_callback_.Run(Result::DECLINED);
71 }
72 
OnAccept()73 void TermsOfServiceScreen::OnAccept() {
74   if (view_ && view_->AreTermsLoaded()) {
75     exit_callback_.Run(Result::ACCEPTED);
76     return;
77   }
78   // If the Terms of Service have not been successfully downloaded, the "accept
79   // and continue" button should not be accessible. If the user managed to
80   // activate it somehow anyway, do not treat this as acceptance of the Terms
81   // and Conditions and end the session instead, as if the user had declined.
82   OnDecline();
83 }
84 
OnRetry()85 void TermsOfServiceScreen::OnRetry() {
86   // If the Terms of Service have been successfully downloaded or are still
87   // being downloaded, this button should not be accessible. If the user managed
88   // to activate it somehow anyway, do not do anything.
89   if (view_ && view_->AreTermsLoaded())
90     return;
91   if (terms_of_service_loader_)
92     return;
93 
94   StartDownload();
95 }
96 
OnViewDestroyed(TermsOfServiceScreenView * view)97 void TermsOfServiceScreen::OnViewDestroyed(TermsOfServiceScreenView* view) {
98   if (view_ == view)
99     view_ = nullptr;
100 }
101 
MaybeSkip(WizardContext * context)102 bool TermsOfServiceScreen::MaybeSkip(WizardContext* context) {
103   // Only show the Terms of Service when logging into a public account and Terms
104   // of Service have been specified through policy. In all other cases, advance
105   // to the post-ToS part immediately.
106   if (!user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() ||
107       !ProfileManager::GetActiveUserProfile()->GetPrefs()->IsManagedPreference(
108           prefs::kTermsOfServiceURL)) {
109     exit_callback_.Run(Result::NOT_APPLICABLE);
110     return true;
111   }
112 
113   return false;
114 }
115 
ShowImpl()116 void TermsOfServiceScreen::ShowImpl() {
117   if (!view_)
118     return;
119 
120   // Set the domain name whose Terms of Service are being shown.
121   policy::BrowserPolicyConnectorChromeOS* connector =
122       g_browser_process->platform_part()->browser_policy_connector_chromeos();
123   view_->SetDomain(connector->GetEnterpriseDisplayDomain());
124 
125   // Show the screen.
126   view_->Show();
127 
128   // Start downloading the Terms of Service.
129   StartDownload();
130 }
131 
HideImpl()132 void TermsOfServiceScreen::HideImpl() {
133   if (view_)
134     view_->Hide();
135 }
136 
OnUserAction(const std::string & action_id)137 void TermsOfServiceScreen::OnUserAction(const std::string& action_id) {
138   if (action_id == kBack)
139     OnDecline();
140   else if (action_id == kAccept)
141     OnAccept();
142   else if (action_id == kRetry)
143     OnRetry();
144   else
145     BaseScreen::OnUserAction(action_id);
146 }
147 
StartDownload()148 void TermsOfServiceScreen::StartDownload() {
149   const PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
150   // If an URL from which the Terms of Service can be downloaded has not been
151   // set, show an error message to the user.
152   std::string terms_of_service_url =
153       prefs->GetString(prefs::kTermsOfServiceURL);
154   if (terms_of_service_url.empty()) {
155     if (view_)
156       view_->OnLoadError();
157     return;
158   }
159 
160   net::NetworkTrafficAnnotationTag traffic_annotation =
161       net::DefineNetworkTrafficAnnotation("terms_of_service_fetch", R"(
162           semantics {
163             sender: "Chrome OS Terms of Service"
164             description:
165               "Chrome OS downloads the latest terms of service document "
166               "from Google servers."
167             trigger:
168               "When a public session starts on managed devices and an admin "
169               "has uploaded a terms of service document for the domain."
170             data:
171               "URL of the terms of service document. "
172               "No user information is sent."
173             destination: WEBSITE
174           }
175           policy {
176             cookies_allowed: YES
177             cookies_store: "user"
178             setting: "Unconditionally enabled on Chrome OS."
179             policy_exception_justification:
180               "Not implemented, considered not useful."
181           })");
182   // Start downloading the Terms of Service.
183 
184   auto resource_request = std::make_unique<network::ResourceRequest>();
185   resource_request->url = GURL(terms_of_service_url);
186   // Request a text/plain MIME type as only plain-text Terms of Service are
187   // accepted.
188   resource_request->headers.SetHeader("Accept", "text/plain");
189   terms_of_service_loader_ = network::SimpleURLLoader::Create(
190       std::move(resource_request), traffic_annotation);
191   // Retry up to three times if network changes are detected during the
192   // download.
193   terms_of_service_loader_->SetRetryOptions(
194       3, network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
195   network::mojom::URLLoaderFactory* loader_factory =
196       g_browser_process->system_network_context_manager()
197           ->GetURLLoaderFactory();
198   terms_of_service_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
199       loader_factory, base::BindOnce(&TermsOfServiceScreen::OnDownloaded,
200                                      base::Unretained(this)));
201 
202   // Abort the download attempt if it takes longer than one minute.
203   download_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(1), this,
204                         &TermsOfServiceScreen::OnDownloadTimeout);
205 }
206 
OnDownloadTimeout()207 void TermsOfServiceScreen::OnDownloadTimeout() {
208   // Destroy the fetcher, which will abort the download attempt.
209   terms_of_service_loader_.reset();
210 
211   // Show an error message to the user.
212   if (view_)
213     view_->OnLoadError();
214 }
215 
OnDownloaded(std::unique_ptr<std::string> response_body)216 void TermsOfServiceScreen::OnDownloaded(
217     std::unique_ptr<std::string> response_body) {
218   download_timer_.Stop();
219 
220   // Destroy the fetcher when this method returns.
221   std::unique_ptr<network::SimpleURLLoader> loader(
222       std::move(terms_of_service_loader_));
223   if (!view_)
224     return;
225 
226   // If the Terms of Service could not be downloaded, do not have a MIME type of
227   // text/plain or are empty, show an error message to the user.
228   if (!response_body || *response_body == "" || !loader->ResponseInfo() ||
229       loader->ResponseInfo()->mime_type != "text/plain") {
230     view_->OnLoadError();
231   } else {
232     // If the Terms of Service were downloaded successfully, show them to the
233     // user.
234     view_->OnLoadSuccess(*response_body);
235   }
236 }
237 
238 }  // namespace chromeos
239