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/supervised_user/supervised_user_service.h"
12 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
13 #include "components/url_formatter/url_fixer.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/web_ui.h"
17 using content::BrowserThread
;
21 // Creates a 'section' for display on about:supervised-user-internals,
22 // consisting of a title and a list of fields. Returns a pointer to the new
23 // section's contents, for use with |AddSectionEntry| below. Note that
24 // |parent_list|, not the caller, owns the newly added section.
25 base::ListValue
* AddSection(base::ListValue
* parent_list
,
26 const std::string
& title
) {
27 scoped_ptr
<base::DictionaryValue
> section(new base::DictionaryValue
);
28 scoped_ptr
<base::ListValue
> section_contents(new base::ListValue
);
29 section
->SetString("title", title
);
30 // Grab a raw pointer to the result before |Pass()|ing it on.
31 base::ListValue
* result
= section_contents
.get();
32 section
->Set("data", section_contents
.Pass());
33 parent_list
->Append(section
.Pass());
37 // Adds a bool entry to a section (created with |AddSection| above).
38 void AddSectionEntry(base::ListValue
* section_list
,
39 const std::string
& name
,
41 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
42 entry
->SetString("stat_name", name
);
43 entry
->SetBoolean("stat_value", value
);
44 entry
->SetBoolean("is_valid", true);
45 section_list
->Append(entry
.Pass());
48 // Adds a string entry to a section (created with |AddSection| above).
49 void AddSectionEntry(base::ListValue
* section_list
,
50 const std::string
& name
,
51 const std::string
& value
) {
52 scoped_ptr
<base::DictionaryValue
> entry(new base::DictionaryValue
);
53 entry
->SetString("stat_name", name
);
54 entry
->SetString("stat_value", value
);
55 entry
->SetBoolean("is_valid", true);
56 section_list
->Append(entry
.Pass());
59 std::string
FilteringBehaviorToString(
60 SupervisedUserURLFilter::FilteringBehavior behavior
) {
62 case SupervisedUserURLFilter::ALLOW
:
64 case SupervisedUserURLFilter::WARN
:
66 case SupervisedUserURLFilter::BLOCK
:
68 case SupervisedUserURLFilter::INVALID
:
74 std::string
FilteringBehaviorToString(
75 SupervisedUserURLFilter::FilteringBehavior behavior
, bool uncertain
) {
76 std::string result
= FilteringBehaviorToString(behavior
);
78 result
+= " (Uncertain)";
82 std::string
FilteringBehaviorReasonToString(
83 SupervisedUserURLFilter::FilteringBehaviorReason reason
) {
85 case SupervisedUserURLFilter::DEFAULT
:
87 case SupervisedUserURLFilter::ASYNC_CHECKER
:
88 return "AsyncChecker";
89 case SupervisedUserURLFilter::BLACKLIST
:
91 case SupervisedUserURLFilter::MANUAL
:
94 return "Unknown/invalid";
99 // Helper class that lives on the IO thread, listens to the
100 // SupervisedUserURLFilter there, and posts results back to the UI thread.
101 class SupervisedUserInternalsMessageHandler::IOThreadHelper
102 : public base::RefCountedThreadSafe
<IOThreadHelper
,
103 BrowserThread::DeleteOnIOThread
>,
104 public SupervisedUserURLFilter::Observer
{
106 using OnURLCheckedCallback
=
107 base::Callback
<void(const GURL
&,
108 SupervisedUserURLFilter::FilteringBehavior
,
109 SupervisedUserURLFilter::FilteringBehaviorReason
,
112 IOThreadHelper(scoped_refptr
<const SupervisedUserURLFilter
> filter
,
113 const OnURLCheckedCallback
& callback
)
114 : filter_(filter
), callback_(callback
) {
115 BrowserThread::PostTask(BrowserThread::IO
,
117 base::Bind(&IOThreadHelper::InitOnIOThread
, this));
121 friend class base::DeleteHelper
<IOThreadHelper
>;
122 friend struct BrowserThread::DeleteOnThread
<BrowserThread::IO
>;
123 virtual ~IOThreadHelper() {
124 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
125 filter_
->RemoveObserver(this);
128 // SupervisedUserURLFilter::Observer:
129 void OnSiteListUpdated() override
{}
130 void OnURLChecked(const GURL
& url
,
131 SupervisedUserURLFilter::FilteringBehavior behavior
,
132 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
133 bool uncertain
) override
{
134 BrowserThread::PostTask(BrowserThread::UI
,
136 base::Bind(callback_
,
137 url
, behavior
, reason
, uncertain
));
140 void InitOnIOThread() {
141 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
142 filter_
->AddObserver(this);
145 scoped_refptr
<const SupervisedUserURLFilter
> filter_
;
146 OnURLCheckedCallback callback_
;
148 DISALLOW_COPY_AND_ASSIGN(IOThreadHelper
);
151 SupervisedUserInternalsMessageHandler::SupervisedUserInternalsMessageHandler()
152 : weak_factory_(this) {
155 SupervisedUserInternalsMessageHandler::
156 ~SupervisedUserInternalsMessageHandler() {
159 void SupervisedUserInternalsMessageHandler::RegisterMessages() {
160 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
162 web_ui()->RegisterMessageCallback("registerForEvents",
163 base::Bind(&SupervisedUserInternalsMessageHandler::
164 HandleRegisterForEvents
,
165 base::Unretained(this)));
167 web_ui()->RegisterMessageCallback("getBasicInfo",
168 base::Bind(&SupervisedUserInternalsMessageHandler::HandleGetBasicInfo
,
169 base::Unretained(this)));
171 web_ui()->RegisterMessageCallback("tryURL",
172 base::Bind(&SupervisedUserInternalsMessageHandler::HandleTryURL
,
173 base::Unretained(this)));
176 void SupervisedUserInternalsMessageHandler::OnURLFilterChanged() {
180 SupervisedUserService
*
181 SupervisedUserInternalsMessageHandler::GetSupervisedUserService() {
182 Profile
* profile
= Profile::FromWebUI(web_ui());
183 return SupervisedUserServiceFactory::GetForProfile(
184 profile
->GetOriginalProfile());
187 void SupervisedUserInternalsMessageHandler::HandleRegisterForEvents(
188 const base::ListValue
* args
) {
189 DCHECK(args
->empty());
191 if (!io_thread_helper_
.get()) {
192 io_thread_helper_
= new IOThreadHelper(
193 GetSupervisedUserService()->GetURLFilterForIOThread(),
194 base::Bind(&SupervisedUserInternalsMessageHandler::OnURLChecked
,
195 weak_factory_
.GetWeakPtr()));
199 void SupervisedUserInternalsMessageHandler::HandleGetBasicInfo(
200 const base::ListValue
* args
) {
204 void SupervisedUserInternalsMessageHandler::HandleTryURL(
205 const base::ListValue
* args
) {
206 DCHECK_EQ(1u, args
->GetSize());
208 if (!args
->GetString(0, &url_str
))
211 GURL url
= url_formatter::FixupURL(url_str
, std::string());
215 SupervisedUserURLFilter
* filter
=
216 GetSupervisedUserService()->GetURLFilterForUIThread();
217 filter
->GetFilteringBehaviorForURLWithAsyncChecks(
219 base::Bind(&SupervisedUserInternalsMessageHandler::OnTryURLResult
,
220 weak_factory_
.GetWeakPtr()));
223 void SupervisedUserInternalsMessageHandler::SendBasicInfo() {
224 scoped_ptr
<base::ListValue
> section_list(new base::ListValue
);
226 Profile
* profile
= Profile::FromWebUI(web_ui());
228 base::ListValue
* section_profile
= AddSection(section_list
.get(), "Profile");
229 AddSectionEntry(section_profile
, "Account", profile
->GetProfileUserName());
230 AddSectionEntry(section_profile
, "Legacy Supervised",
231 profile
->IsLegacySupervised());
232 AddSectionEntry(section_profile
, "Child", profile
->IsChild());
234 SupervisedUserURLFilter
* filter
=
235 GetSupervisedUserService()->GetURLFilterForUIThread();
237 base::ListValue
* section_filter
= AddSection(section_list
.get(), "Filter");
238 AddSectionEntry(section_filter
, "Blacklist active", filter
->HasBlacklist());
239 AddSectionEntry(section_filter
, "Online checks active",
240 filter
->HasAsyncURLChecker());
241 AddSectionEntry(section_filter
, "Default behavior",
242 FilteringBehaviorToString(
243 filter
->GetDefaultFilteringBehavior()));
245 base::DictionaryValue result
;
246 result
.Set("sections", section_list
.Pass());
247 web_ui()->CallJavascriptFunction(
248 "chrome.supervised_user_internals.receiveBasicInfo", result
);
251 void SupervisedUserInternalsMessageHandler::OnTryURLResult(
252 SupervisedUserURLFilter::FilteringBehavior behavior
,
253 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
255 web_ui()->CallJavascriptFunction(
256 "chrome.supervised_user_internals.receiveTryURLResult",
257 base::StringValue(FilteringBehaviorToString(behavior
, uncertain
)));
260 void SupervisedUserInternalsMessageHandler::OnURLChecked(
262 SupervisedUserURLFilter::FilteringBehavior behavior
,
263 SupervisedUserURLFilter::FilteringBehaviorReason reason
,
265 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
266 base::DictionaryValue result
;
267 result
.SetString("url", url
.possibly_invalid_spec());
268 result
.SetString("result", FilteringBehaviorToString(behavior
, uncertain
));
269 result
.SetString("reason", FilteringBehaviorReasonToString(reason
));
270 web_ui()->CallJavascriptFunction(
271 "chrome.supervised_user_internals.receiveFilteringResult", result
);