1 // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "include/base/cef_callback.h"
6 #include "include/cef_request_context_handler.h"
7 #include "include/cef_waitable_event.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "tests/ceftests/test_handler.h"
10 #include "tests/ceftests/test_util.h"
11 #include "tests/gtest/include/gtest/gtest.h"
12 #include "tests/shared/browser/client_app_browser.h"
13
14 namespace {
15
16 // Fully qualified preference names.
17 const char kPrefTest[] = "test";
18 const char kPrefTestBool[] = "test.bool";
19 const char kPrefTestInt[] = "test.int";
20 const char kPrefTestDouble[] = "test.double";
21 const char kPrefTestString[] = "test.string";
22 const char kPrefTestList[] = "test.list";
23 const char kPrefTestDict[] = "test.dict";
24 const char kPrefTestNoExist[] = "test.noexist";
25
26 // Unqualified preference names.
27 const char kPrefBool[] = "bool";
28 const char kPrefInt[] = "int";
29 const char kPrefDouble[] = "double";
30 const char kPrefString[] = "string";
31 const char kPrefList[] = "list";
32 const char kPrefDict[] = "dict";
33
PendingAction()34 std::string* PendingAction() {
35 static std::string str;
36 return &str;
37 }
38
39 // Browser-side app delegate.
40 class PreferenceBrowserTest : public client::ClientAppBrowser::Delegate {
41 public:
PreferenceBrowserTest()42 PreferenceBrowserTest() {}
43
OnBeforeCommandLineProcessing(CefRefPtr<client::ClientAppBrowser> app,CefRefPtr<CefCommandLine> command_line)44 void OnBeforeCommandLineProcessing(
45 CefRefPtr<client::ClientAppBrowser> app,
46 CefRefPtr<CefCommandLine> command_line) override {
47 // Enables testing of preferences.
48 // See CefBrowserPrefStore::CreateService.
49 command_line->AppendSwitch("enable-preference-testing");
50 }
51
52 private:
53 IMPLEMENT_REFCOUNTING(PreferenceBrowserTest);
54 };
55
ValidateReset(CefRefPtr<CefRequestContext> context,const char * name)56 void ValidateReset(CefRefPtr<CefRequestContext> context, const char* name) {
57 EXPECT_TRUE(context->HasPreference(name));
58 EXPECT_TRUE(context->CanSetPreference(name));
59
60 CefString error;
61 EXPECT_TRUE(context->SetPreference(name, nullptr, error));
62 EXPECT_TRUE(error.empty());
63 }
64
ValidateBool(CefRefPtr<CefRequestContext> context,bool set,bool expected,const char * name=kPrefTestBool)65 void ValidateBool(CefRefPtr<CefRequestContext> context,
66 bool set,
67 bool expected,
68 const char* name = kPrefTestBool) {
69 EXPECT_TRUE(context->HasPreference(name));
70 EXPECT_TRUE(context->CanSetPreference(name));
71
72 CefRefPtr<CefValue> value;
73
74 if (set) {
75 value = CefValue::Create();
76 value->SetBool(expected);
77 CefString error;
78 EXPECT_TRUE(context->SetPreference(name, value, error));
79 EXPECT_TRUE(error.empty());
80 }
81
82 value = context->GetPreference(name);
83 EXPECT_TRUE(value.get());
84 EXPECT_EQ(VTYPE_BOOL, value->GetType());
85 EXPECT_EQ(expected, value->GetBool()) << *PendingAction();
86 }
87
ValidateInt(CefRefPtr<CefRequestContext> context,bool set,int expected,const char * name=kPrefTestInt)88 void ValidateInt(CefRefPtr<CefRequestContext> context,
89 bool set,
90 int expected,
91 const char* name = kPrefTestInt) {
92 EXPECT_TRUE(context->HasPreference(name));
93 EXPECT_TRUE(context->CanSetPreference(name));
94
95 CefRefPtr<CefValue> value;
96
97 if (set) {
98 value = CefValue::Create();
99 value->SetInt(expected);
100 CefString error;
101 EXPECT_TRUE(context->SetPreference(name, value, error));
102 EXPECT_TRUE(error.empty());
103 }
104
105 value = context->GetPreference(name);
106 EXPECT_TRUE(value.get());
107 EXPECT_EQ(VTYPE_INT, value->GetType());
108 EXPECT_EQ(expected, value->GetInt()) << *PendingAction();
109 }
110
ValidateDouble(CefRefPtr<CefRequestContext> context,bool set,double expected,const char * name=kPrefTestDouble)111 void ValidateDouble(CefRefPtr<CefRequestContext> context,
112 bool set,
113 double expected,
114 const char* name = kPrefTestDouble) {
115 EXPECT_TRUE(context->HasPreference(name));
116 EXPECT_TRUE(context->CanSetPreference(name));
117
118 CefRefPtr<CefValue> value;
119
120 if (set) {
121 value = CefValue::Create();
122 value->SetDouble(expected);
123 CefString error;
124 EXPECT_TRUE(context->SetPreference(name, value, error));
125 EXPECT_TRUE(error.empty());
126 }
127
128 value = context->GetPreference(name);
129 EXPECT_TRUE(value.get());
130 EXPECT_EQ(VTYPE_DOUBLE, value->GetType());
131 EXPECT_EQ(expected, value->GetDouble()) << *PendingAction();
132 }
133
ValidateString(CefRefPtr<CefRequestContext> context,bool set,const std::string & expected,const char * name=kPrefTestString)134 void ValidateString(CefRefPtr<CefRequestContext> context,
135 bool set,
136 const std::string& expected,
137 const char* name = kPrefTestString) {
138 EXPECT_TRUE(context->HasPreference(name));
139 EXPECT_TRUE(context->CanSetPreference(name));
140
141 CefRefPtr<CefValue> value;
142
143 if (set) {
144 value = CefValue::Create();
145 value->SetString(expected);
146 CefString error;
147 EXPECT_TRUE(context->SetPreference(name, value, error));
148 EXPECT_TRUE(error.empty());
149 }
150
151 value = context->GetPreference(name);
152 EXPECT_TRUE(value.get());
153 EXPECT_EQ(VTYPE_STRING, value->GetType());
154 EXPECT_STREQ(expected.c_str(), value->GetString().ToString().c_str())
155 << *PendingAction();
156 }
157
ValidateList(CefRefPtr<CefRequestContext> context,bool set,CefRefPtr<CefListValue> expected,const char * name=kPrefTestList)158 void ValidateList(CefRefPtr<CefRequestContext> context,
159 bool set,
160 CefRefPtr<CefListValue> expected,
161 const char* name = kPrefTestList) {
162 EXPECT_TRUE(context->HasPreference(name));
163 EXPECT_TRUE(context->CanSetPreference(name));
164
165 CefRefPtr<CefValue> value;
166
167 if (set) {
168 value = CefValue::Create();
169 value->SetList(expected);
170 CefString error;
171 EXPECT_TRUE(context->SetPreference(name, value, error));
172 EXPECT_TRUE(error.empty());
173 }
174
175 value = context->GetPreference(name);
176 EXPECT_TRUE(value.get());
177 EXPECT_EQ(VTYPE_LIST, value->GetType());
178 CefRefPtr<CefListValue> list_val = value->GetList();
179 EXPECT_TRUE(list_val);
180 TestListEqual(expected, list_val);
181 }
182
ValidateDict(CefRefPtr<CefRequestContext> context,bool set,CefRefPtr<CefDictionaryValue> expected,const char * name=kPrefTestDict)183 void ValidateDict(CefRefPtr<CefRequestContext> context,
184 bool set,
185 CefRefPtr<CefDictionaryValue> expected,
186 const char* name = kPrefTestDict) {
187 EXPECT_TRUE(context->HasPreference(name));
188 EXPECT_TRUE(context->CanSetPreference(name));
189
190 CefRefPtr<CefValue> value;
191
192 if (set) {
193 value = CefValue::Create();
194 value->SetDictionary(expected);
195 CefString error;
196 EXPECT_TRUE(context->SetPreference(name, value, error));
197 EXPECT_TRUE(error.empty());
198 }
199
200 value = context->GetPreference(name);
201 EXPECT_TRUE(value.get());
202 EXPECT_EQ(VTYPE_DICTIONARY, value->GetType());
203 CefRefPtr<CefDictionaryValue> dict_val = value->GetDictionary();
204 EXPECT_TRUE(dict_val);
205 TestDictionaryEqual(expected, dict_val);
206 }
207
ValidateNoExist(CefRefPtr<CefRequestContext> context,bool set,const char * name=kPrefTestNoExist)208 void ValidateNoExist(CefRefPtr<CefRequestContext> context,
209 bool set,
210 const char* name = kPrefTestNoExist) {
211 EXPECT_FALSE(context->HasPreference(name));
212 EXPECT_FALSE(context->CanSetPreference(name));
213
214 CefRefPtr<CefValue> value;
215
216 if (set) {
217 value = CefValue::Create();
218 value->SetBool(false);
219 CefString error;
220 EXPECT_FALSE(context->SetPreference(name, value, error));
221 EXPECT_FALSE(error.empty());
222 }
223
224 value = context->GetPreference(name);
225 EXPECT_FALSE(value.get()) << *PendingAction();
226 }
227
PopulateRootDefaults(CefRefPtr<CefDictionaryValue> val)228 void PopulateRootDefaults(CefRefPtr<CefDictionaryValue> val) {
229 // Should match the values in CefBrowserPrefStore::CreateService.
230 val->SetBool(kPrefBool, true);
231 val->SetInt(kPrefInt, 2);
232 val->SetDouble(kPrefDouble, 5.0);
233 val->SetString(kPrefString, "default");
234 val->SetList(kPrefList, CefListValue::Create());
235 val->SetDictionary(kPrefDict, CefDictionaryValue::Create());
236 }
237
ValidateRoot(CefRefPtr<CefDictionaryValue> root,CefRefPtr<CefDictionaryValue> expected,const char * name=kPrefTest)238 void ValidateRoot(CefRefPtr<CefDictionaryValue> root,
239 CefRefPtr<CefDictionaryValue> expected,
240 const char* name = kPrefTest) {
241 EXPECT_TRUE(root->HasKey(kPrefTest));
242 EXPECT_EQ(VTYPE_DICTIONARY, root->GetType(kPrefTest));
243
244 CefRefPtr<CefDictionaryValue> actual = root->GetDictionary(kPrefTest);
245 TestDictionaryEqual(expected, actual);
246 }
247
248 // Validate getting default values.
ValidateDefaults(CefRefPtr<CefRequestContext> context,bool reset,CefRefPtr<CefWaitableEvent> event)249 void ValidateDefaults(CefRefPtr<CefRequestContext> context,
250 bool reset,
251 CefRefPtr<CefWaitableEvent> event) {
252 if (!CefCurrentlyOn(TID_UI)) {
253 CefPostTask(TID_UI,
254 base::BindOnce(ValidateDefaults, context, reset, event));
255 return;
256 }
257
258 if (reset) {
259 // Reset default values.
260 ValidateReset(context, kPrefTestBool);
261 ValidateReset(context, kPrefTestInt);
262 ValidateReset(context, kPrefTestDouble);
263 ValidateReset(context, kPrefTestString);
264 ValidateReset(context, kPrefTestList);
265 ValidateReset(context, kPrefTestDict);
266 }
267
268 // Test default values.
269 // Should match the values in CefBrowserPrefStore::CreateService.
270 ValidateBool(context, false, true);
271 ValidateInt(context, false, 2);
272 ValidateDouble(context, false, 5.0);
273 ValidateString(context, false, "default");
274 ValidateList(context, false, CefListValue::Create());
275 ValidateDict(context, false, CefDictionaryValue::Create());
276 ValidateNoExist(context, false);
277
278 // Expected value of the tests root.
279 CefRefPtr<CefDictionaryValue> expected = CefDictionaryValue::Create();
280 PopulateRootDefaults(expected);
281
282 // Test all preferences including defaults.
283 ValidateRoot(context->GetAllPreferences(true), expected);
284
285 // Test all preferences excluding defaults.
286 EXPECT_FALSE(context->GetAllPreferences(false)->HasKey(kPrefTest));
287
288 event->Signal();
289 }
290
PopulateListValue(CefRefPtr<CefListValue> val)291 void PopulateListValue(CefRefPtr<CefListValue> val) {
292 // Test list values.
293 val->SetInt(0, 54);
294 val->SetString(1, "foobar");
295 val->SetDouble(2, 99.7643);
296 }
297
PopulateDictValue(CefRefPtr<CefDictionaryValue> val)298 void PopulateDictValue(CefRefPtr<CefDictionaryValue> val) {
299 // Test dictionary values.
300 val->SetString("key1", "some string");
301 val->SetBool("key2", false);
302
303 CefRefPtr<CefListValue> list_val = CefListValue::Create();
304 PopulateListValue(list_val);
305 val->SetList("key3", list_val);
306 }
307
PopulateRootSet(CefRefPtr<CefDictionaryValue> val)308 void PopulateRootSet(CefRefPtr<CefDictionaryValue> val) {
309 CefRefPtr<CefListValue> list_val = CefListValue::Create();
310 CefRefPtr<CefDictionaryValue> dict_val = CefDictionaryValue::Create();
311
312 PopulateListValue(list_val);
313 PopulateDictValue(dict_val);
314
315 // Should match the values in ValidateSetGet and ValidateGet.
316 val->SetBool(kPrefBool, true);
317 val->SetInt(kPrefInt, 65);
318 val->SetDouble(kPrefDouble, 54.5443);
319 val->SetString(kPrefString, "My test string");
320 val->SetList(kPrefList, list_val);
321 val->SetDictionary(kPrefDict, dict_val);
322 }
323
324 // Validate getting and setting values.
ValidateSetGet(CefRefPtr<CefRequestContext> context,CefRefPtr<CefWaitableEvent> event)325 void ValidateSetGet(CefRefPtr<CefRequestContext> context,
326 CefRefPtr<CefWaitableEvent> event) {
327 if (!CefCurrentlyOn(TID_UI)) {
328 CefPostTask(TID_UI, base::BindOnce(ValidateSetGet, context, event));
329 return;
330 }
331
332 CefRefPtr<CefListValue> list_val = CefListValue::Create();
333 CefRefPtr<CefDictionaryValue> dict_val = CefDictionaryValue::Create();
334
335 PopulateListValue(list_val);
336 PopulateDictValue(dict_val);
337
338 // Test setting/getting values.
339 // Should match the values in PopulateRootSet and ValidateGet.
340 ValidateBool(context, true, true);
341 ValidateInt(context, true, 65);
342 ValidateDouble(context, true, 54.5443);
343 ValidateString(context, true, "My test string");
344 ValidateList(context, true, list_val);
345 ValidateDict(context, true, dict_val);
346 ValidateNoExist(context, true);
347
348 // Expected value of the tests root.
349 CefRefPtr<CefDictionaryValue> expected = CefDictionaryValue::Create();
350 PopulateRootSet(expected);
351
352 // Validate all preferences including defaults.
353 ValidateRoot(context->GetAllPreferences(true), expected);
354
355 // Validate all preferences excluding defaults.
356 ValidateRoot(context->GetAllPreferences(false), expected);
357
358 event->Signal();
359 }
360
361 // Validate getting values.
ValidateGet(CefRefPtr<CefRequestContext> context,CefRefPtr<CefWaitableEvent> event)362 void ValidateGet(CefRefPtr<CefRequestContext> context,
363 CefRefPtr<CefWaitableEvent> event) {
364 if (!CefCurrentlyOn(TID_UI)) {
365 CefPostTask(TID_UI, base::BindOnce(ValidateGet, context, event));
366 return;
367 }
368
369 CefRefPtr<CefListValue> list_val = CefListValue::Create();
370 CefRefPtr<CefDictionaryValue> dict_val = CefDictionaryValue::Create();
371
372 PopulateListValue(list_val);
373 PopulateDictValue(dict_val);
374
375 // Test getting values.
376 // Should match the values in PopulateRootSet and ValidateSetGet.
377 ValidateBool(context, false, true);
378 ValidateInt(context, false, 65);
379 ValidateDouble(context, false, 54.5443);
380 ValidateString(context, false, "My test string");
381 ValidateList(context, false, list_val);
382 ValidateDict(context, false, dict_val);
383 ValidateNoExist(context, false);
384
385 // Expected value of the tests root.
386 CefRefPtr<CefDictionaryValue> expected = CefDictionaryValue::Create();
387 PopulateRootSet(expected);
388
389 // Validate all preferences including defaults.
390 ValidateRoot(context->GetAllPreferences(true), expected);
391
392 // Validate all preferences excluding defaults.
393 ValidateRoot(context->GetAllPreferences(false), expected);
394
395 event->Signal();
396 }
397
398 // No-op implementation.
399 class TestRequestContextHandler : public CefRequestContextHandler {
400 public:
TestRequestContextHandler()401 TestRequestContextHandler() {}
TestRequestContextHandler(CefRefPtr<CefWaitableEvent> event)402 explicit TestRequestContextHandler(CefRefPtr<CefWaitableEvent> event)
403 : event_(event) {}
404
OnRequestContextInitialized(CefRefPtr<CefRequestContext> context)405 void OnRequestContextInitialized(
406 CefRefPtr<CefRequestContext> context) override {
407 if (event_) {
408 event_->Signal();
409 event_ = nullptr;
410 }
411 }
412
413 private:
414 CefRefPtr<CefWaitableEvent> event_;
415
416 IMPLEMENT_REFCOUNTING(TestRequestContextHandler);
417 };
418
419 } // namespace
420
421 // Verify default preference values on the global context.
TEST(PreferenceTest,GlobalDefaults)422 TEST(PreferenceTest, GlobalDefaults) {
423 CefRefPtr<CefWaitableEvent> event =
424 CefWaitableEvent::CreateWaitableEvent(true, false);
425
426 CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
427 EXPECT_TRUE(context.get());
428
429 ValidateDefaults(context, false, event);
430 event->Wait();
431 }
432
433 // Verify setting/getting preference values on the global context.
TEST(PreferenceTest,GlobalSetGet)434 TEST(PreferenceTest, GlobalSetGet) {
435 CefRefPtr<CefWaitableEvent> event =
436 CefWaitableEvent::CreateWaitableEvent(true, false);
437
438 CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
439 EXPECT_TRUE(context.get());
440
441 ValidateSetGet(context, event);
442 event->Wait();
443
444 // Reset to the default values.
445 ValidateDefaults(context, true, event);
446 event->Wait();
447 }
448
449 // Verify setting/getting preference values on shared global contexts.
TEST(PreferenceTest,GlobalSetGetShared)450 TEST(PreferenceTest, GlobalSetGetShared) {
451 CefRefPtr<CefWaitableEvent> event =
452 CefWaitableEvent::CreateWaitableEvent(true, false);
453
454 CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
455 EXPECT_TRUE(context.get());
456
457 // Sharing storage.
458 CefRefPtr<CefRequestContext> context2 =
459 CefRequestContext::CreateContext(context, nullptr);
460 EXPECT_TRUE(context2.get());
461
462 // Sharing storage.
463 CefRefPtr<CefRequestContext> context3 =
464 CefRequestContext::CreateContext(context, new TestRequestContextHandler);
465 EXPECT_TRUE(context3.get());
466
467 // Unassociated context.
468 CefRequestContextSettings settings;
469 CefRefPtr<CefRequestContext> context4 = CefRequestContext::CreateContext(
470 settings, new TestRequestContextHandler(event));
471 EXPECT_TRUE(context4.get());
472 // Wait for the context to be fully initialized.
473 event->Wait();
474
475 // Set/get the values on the first context.
476 *PendingAction() = "Set/get the values on the first context";
477 ValidateSetGet(context, event);
478 event->Wait();
479
480 // Get the values from the 2nd and 3rd contexts. They should be the same.
481 *PendingAction() = "Get the values from the 2nd context.";
482 ValidateGet(context2, event);
483 event->Wait();
484 *PendingAction() = "Get the values from the 3rd context.";
485 ValidateGet(context3, event);
486 event->Wait();
487
488 // Get the values from the 4th context.
489 *PendingAction() = "Get the values from the 4th context.";
490 if (IsChromeRuntimeEnabled()) {
491 // With the Chrome runtime, prefs set via an incognito profile will become
492 // an overlay on top of the global (parent) profile. The incognito profile
493 // shares the prefs in this case because they were set via the global
494 // profile.
495 ValidateGet(context4, event);
496 } else {
497 // They should be at the default.
498 ValidateDefaults(context4, false, event);
499 }
500 event->Wait();
501
502 // Reset to the default values.
503 *PendingAction() = "Reset to the default values.";
504 ValidateDefaults(context, true, event);
505 event->Wait();
506 }
507
508 // Verify default preference values on a custom context.
TEST(PreferenceTest,CustomDefaults)509 TEST(PreferenceTest, CustomDefaults) {
510 CefRefPtr<CefWaitableEvent> event =
511 CefWaitableEvent::CreateWaitableEvent(true, false);
512
513 CefRequestContextSettings settings;
514 CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
515 settings, new TestRequestContextHandler(event));
516 EXPECT_TRUE(context.get());
517 // Wait for the context to be fully initialized.
518 event->Wait();
519
520 ValidateDefaults(context, false, event);
521 event->Wait();
522 }
523
524 // Verify setting/getting preference values on a custom context.
TEST(PreferenceTest,CustomSetGet)525 TEST(PreferenceTest, CustomSetGet) {
526 CefRefPtr<CefWaitableEvent> event =
527 CefWaitableEvent::CreateWaitableEvent(true, false);
528
529 CefRequestContextSettings settings;
530 CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
531 settings, new TestRequestContextHandler(event));
532 EXPECT_TRUE(context.get());
533 // Wait for the context to be fully initialized.
534 event->Wait();
535
536 ValidateSetGet(context, event);
537 event->Wait();
538
539 // Reset to the default values.
540 ValidateDefaults(context, true, event);
541 event->Wait();
542 }
543
544 // Verify setting/getting preference values on shared custom contexts.
TEST(PreferenceTest,CustomSetGetShared)545 TEST(PreferenceTest, CustomSetGetShared) {
546 CefRefPtr<CefWaitableEvent> event =
547 CefWaitableEvent::CreateWaitableEvent(true, false);
548
549 CefRequestContextSettings settings;
550 CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
551 settings, new TestRequestContextHandler(event));
552 EXPECT_TRUE(context.get());
553 // Wait for the context to be fully initialized.
554 event->Wait();
555
556 // Sharing storage.
557 CefRefPtr<CefRequestContext> context2 =
558 CefRequestContext::CreateContext(context, nullptr);
559 EXPECT_TRUE(context2.get());
560
561 // Sharing storage.
562 CefRefPtr<CefRequestContext> context3 =
563 CefRequestContext::CreateContext(context, new TestRequestContextHandler);
564 EXPECT_TRUE(context3.get());
565
566 // Unassociated context.
567 CefRefPtr<CefRequestContext> context4 = CefRequestContext::CreateContext(
568 settings, new TestRequestContextHandler(event));
569 EXPECT_TRUE(context4.get());
570 // Wait for the context to be fully initialized.
571 event->Wait();
572
573 // Set/get the values on the first context.
574 *PendingAction() = "Set/get the values on the first context";
575 ValidateSetGet(context, event);
576 event->Wait();
577
578 // Get the values from the 2nd and 3d contexts. They should be the same.
579 *PendingAction() = "Get the values from the 2nd context.";
580 ValidateGet(context2, event);
581 event->Wait();
582 *PendingAction() = "Get the values from the 3rd context.";
583 ValidateGet(context3, event);
584 event->Wait();
585
586 // Get the values from the 4th context. They should be at the default.
587 // This works with the Chrome runtime because the preference changes only
588 // exist in the other incognito profile's overlay.
589 *PendingAction() = "Get the values from the 4th context.";
590 ValidateDefaults(context4, false, event);
591 event->Wait();
592
593 // Reset to the default values.
594 *PendingAction() = "Reset to the default values.";
595 ValidateDefaults(context, true, event);
596 event->Wait();
597 }
598
599 // Entry point for creating preference browser test objects.
600 // Called from client_app_delegates.cc.
CreatePreferenceBrowserTests(client::ClientAppBrowser::DelegateSet & delegates)601 void CreatePreferenceBrowserTests(
602 client::ClientAppBrowser::DelegateSet& delegates) {
603 delegates.insert(new PreferenceBrowserTest);
604 }
605