1 // Copyright 2015 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.
5 #include "chrome/browser/ui/webui/supervised_user_internals_message_handler.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/values.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/signin/account_tracker_service_factory.h"
12 #include "chrome/browser/supervised_user/supervised_user_service.h"
13 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
14 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
15 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
16 #include "components/signin/core/browser/account_tracker_service.h"
17 #include "components/url_formatter/url_fixer.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/web_ui.h"
21 using content::BrowserThread
;
25 // Creates a 'section' for display on about:supervised-user-internals,
26 // consisting of a title and a list of fields. Returns a pointer to the new
27 // section's contents, for use with |AddSectionEntry| below. Note that
28 // |parent_list|, not the caller, owns the newly added section.
29 base::ListValue
* AddSection(base::ListValue
* parent_list
,
30 const std::string
& title
) {
31 scoped_ptr
<base::DictionaryValue
> section(new base::DictionaryValue
);
32 scoped_ptr
<base::ListValue
> section_contents(new base::ListValue
);
33 section
->SetString("title", title
);
34 // Grab a raw pointer to the result before |Pass()|ing it on.
35 base::ListValue
* result
= section_contents
.get();
36 section
->Set("data", section_contents
.Pass());
37 parent_list
->Append(section
.Pass());
41 // Adds a bool entry to a section (created with |AddSection| above).
42 void AddSectionEntry(base::ListValue
* section_list
,
43 const std::string
& name
,
45 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
46 entry
->SetString("stat_name", name
);
47 entry
->SetBoolean("stat_value", value
);
48 entry
->SetBoolean("is_valid", true);
49 section_list
->Append(entry
.Pass());
52 // Adds a string entry to a section (created with |AddSection| above).
53 void AddSectionEntry(base::ListValue
* section_list
,
54 const std::string
& name
,
55 const std::string
& value
) {
56 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
57 entry
->SetString("stat_name", name
);
58 entry
->SetString("stat_value", value
);
59 entry
->SetBoolean("is_valid", true);
60 section_list
->Append(entry
.Pass());
63 std::string
FilteringBehaviorToString(
64 SupervisedUserURLFilter::FilteringBehavior behavior
) {
66 case SupervisedUserURLFilter::ALLOW
:
68 case SupervisedUserURLFilter::WARN
:
70 case SupervisedUserURLFilter::BLOCK
:
72 case SupervisedUserURLFilter::INVALID
:
78 std::string
FilteringBehaviorToString(
79 SupervisedUserURLFilter::FilteringBehavior behavior
, bool uncertain
) {
80 std::string result
= FilteringBehaviorToString(behavior
);
82 result
+= " (Uncertain)";
86 std::string
FilteringBehaviorReasonToString(
87 SupervisedUserURLFilter::FilteringBehaviorReason reason
) {
89 case SupervisedUserURLFilter::DEFAULT
:
91 case SupervisedUserURLFilter::ASYNC_CHECKER
:
92 return "AsyncChecker";
93 case SupervisedUserURLFilter::BLACKLIST
:
95 case SupervisedUserURLFilter::MANUAL
:
98 return "Unknown/invalid";
103 // Helper class that lives on the IO thread, listens to the
104 // SupervisedUserURLFilter there, and posts results back to the UI thread.
105 class SupervisedUserInternalsMessageHandler::IOThreadHelper
106 : public base::RefCountedThreadSafe
<IOThreadHelper
,
107 BrowserThread::DeleteOnIOThread
>,
108 public SupervisedUserURLFilter::Observer
{
110 using OnURLCheckedCallback
=
111 base::Callback
<void(const GURL
&,
112 SupervisedUserURLFilter::FilteringBehavior
,
113 SupervisedUserURLFilter::FilteringBehaviorReason
,
116 IOThreadHelper(scoped_refptr
<const SupervisedUserURLFilter
> filter
,
117 const OnURLCheckedCallback
& callback
)
118 : filter_(filter
), callback_(callback
) {
119 BrowserThread::PostTask(BrowserThread::IO
,
121 base::Bind(&IOThreadHelper::InitOnIOThread
, this));
125 friend class base::DeleteHelper
<IOThreadHelper
>;
126 friend struct BrowserThread::DeleteOnThread
<BrowserThread::IO
>;
127 virtual ~IOThreadHelper() {
128 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
129 filter_
->RemoveObserver(this);
132 // SupervisedUserURLFilter::Observer:
133 void OnSiteListUpdated() override
{}
134 void OnURLChecked(const GURL
& url
,
135 SupervisedUserURLFilter::FilteringBehavior behavior
,
136 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
137 bool uncertain
) override
{
138 BrowserThread::PostTask(BrowserThread::UI
,
140 base::Bind(callback_
,
141 url
, behavior
, reason
, uncertain
));
144 void InitOnIOThread() {
145 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
146 filter_
->AddObserver(this);
149 scoped_refptr
<const SupervisedUserURLFilter
> filter_
;
150 OnURLCheckedCallback callback_
;
152 DISALLOW_COPY_AND_ASSIGN(IOThreadHelper
);
155 SupervisedUserInternalsMessageHandler::SupervisedUserInternalsMessageHandler()
156 : weak_factory_(this) {
159 SupervisedUserInternalsMessageHandler::
160 ~SupervisedUserInternalsMessageHandler() {
163 void SupervisedUserInternalsMessageHandler::RegisterMessages() {
164 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
166 web_ui()->RegisterMessageCallback("registerForEvents",
167 base::Bind(&SupervisedUserInternalsMessageHandler::
168 HandleRegisterForEvents
,
169 base::Unretained(this)));
171 web_ui()->RegisterMessageCallback("getBasicInfo",
172 base::Bind(&SupervisedUserInternalsMessageHandler::HandleGetBasicInfo
,
173 base::Unretained(this)));
175 web_ui()->RegisterMessageCallback("tryURL",
176 base::Bind(&SupervisedUserInternalsMessageHandler::HandleTryURL
,
177 base::Unretained(this)));
180 void SupervisedUserInternalsMessageHandler::OnURLFilterChanged() {
184 SupervisedUserService
*
185 SupervisedUserInternalsMessageHandler::GetSupervisedUserService() {
186 Profile
* profile
= Profile::FromWebUI(web_ui());
187 return SupervisedUserServiceFactory::GetForProfile(
188 profile
->GetOriginalProfile());
191 void SupervisedUserInternalsMessageHandler::HandleRegisterForEvents(
192 const base::ListValue
* args
) {
193 DCHECK(args
->empty());
195 if (!io_thread_helper_
.get()) {
196 io_thread_helper_
= new IOThreadHelper(
197 GetSupervisedUserService()->GetURLFilterForIOThread(),
198 base::Bind(&SupervisedUserInternalsMessageHandler::OnURLChecked
,
199 weak_factory_
.GetWeakPtr()));
203 void SupervisedUserInternalsMessageHandler::HandleGetBasicInfo(
204 const base::ListValue
* args
) {
208 void SupervisedUserInternalsMessageHandler::HandleTryURL(
209 const base::ListValue
* args
) {
210 DCHECK_EQ(1u, args
->GetSize());
212 if (!args
->GetString(0, &url_str
))
215 GURL url
= url_formatter::FixupURL(url_str
, std::string());
219 SupervisedUserURLFilter
* filter
=
220 GetSupervisedUserService()->GetURLFilterForUIThread();
221 filter
->GetFilteringBehaviorForURLWithAsyncChecks(
223 base::Bind(&SupervisedUserInternalsMessageHandler::OnTryURLResult
,
224 weak_factory_
.GetWeakPtr()));
227 void SupervisedUserInternalsMessageHandler::SendBasicInfo() {
228 scoped_ptr
<base::ListValue
> section_list(new base::ListValue
);
230 Profile
* profile
= Profile::FromWebUI(web_ui());
232 base::ListValue
* section_profile
= AddSection(section_list
.get(), "Profile");
233 AddSectionEntry(section_profile
, "Account", profile
->GetProfileUserName());
234 AddSectionEntry(section_profile
, "Legacy Supervised",
235 profile
->IsLegacySupervised());
236 AddSectionEntry(section_profile
, "Child", profile
->IsChild());
238 SupervisedUserURLFilter
* filter
=
239 GetSupervisedUserService()->GetURLFilterForUIThread();
241 base::ListValue
* section_filter
= AddSection(section_list
.get(), "Filter");
242 AddSectionEntry(section_filter
, "Blacklist active", filter
->HasBlacklist());
243 AddSectionEntry(section_filter
, "Online checks active",
244 filter
->HasAsyncURLChecker());
245 AddSectionEntry(section_filter
, "Default behavior",
246 FilteringBehaviorToString(
247 filter
->GetDefaultFilteringBehavior()));
249 AccountTrackerService
* account_tracker
=
250 AccountTrackerServiceFactory::GetForProfile(profile
);
252 for (const auto& account
: account_tracker
->GetAccounts()) {
253 base::ListValue
* section_user
= AddSection(section_list
.get(),
254 "User Information for " + account
.full_name
);
255 AddSectionEntry(section_user
, "Account id", account
.account_id
);
256 AddSectionEntry(section_user
, "Gaia", account
.gaia
);
257 AddSectionEntry(section_user
, "Email", account
.email
);
258 AddSectionEntry(section_user
, "Given name", account
.given_name
);
259 AddSectionEntry(section_user
, "Hosted domain", account
.hosted_domain
);
260 AddSectionEntry(section_user
, "Locale", account
.locale
);
261 AddSectionEntry(section_user
, "Is child", account
.is_child_account
);
262 AddSectionEntry(section_user
, "Is valid", account
.IsValid());
265 base::DictionaryValue result
;
266 result
.Set("sections", section_list
.Pass());
267 web_ui()->CallJavascriptFunction(
268 "chrome.supervised_user_internals.receiveBasicInfo", result
);
270 // Trigger retrieval of the user settings
271 SupervisedUserSettingsService
* settings_service
=
272 SupervisedUserSettingsServiceFactory::GetForProfile(profile
);
273 user_settings_subscription_
= settings_service
->Subscribe(base::Bind(
274 &SupervisedUserInternalsMessageHandler::SendSupervisedUserSettings
,
275 weak_factory_
.GetWeakPtr()));
278 void SupervisedUserInternalsMessageHandler::SendSupervisedUserSettings(
279 const base::DictionaryValue
* settings
) {
280 web_ui()->CallJavascriptFunction(
281 "chrome.supervised_user_internals.receiveUserSettings",
282 *(settings
? settings
: base::Value::CreateNullValue().get()));
285 void SupervisedUserInternalsMessageHandler::OnTryURLResult(
286 SupervisedUserURLFilter::FilteringBehavior behavior
,
287 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
289 web_ui()->CallJavascriptFunction(
290 "chrome.supervised_user_internals.receiveTryURLResult",
291 base::StringValue(FilteringBehaviorToString(behavior
, uncertain
)));
294 void SupervisedUserInternalsMessageHandler::OnURLChecked(
296 SupervisedUserURLFilter::FilteringBehavior behavior
,
297 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
299 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
300 base::DictionaryValue result
;
301 result
.SetString("url", url
.possibly_invalid_spec());
302 result
.SetString("result", FilteringBehaviorToString(behavior
, uncertain
));
303 result
.SetString("reason", FilteringBehaviorReasonToString(reason
));
304 web_ui()->CallJavascriptFunction(
305 "chrome.supervised_user_internals.receiveFilteringResult", result
);