1 // Copyright 2014 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 "base/path_service.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/prefs/scoped_user_pref_update.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
12 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14 #include "chrome/browser/supervised_user/custodian_profile_downloader_service.h"
15 #include "chrome/browser/supervised_user/custodian_profile_downloader_service_factory.h"
16 #include "chrome/browser/supervised_user/permission_request_creator.h"
17 #include "chrome/browser/supervised_user/supervised_user_service.h"
18 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_utils.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 #if defined(ENABLE_EXTENSIONS)
28 #include "chrome/browser/extensions/extension_service.h"
29 #include "chrome/browser/extensions/extension_service_test_base.h"
30 #include "chrome/browser/extensions/unpacked_installer.h"
31 #include "chrome/common/extensions/features/feature_channel.h"
32 #include "extensions/common/extension.h"
33 #include "extensions/common/extension_builder.h"
34 #include "extensions/common/manifest_constants.h"
37 using content::MessageLoopRunner
;
41 void OnProfileDownloadedFail(const base::string16
& full_name
) {
42 ASSERT_TRUE(false) << "Profile download should not have succeeded.";
45 class SupervisedUserURLFilterObserver
:
46 public SupervisedUserURLFilter::Observer
{
48 explicit SupervisedUserURLFilterObserver(SupervisedUserURLFilter
* url_filter
)
49 : url_filter_(url_filter
) {
51 url_filter_
->AddObserver(this);
54 ~SupervisedUserURLFilterObserver() {
55 url_filter_
->RemoveObserver(this);
59 message_loop_runner_
->Run();
63 // SupervisedUserURLFilter::Observer
64 virtual void OnSiteListUpdated() override
{
65 message_loop_runner_
->Quit();
70 message_loop_runner_
= new MessageLoopRunner
;
73 SupervisedUserURLFilter
* url_filter_
;
74 scoped_refptr
<MessageLoopRunner
> message_loop_runner_
;
77 class AsyncResultHolder
{
79 AsyncResultHolder() : result_(false) {}
80 ~AsyncResultHolder() {}
82 void SetResult(bool result
) {
93 base::RunLoop run_loop_
;
96 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder
);
99 class SupervisedUserServiceTest
: public ::testing::Test
{
101 SupervisedUserServiceTest() {}
103 virtual void SetUp() override
{
104 TestingProfile::Builder builder
;
105 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
106 BuildFakeProfileOAuth2TokenService
);
107 profile_
= builder
.Build();
108 supervised_user_service_
=
109 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
112 virtual void TearDown() override
{
116 virtual ~SupervisedUserServiceTest() {}
119 void AddAccessRequest(const GURL
& url
, AsyncResultHolder
* result_holder
) {
120 supervised_user_service_
->AddAccessRequest(
121 url
, base::Bind(&AsyncResultHolder::SetResult
,
122 base::Unretained(result_holder
)));
125 content::TestBrowserThreadBundle thread_bundle_
;
126 scoped_ptr
<TestingProfile
> profile_
;
127 SupervisedUserService
* supervised_user_service_
;
132 TEST_F(SupervisedUserServiceTest
, GetManualExceptionsForHost
) {
133 GURL
kExampleFooURL("http://www.example.com/foo");
134 GURL
kExampleBarURL("http://www.example.com/bar");
135 GURL
kExampleFooNoWWWURL("http://example.com/foo");
136 GURL
kBlurpURL("http://blurp.net/bla");
137 GURL
kMooseURL("http://moose.org/baz");
139 DictionaryPrefUpdate
update(profile_
->GetPrefs(),
140 prefs::kSupervisedUserManualURLs
);
141 base::DictionaryValue
* dict
= update
.Get();
142 dict
->SetBooleanWithoutPathExpansion(kExampleFooURL
.spec(), true);
143 dict
->SetBooleanWithoutPathExpansion(kExampleBarURL
.spec(), false);
144 dict
->SetBooleanWithoutPathExpansion(kExampleFooNoWWWURL
.spec(), true);
145 dict
->SetBooleanWithoutPathExpansion(kBlurpURL
.spec(), true);
148 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
149 supervised_user_service_
->GetManualBehaviorForURL(kExampleFooURL
));
150 EXPECT_EQ(SupervisedUserService::MANUAL_BLOCK
,
151 supervised_user_service_
->GetManualBehaviorForURL(kExampleBarURL
));
152 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
153 supervised_user_service_
->GetManualBehaviorForURL(
154 kExampleFooNoWWWURL
));
155 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
156 supervised_user_service_
->GetManualBehaviorForURL(kBlurpURL
));
157 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
158 supervised_user_service_
->GetManualBehaviorForURL(kMooseURL
));
159 std::vector
<GURL
> exceptions
;
160 supervised_user_service_
->GetManualExceptionsForHost("www.example.com",
162 ASSERT_EQ(2u, exceptions
.size());
163 EXPECT_EQ(kExampleBarURL
, exceptions
[0]);
164 EXPECT_EQ(kExampleFooURL
, exceptions
[1]);
167 DictionaryPrefUpdate
update(profile_
->GetPrefs(),
168 prefs::kSupervisedUserManualURLs
);
169 base::DictionaryValue
* dict
= update
.Get();
170 for (const GURL
& url
: exceptions
)
171 dict
->RemoveWithoutPathExpansion(url
.spec(), NULL
);
174 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
175 supervised_user_service_
->GetManualBehaviorForURL(kExampleFooURL
));
176 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
177 supervised_user_service_
->GetManualBehaviorForURL(kExampleBarURL
));
178 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
179 supervised_user_service_
->GetManualBehaviorForURL(
180 kExampleFooNoWWWURL
));
181 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
182 supervised_user_service_
->GetManualBehaviorForURL(kBlurpURL
));
183 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
184 supervised_user_service_
->GetManualBehaviorForURL(kMooseURL
));
187 TEST_F(SupervisedUserServiceTest
, ChangesIncludedSessionOnChangedSettings
) {
188 supervised_user_service_
->Init();
189 EXPECT_TRUE(supervised_user_service_
->IncludesSyncSessionsType());
190 profile_
->GetPrefs()->SetBoolean(prefs::kRecordHistory
, false);
191 EXPECT_FALSE(supervised_user_service_
->IncludesSyncSessionsType());
194 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
195 // DCHECK is hit when the service is destroyed, this test passed.
196 TEST_F(SupervisedUserServiceTest
, ShutDownCustodianProfileDownloader
) {
197 CustodianProfileDownloaderService
* downloader_service
=
198 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_
.get());
200 // Emulate being logged in, then start to download a profile so a
201 // ProfileDownloader gets created.
202 profile_
->GetPrefs()->SetString(prefs::kGoogleServicesUsername
, "Logged In");
203 downloader_service
->DownloadProfile(base::Bind(&OnProfileDownloadedFail
));
208 class MockPermissionRequestCreator
: public PermissionRequestCreator
{
210 MockPermissionRequestCreator() : enabled_(false) {}
211 virtual ~MockPermissionRequestCreator() {}
213 void set_enabled(bool enabled
) {
217 const std::vector
<GURL
>& requested_urls() const {
218 return requested_urls_
;
221 void AnswerRequest(size_t index
, bool result
) {
222 ASSERT_LT(index
, requested_urls_
.size());
223 callbacks_
[index
].Run(result
);
224 callbacks_
.erase(callbacks_
.begin() + index
);
225 requested_urls_
.erase(requested_urls_
.begin() + index
);
229 // PermissionRequestCreator:
230 virtual bool IsEnabled() const override
{
234 virtual void CreatePermissionRequest(
235 const GURL
& url_requested
,
236 const SuccessCallback
& callback
) override
{
237 ASSERT_TRUE(enabled_
);
238 requested_urls_
.push_back(url_requested
);
239 callbacks_
.push_back(callback
);
243 std::vector
<GURL
> requested_urls_
;
244 std::vector
<SuccessCallback
> callbacks_
;
246 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator
);
251 TEST_F(SupervisedUserServiceTest
, CreatePermissionRequest
) {
252 GURL
url("http://www.example.com");
254 // Without any permission request creators, it should be disabled, and any
255 // AddAccessRequest() calls should fail.
256 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
258 AsyncResultHolder result_holder
;
259 AddAccessRequest(url
, &result_holder
);
260 EXPECT_FALSE(result_holder
.GetResult());
263 // Add a disabled permission request creator. This should not change anything.
264 MockPermissionRequestCreator
* creator
= new MockPermissionRequestCreator
;
265 supervised_user_service_
->AddPermissionRequestCreatorForTesting(creator
);
267 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
269 AsyncResultHolder result_holder
;
270 AddAccessRequest(url
, &result_holder
);
271 EXPECT_FALSE(result_holder
.GetResult());
274 // Enable the permission request creator. This should enable permission
275 // requests and queue them up.
276 creator
->set_enabled(true);
277 EXPECT_TRUE(supervised_user_service_
->AccessRequestsEnabled());
279 AsyncResultHolder result_holder
;
280 AddAccessRequest(url
, &result_holder
);
281 ASSERT_EQ(1u, creator
->requested_urls().size());
282 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
284 creator
->AnswerRequest(0, true);
285 EXPECT_TRUE(result_holder
.GetResult());
289 AsyncResultHolder result_holder
;
290 AddAccessRequest(url
, &result_holder
);
291 ASSERT_EQ(1u, creator
->requested_urls().size());
292 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
294 creator
->AnswerRequest(0, false);
295 EXPECT_FALSE(result_holder
.GetResult());
298 // Add a second permission request creator.
299 MockPermissionRequestCreator
* creator_2
= new MockPermissionRequestCreator
;
300 creator_2
->set_enabled(true);
301 supervised_user_service_
->AddPermissionRequestCreatorForTesting(creator_2
);
304 AsyncResultHolder result_holder
;
305 AddAccessRequest(url
, &result_holder
);
306 ASSERT_EQ(1u, creator
->requested_urls().size());
307 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
309 // Make the first creator succeed. This should make the whole thing succeed.
310 creator
->AnswerRequest(0, true);
311 EXPECT_TRUE(result_holder
.GetResult());
315 AsyncResultHolder result_holder
;
316 AddAccessRequest(url
, &result_holder
);
317 ASSERT_EQ(1u, creator
->requested_urls().size());
318 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
320 // Make the first creator fail. This should fall back to the second one.
321 creator
->AnswerRequest(0, false);
322 ASSERT_EQ(1u, creator_2
->requested_urls().size());
323 EXPECT_EQ(url
.spec(), creator_2
->requested_urls()[0].spec());
325 // Make the second creator succeed, which will make the whole thing succeed.
326 creator_2
->AnswerRequest(0, true);
327 EXPECT_TRUE(result_holder
.GetResult());
331 #if defined(ENABLE_EXTENSIONS)
332 class SupervisedUserServiceExtensionTestBase
333 : public extensions::ExtensionServiceTestBase
{
335 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised
)
336 : is_supervised_(is_supervised
),
337 channel_(chrome::VersionInfo::CHANNEL_DEV
) {}
338 virtual ~SupervisedUserServiceExtensionTestBase() {}
340 virtual void SetUp() override
{
341 ExtensionServiceTestBase::SetUp();
342 ExtensionServiceTestBase::ExtensionServiceInitParams params
=
343 CreateDefaultInitParams();
344 params
.profile_is_supervised
= is_supervised_
;
345 InitializeExtensionService(params
);
346 SupervisedUserServiceFactory::GetForProfile(profile_
.get())->Init();
350 ScopedVector
<SupervisedUserSiteList
> GetActiveSiteLists(
351 SupervisedUserService
* supervised_user_service
) {
352 return supervised_user_service
->GetActiveSiteLists();
355 scoped_refptr
<extensions::Extension
> MakeThemeExtension() {
356 scoped_ptr
<base::DictionaryValue
> source(new base::DictionaryValue());
357 source
->SetString(extensions::manifest_keys::kName
, "Theme");
358 source
->Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
359 source
->SetString(extensions::manifest_keys::kVersion
, "1.0");
360 extensions::ExtensionBuilder builder
;
361 scoped_refptr
<extensions::Extension
> extension
=
362 builder
.SetManifest(source
.Pass()).Build();
366 scoped_refptr
<extensions::Extension
> MakeExtension(bool by_custodian
) {
367 scoped_ptr
<base::DictionaryValue
> manifest
= extensions::DictionaryBuilder()
368 .Set(extensions::manifest_keys::kName
, "Extension")
369 .Set(extensions::manifest_keys::kVersion
, "1.0")
371 int creation_flags
= extensions::Extension::NO_FLAGS
;
373 creation_flags
|= extensions::Extension::WAS_INSTALLED_BY_CUSTODIAN
;
374 extensions::ExtensionBuilder builder
;
375 scoped_refptr
<extensions::Extension
> extension
=
376 builder
.SetManifest(manifest
.Pass()).AddFlags(creation_flags
).Build();
381 extensions::ScopedCurrentChannel channel_
;
384 class SupervisedUserServiceExtensionTestUnsupervised
385 : public SupervisedUserServiceExtensionTestBase
{
387 SupervisedUserServiceExtensionTestUnsupervised()
388 : SupervisedUserServiceExtensionTestBase(false) {}
391 class SupervisedUserServiceExtensionTest
392 : public SupervisedUserServiceExtensionTestBase
{
394 SupervisedUserServiceExtensionTest()
395 : SupervisedUserServiceExtensionTestBase(true) {}
398 TEST_F(SupervisedUserServiceExtensionTestUnsupervised
,
399 ExtensionManagementPolicyProvider
) {
400 SupervisedUserService
* supervised_user_service
=
401 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
402 EXPECT_FALSE(profile_
->IsSupervised());
404 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
405 base::string16 error_1
;
406 EXPECT_TRUE(supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
407 EXPECT_EQ(base::string16(), error_1
);
409 base::string16 error_2
;
411 supervised_user_service
->UserMayModifySettings(extension
.get(),
413 EXPECT_EQ(base::string16(), error_2
);
416 TEST_F(SupervisedUserServiceExtensionTest
, ExtensionManagementPolicyProvider
) {
417 SupervisedUserService
* supervised_user_service
=
418 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
419 SupervisedUserURLFilterObserver
observer(
420 supervised_user_service
->GetURLFilterForUIThread());
421 ASSERT_TRUE(profile_
->IsSupervised());
422 // Wait for the initial update to finish (otherwise we'll get leaks).
425 // Check that a supervised user can install a theme.
426 scoped_refptr
<extensions::Extension
> theme
= MakeThemeExtension();
427 base::string16 error_1
;
428 EXPECT_TRUE(supervised_user_service
->UserMayLoad(theme
.get(), &error_1
));
429 EXPECT_TRUE(error_1
.empty());
431 supervised_user_service
->UserMayModifySettings(theme
.get(), &error_1
));
432 EXPECT_TRUE(error_1
.empty());
434 // Now check a different kind of extension.
435 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
436 EXPECT_FALSE(supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
437 EXPECT_FALSE(error_1
.empty());
439 base::string16 error_2
;
440 EXPECT_FALSE(supervised_user_service
->UserMayModifySettings(extension
.get(),
442 EXPECT_FALSE(error_2
.empty());
444 // Check that an extension that was installed by the custodian may be loaded.
445 base::string16 error_3
;
446 scoped_refptr
<extensions::Extension
> extension_2
= MakeExtension(true);
447 EXPECT_TRUE(supervised_user_service
->UserMayLoad(extension_2
.get(),
449 EXPECT_TRUE(error_3
.empty());
451 // The supervised user should still not be able to uninstall or disable the
453 base::string16 error_4
;
454 EXPECT_FALSE(supervised_user_service
->UserMayModifySettings(extension_2
.get(),
456 EXPECT_FALSE(error_4
.empty());
459 EXPECT_FALSE(supervised_user_service
->GetDebugPolicyProviderName().empty());
463 TEST_F(SupervisedUserServiceExtensionTest
, NoContentPacks
) {
464 SupervisedUserService
* supervised_user_service
=
465 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
466 SupervisedUserURLFilter
* url_filter
=
467 supervised_user_service
->GetURLFilterForUIThread();
469 GURL
url("http://youtube.com");
470 ScopedVector
<SupervisedUserSiteList
> site_lists
=
471 GetActiveSiteLists(supervised_user_service
);
472 ASSERT_EQ(0u, site_lists
.size());
473 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
474 url_filter
->GetFilteringBehaviorForURL(url
));
477 TEST_F(SupervisedUserServiceExtensionTest
, InstallContentPacks
) {
478 SupervisedUserService
* supervised_user_service
=
479 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
480 SupervisedUserURLFilter
* url_filter
=
481 supervised_user_service
->GetURLFilterForUIThread();
482 SupervisedUserURLFilterObserver
observer(url_filter
);
485 GURL
example_url("http://example.com");
486 GURL
moose_url("http://moose.org");
487 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
488 url_filter
->GetFilteringBehaviorForURL(example_url
));
490 profile_
->GetPrefs()->SetInteger(
491 prefs::kDefaultSupervisedUserFilteringBehavior
,
492 SupervisedUserURLFilter::BLOCK
);
493 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
494 url_filter
->GetFilteringBehaviorForURL(example_url
));
496 profile_
->GetPrefs()->SetInteger(
497 prefs::kDefaultSupervisedUserFilteringBehavior
,
498 SupervisedUserURLFilter::WARN
);
499 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
500 url_filter
->GetFilteringBehaviorForURL(example_url
));
502 supervised_user_service
->set_elevated_for_testing(true);
504 // Load a content pack.
505 scoped_refptr
<extensions::UnpackedInstaller
> installer(
506 extensions::UnpackedInstaller::Create(service_
));
507 installer
->set_prompt_for_plugins(false);
508 base::FilePath test_data_dir
;
509 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
510 base::FilePath extension_path
=
511 test_data_dir
.AppendASCII("extensions/supervised_user/content_pack");
512 content::WindowedNotificationObserver
extension_load_observer(
513 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
,
514 content::Source
<Profile
>(profile_
.get()));
515 installer
->Load(extension_path
);
516 extension_load_observer
.Wait();
518 content::Details
<extensions::Extension
> details
=
519 extension_load_observer
.details();
520 scoped_refptr
<extensions::Extension
> extension
=
521 make_scoped_refptr(details
.ptr());
522 ASSERT_TRUE(extension
.get());
524 ScopedVector
<SupervisedUserSiteList
> site_lists
=
525 GetActiveSiteLists(supervised_user_service
);
526 ASSERT_EQ(1u, site_lists
.size());
527 std::vector
<SupervisedUserSiteList::Site
> sites
;
528 site_lists
[0]->GetSites(&sites
);
529 ASSERT_EQ(3u, sites
.size());
530 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), sites
[0].name
);
531 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"), sites
[1].name
);
532 EXPECT_EQ(base::string16(), sites
[2].name
);
534 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
535 url_filter
->GetFilteringBehaviorForURL(example_url
));
536 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
537 url_filter
->GetFilteringBehaviorForURL(moose_url
));
539 // Load a second content pack.
540 installer
= extensions::UnpackedInstaller::Create(service_
);
542 test_data_dir
.AppendASCII("extensions/supervised_user/content_pack_2");
543 installer
->Load(extension_path
);
546 site_lists
= GetActiveSiteLists(supervised_user_service
);
547 ASSERT_EQ(2u, site_lists
.size());
549 site_lists
[0]->GetSites(&sites
);
550 site_lists
[1]->GetSites(&sites
);
551 ASSERT_EQ(4u, sites
.size());
552 // The site lists might be returned in any order, so we put them into a set.
553 std::set
<std::string
> site_names
;
554 for (const SupervisedUserSiteList::Site
& site
: sites
)
555 site_names
.insert(base::UTF16ToUTF8(site
.name
));
556 EXPECT_EQ(1u, site_names
.count("YouTube"));
557 EXPECT_EQ(1u, site_names
.count("Homestar Runner"));
558 EXPECT_EQ(1u, site_names
.count(std::string()));
559 EXPECT_EQ(1u, site_names
.count("Moose"));
561 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
562 url_filter
->GetFilteringBehaviorForURL(example_url
));
563 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
564 url_filter
->GetFilteringBehaviorForURL(moose_url
));
566 // Disable the first content pack.
567 service_
->DisableExtension(extension
->id(),
568 extensions::Extension::DISABLE_USER_ACTION
);
571 site_lists
= GetActiveSiteLists(supervised_user_service
);
572 ASSERT_EQ(1u, site_lists
.size());
574 site_lists
[0]->GetSites(&sites
);
575 ASSERT_EQ(1u, sites
.size());
576 EXPECT_EQ(base::ASCIIToUTF16("Moose"), sites
[0].name
);
578 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
579 url_filter
->GetFilteringBehaviorForURL(example_url
));
580 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
581 url_filter
->GetFilteringBehaviorForURL(moose_url
));
583 #endif // defined(ENABLE_EXTENSIONS)