gpu: Tweak Android WebGL test expectations
[chromium-blink-merge.git] / chrome_frame / test / ie_configurator.cc
blob8f30c3030a3c6a45300556f0465ee1b85eed053e
1 // Copyright (c) 2012 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_frame/test/ie_configurator.h"
7 #include <windows.h>
8 #include <objbase.h>
10 #include <ios>
11 #include <list>
12 #include <vector>
14 #include "base/compiler_specific.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/string16.h"
17 #include "base/time/time.h"
18 #include "base/win/registry.h"
19 #include "chrome_frame/chrome_tab.h"
20 #include "chrome_frame/test/chrome_frame_test_utils.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace chrome_frame_test {
25 namespace {
27 const wchar_t kKeyIEApprovedExtensions[] =
28 L"Software\\Microsoft\\Internet Explorer\\Approved Extensions\\";
29 const wchar_t kKeyIEInformationBar[] =
30 L"Software\\Microsoft\\Internet Explorer\\InformationBar";
31 const wchar_t kKeyIEMain[] =
32 L"Software\\Microsoft\\Internet Explorer\\Main";
33 const wchar_t kKeyIEPhishingFilter[] =
34 L"Software\\Microsoft\\Internet Explorer\\PhishingFilter";
35 const wchar_t kKeyIEBrowserEmulation[] =
36 L"Software\\Microsoft\\Internet Explorer\\BrowserEmulation";
37 const wchar_t kKeyPoliciesExt[] =
38 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ext";
39 const wchar_t kValueEnabledV8[] = L"EnabledV8";
40 const wchar_t kValueEnabledV9[] = L"EnabledV9";
41 const wchar_t kValueFirstTime[] = L"FirstTime";
42 const wchar_t kValueIE8Completed[] = L"IE8RunOncePerInstallCompleted";
43 const wchar_t kValueIE8CompletionTime[] = L"IE8RunOnceCompletionTime";
44 const wchar_t kValueIE8RunOnceLastShown[] = L"IE8RunOnceLastShown";
45 const wchar_t kValueIE8RunOnceLastShownTimestamp[] =
46 L"IE8RunOnceLastShown_TIMESTAMP";
47 const wchar_t kValueIE8TourNoShow[] = L"IE8TourNoShow";
48 const wchar_t kValueIE9Completed[] = L"IE9RunOncePerInstallCompleted";
49 const wchar_t kValueIE9CompletionTime[] = L"IE9RunOnceCompletionTime";
50 const wchar_t kValueIE9RunOnceLastShown[] = L"IE9RunOnceLastShown";
51 const wchar_t kValueIE9RunOnceLastShownTimestamp[] =
52 L"IE9RunOnceLastShown_TIMESTAMP";
53 const wchar_t kValueIE9TourNoShow[] = L"IE9TourNoShow";
54 const wchar_t kValueIE10Completed[] = L"IE10RunOncePerInstallCompleted";
55 const wchar_t kValueIE10CompletionTime[] = L"IE10RunOnceCompletionTime";
56 const wchar_t kValueIE10RunOnceLastShown[] = L"IE10RunOnceLastShown";
57 const wchar_t kValueIE10RunOnceLastShownTimestamp[] =
58 L"IE10RunOnceLastShown_TIMESTAMP";
59 const wchar_t kValueIgnoreFrameApprovalCheck[] = L"IgnoreFrameApprovalCheck";
60 const wchar_t kValueMSCompatibilityMode[] = L"MSCompatibilityMode";
62 // A helper class that accumulate a set of registry mutations and corresponding
63 // undo data via calls to its Add*() methods. The mutations can be applied to
64 // the registry (repeatedly, if desired) via a call to Apply(). Revert() can be
65 // called to apply the accumulated undo data.
66 class RegistrySetter {
67 public:
68 RegistrySetter();
69 ~RegistrySetter();
71 // Adds a mutation that sets a REG_DWORD registry value, creating any
72 // intermediate keys as necessary. |key| and |value| must remain valid
73 // throughout all calls to Apply().
74 void AddDWORDValue(HKEY root, const wchar_t* key, const wchar_t* value,
75 DWORD data);
77 // Adds a mutation that assigns a FILETIME to a REG_BINARY registry value,
78 // creating any intermediate keys as necessary. |key| and |value| must remain
79 // valid throughout all calls to Apply().
80 void AddFILETIMEValue(HKEY root, const wchar_t* key, const wchar_t* value,
81 FILETIME data);
83 // Applies all mutations in the order they were added. Errors encountered
84 // along the way are logged, but do not stop progress.
85 void Apply() const;
87 // Applies the undo data in the reverse order that their corresponding
88 // mutations were added.
89 void Revert() const;
91 private:
92 // The data for an individual registry value. A non-existent value is
93 // indicated by type = REG_NONE and empty data.
94 struct RegistryData {
95 HKEY root;
96 const wchar_t* key;
97 const wchar_t* value;
98 DWORD type;
99 std::vector<uint8> data;
102 typedef std::list<RegistryData> RegistryDataList;
104 // Adds a mutation to the end of the apply list with the given data, and a
105 // mutation to the revert list with the current state of the value.
106 void AddValue(HKEY root, const wchar_t* key, const wchar_t* value, DWORD type,
107 const uint8* value_begin, size_t value_len);
109 // Add a mutation to the revert list that restores a registry value to its
110 // current state. This only adds entries to set or remove |value|. If
111 // portions of the hierarchy identified by |key| do not exist, but are created
112 // between the invocation of this method and the time the revert list is
113 // applied, only |value| is deleted upon revert (intermediate keys are not
114 // deleted).
115 void SaveCurrentValue(HKEY root, const wchar_t* key, const wchar_t* value);
117 // Applies all mutations in |data_list| in order.
118 static void ApplyList(const RegistryDataList& data_list);
120 RegistryDataList apply_list_;
121 RegistryDataList revert_list_;
123 DISALLOW_COPY_AND_ASSIGN(RegistrySetter);
126 // A Google Test event listener that delegates to a configurator.
127 class ConfiguratorDriver : public testing::EmptyTestEventListener {
128 public:
129 explicit ConfiguratorDriver(IEConfigurator* configurator);
130 virtual ~ConfiguratorDriver();
132 virtual void OnTestProgramStart(const testing::UnitTest& unit_test) OVERRIDE;
133 virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE;
134 virtual void OnTestProgramEnd(const testing::UnitTest& unit_test) OVERRIDE;
136 private:
137 scoped_ptr<IEConfigurator> configurator_;
138 DISALLOW_COPY_AND_ASSIGN(ConfiguratorDriver);
141 // A configurator for Internet Explorer 7.
142 class IE7Configurator : public IEConfigurator {
143 public:
144 IE7Configurator();
145 virtual ~IE7Configurator();
147 virtual void Initialize() OVERRIDE;
148 virtual void ApplySettings() OVERRIDE;
149 virtual void RevertSettings() OVERRIDE;
151 private:
152 RegistrySetter setter_;
154 DISALLOW_COPY_AND_ASSIGN(IE7Configurator);
157 // A configurator for Internet Explorer 8, 9, and 10.
158 class ModernIEConfigurator : public IEConfigurator {
159 public:
160 explicit ModernIEConfigurator(IEVersion ie_version);
161 virtual ~ModernIEConfigurator();
163 virtual void Initialize() OVERRIDE;
164 virtual void ApplySettings() OVERRIDE;
165 virtual void RevertSettings() OVERRIDE;
167 private:
168 // The names of the registry values used to determine if IE's one-time
169 // initialization has been completed.
170 struct RunOnceValueNames {
171 // This DWORD value is non-zero once initialization has been completed.
172 const wchar_t* completed;
173 // This 8-byte binary value is the FILETIME of completion.
174 const wchar_t* completion_time;
175 // This DWORD value is non-zero if run-once was previously deferred.
176 const wchar_t* last_shown;
177 // This 8-byte binary value is the FILETIME of run-once deferral.
178 const wchar_t* last_shown_timestamp;
181 static const RunOnceValueNames kIE8ValueNames;
182 static const RunOnceValueNames kIE9ValueNames;
183 static const RunOnceValueNames kIE10ValueNames;
185 static const RunOnceValueNames* RunOnceNamesForVersion(IEVersion ie_version);
186 bool IsPerUserSetupComplete();
187 static string16 GetChromeFrameBHOCLSID();
188 static bool IsAddonPromptDisabledForChromeFrame();
190 const IEVersion ie_version_;
191 const RunOnceValueNames* run_once_value_names_;
192 RegistrySetter setter_;
194 DISALLOW_COPY_AND_ASSIGN(ModernIEConfigurator);
197 // RegistrySetter implementation.
199 RegistrySetter::RegistrySetter() {
202 RegistrySetter::~RegistrySetter() {
205 void RegistrySetter::AddValue(HKEY root,
206 const wchar_t* key,
207 const wchar_t* value,
208 DWORD type,
209 const uint8* value_begin,
210 size_t value_len) {
211 RegistryData the_data = {
212 root,
213 key,
214 value,
215 type,
216 std::vector<uint8>(value_begin, value_begin + value_len)
218 apply_list_.push_back(the_data);
219 SaveCurrentValue(root, key, value);
222 void RegistrySetter::SaveCurrentValue(HKEY root,
223 const wchar_t* key,
224 const wchar_t* value) {
225 base::win::RegKey the_key;
226 RegistryData the_data = { root, key, value, REG_NONE };
228 LONG result = the_key.Open(root, key, KEY_QUERY_VALUE);
229 if (result == ERROR_SUCCESS) {
230 DWORD size = 0;
231 result = the_key.ReadValue(value, NULL, &size, &the_data.type);
232 if (result == ERROR_FILE_NOT_FOUND) {
233 // Add a mutation to delete the value.
234 the_data.type = REG_NONE;
235 revert_list_.push_front(the_data);
236 } else if (result == ERROR_SUCCESS) {
237 the_data.data.resize(size);
238 result = the_key.ReadValue(value, &the_data.data[0], &size,
239 &the_data.type);
240 if (result == ERROR_SUCCESS) {
241 revert_list_.push_front(the_data);
242 } else {
243 ::SetLastError(result);
244 PLOG(ERROR) << __FUNCTION__ << " unexpected error reading data for "
245 << value << " from key " << key
246 << ". The current value will not be restored upon revert.";
248 } else {
249 ::SetLastError(result);
250 PLOG(ERROR) << __FUNCTION__ << " unexpected error reading " << value
251 << " from key " << key
252 << ". The current value will not be restored upon revert.";
254 } else if (result == ERROR_FILE_NOT_FOUND) {
255 // Add a mutation to delete the value (but not any keys).
256 revert_list_.push_front(the_data);
257 } else {
258 ::SetLastError(result);
259 PLOG(ERROR) << __FUNCTION__ << " unexpected error opening key " << key
260 << " to read value " << value
261 << ". The current value will not be restored upon revert.";
265 void RegistrySetter::AddDWORDValue(HKEY root,
266 const wchar_t* key,
267 const wchar_t* value,
268 DWORD data) {
269 const uint8* data_ptr = reinterpret_cast<uint8*>(&data);
270 AddValue(root, key, value, REG_DWORD, data_ptr, sizeof(data));
273 void RegistrySetter::AddFILETIMEValue(HKEY root,
274 const wchar_t* key,
275 const wchar_t* value,
276 FILETIME data) {
277 const uint8* data_ptr = reinterpret_cast<uint8*>(&data);
278 AddValue(root, key, value, REG_BINARY, data_ptr, sizeof(data));
281 // static
282 void RegistrySetter::ApplyList(const RegistryDataList& data_list) {
283 base::win::RegKey key;
284 LONG result = ERROR_SUCCESS;
285 for (RegistryDataList::const_iterator scan(data_list.begin());
286 scan != data_list.end(); ++scan) {
287 const RegistryData& data = *scan;
288 const bool do_delete = (data.type == REG_NONE && data.data.empty());
289 result = do_delete ?
290 key.Open(data.root, data.key, KEY_SET_VALUE) :
291 key.Create(data.root, data.key, KEY_SET_VALUE);
292 if (result == ERROR_SUCCESS) {
293 if (do_delete) {
294 result = key.DeleteValue(data.value);
295 } else {
296 result = key.WriteValue(data.value,
297 data.data.empty() ? NULL : &data.data[0],
298 data.data.size(), data.type);
300 if (result != ERROR_SUCCESS) {
301 ::SetLastError(result);
302 PLOG(ERROR) << "Failed to " << (do_delete ? "delete" : "set")
303 << " value " << data.value
304 << " in registry key " << data.key
305 << " in hive " << std::hex <<data.root << std::dec;
307 } else if (!do_delete || result != ERROR_FILE_NOT_FOUND) {
308 ::SetLastError(result);
309 PLOG(ERROR) << "Failed to create/open registry key " << data.key
310 << " in hive " << std::hex << data.root << std::dec;
315 void RegistrySetter::Apply() const {
316 ApplyList(apply_list_);
319 void RegistrySetter::Revert() const {
320 ApplyList(revert_list_);
323 // ConfiguratorDriver implementation.
325 ConfiguratorDriver::ConfiguratorDriver(IEConfigurator* configurator)
326 : configurator_(configurator) {
327 DCHECK(configurator);
330 ConfiguratorDriver::~ConfiguratorDriver() {
333 void ConfiguratorDriver::OnTestProgramStart(
334 const testing::UnitTest& unit_test) {
335 configurator_->Initialize();
338 void ConfiguratorDriver::OnTestStart(const testing::TestInfo& test_info) {
339 configurator_->ApplySettings();
342 void ConfiguratorDriver::OnTestProgramEnd(const testing::UnitTest& unit_test) {
343 configurator_->RevertSettings();
346 // IE7Configurator implementation
348 IE7Configurator::IE7Configurator() {
351 IE7Configurator::~IE7Configurator() {
354 void IE7Configurator::Initialize() {
355 // Suppress the friendly "Hi! I popped up an info bar for you. Did you see
356 // the info bar I just showed you? There's a yellow thing in your IE window
357 // that wasn't there before! I call it an Information Bar. Did you notice
358 // the Information Bar?" dialog that it likes to show.
359 setter_.AddDWORDValue(HKEY_CURRENT_USER, kKeyIEInformationBar,
360 kValueFirstTime, 0);
363 void IE7Configurator::ApplySettings() {
364 setter_.Apply();
367 void IE7Configurator::RevertSettings() {
368 setter_.Revert();
371 // ModernIEConfigurator implementation
373 const ModernIEConfigurator::RunOnceValueNames
374 ModernIEConfigurator::kIE8ValueNames = {
375 kValueIE8Completed,
376 kValueIE8CompletionTime,
377 kValueIE8RunOnceLastShown,
378 kValueIE8RunOnceLastShownTimestamp,
381 const ModernIEConfigurator::RunOnceValueNames
382 ModernIEConfigurator::kIE9ValueNames = {
383 kValueIE9Completed,
384 kValueIE9CompletionTime,
385 kValueIE9RunOnceLastShown,
386 kValueIE9RunOnceLastShownTimestamp,
389 const ModernIEConfigurator::RunOnceValueNames
390 ModernIEConfigurator::kIE10ValueNames = {
391 kValueIE10Completed,
392 kValueIE10CompletionTime,
393 kValueIE10RunOnceLastShown,
394 kValueIE10RunOnceLastShownTimestamp,
397 ModernIEConfigurator::ModernIEConfigurator(IEVersion ie_version)
398 : ie_version_(ie_version),
399 run_once_value_names_(RunOnceNamesForVersion(ie_version)) {
402 ModernIEConfigurator::~ModernIEConfigurator() {
405 // static
406 const ModernIEConfigurator::RunOnceValueNames*
407 ModernIEConfigurator::RunOnceNamesForVersion(
408 IEVersion ie_version) {
409 switch (ie_version) {
410 case IE_8:
411 return &kIE8ValueNames;
412 break;
413 case IE_9:
414 return &kIE9ValueNames;
415 break;
416 case IE_10:
417 return &kIE10ValueNames;
418 break;
419 default:
420 NOTREACHED();
422 return NULL;
425 // Returns true if the per-user setup is complete.
426 bool ModernIEConfigurator::IsPerUserSetupComplete() {
427 bool is_complete = false;
428 base::win::RegKey key_main;
430 if (key_main.Open(HKEY_CURRENT_USER, kKeyIEMain,
431 KEY_QUERY_VALUE) != ERROR_SUCCESS) {
432 return false;
435 DWORD dword_value = 0;
436 FILETIME shown_time = {};
437 FILETIME completion_time = {};
438 DWORD size = sizeof(completion_time);
440 // See if the user has seen the first-run prompt.
441 if (key_main.ReadValue(run_once_value_names_->last_shown_timestamp,
442 &shown_time, &size, NULL) != ERROR_SUCCESS ||
443 size != sizeof(shown_time)) {
444 return false;
447 // See if setup was completed.
448 if (key_main.ReadValue(run_once_value_names_->completion_time,
449 &completion_time, &size, NULL) != ERROR_SUCCESS ||
450 size != sizeof(completion_time)) {
451 return false;
454 // See if setup was completed after the last time the prompt was shown.
455 base::Time time_shown = base::Time::FromFileTime(shown_time);
456 base::Time time_completed = base::Time::FromFileTime(completion_time);
457 if (time_shown >= time_completed)
458 return false;
460 return true;
463 // Returns the path to the IE9 Approved Extensions key for Chrome Frame.
464 // static
465 string16 ModernIEConfigurator::GetChromeFrameBHOCLSID() {
466 string16 bho_guid(39, L'\0');
467 int guid_len = StringFromGUID2(CLSID_ChromeFrameBHO, &bho_guid[0],
468 bho_guid.size());
469 DCHECK_EQ(guid_len, static_cast<int>(bho_guid.size()));
470 bho_guid.resize(guid_len - 1);
471 return bho_guid;
474 // Returns true if the add-on enablement prompt is disabled by Group Policy.
475 // static
476 bool ModernIEConfigurator::IsAddonPromptDisabledForChromeFrame() {
477 bool is_disabled = false;
478 base::win::RegKey key;
480 // See if the prompt is disabled for this user of IE.
481 if (key.Open(HKEY_CURRENT_USER, kKeyIEApprovedExtensions,
482 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
483 DWORD type = REG_NONE;
484 DWORD size = 0;
485 if (key.ReadValue(GetChromeFrameBHOCLSID().c_str(), NULL, &size,
486 &type) == ERROR_SUCCESS &&
487 type == REG_BINARY) {
488 is_disabled = true;
492 // Now check if the prompt is disabled for all add-ons via Group Policy.
493 if (!is_disabled &&
494 key.Open(HKEY_LOCAL_MACHINE, kKeyPoliciesExt,
495 KEY_QUERY_VALUE) == ERROR_SUCCESS) {
496 DWORD ignore = 0;
497 if (key.ReadValueDW(kValueIgnoreFrameApprovalCheck,
498 &ignore) == ERROR_SUCCESS &&
499 ignore != 0) {
500 is_disabled = true;
504 return is_disabled;
507 void ModernIEConfigurator::Initialize() {
508 // Check for per-user IE setup.
509 if (!IsPerUserSetupComplete()) {
510 base::Time time(base::Time::Now());
511 const HKEY root = HKEY_CURRENT_USER;
512 // Suppress the "Set up Internet Explorer" dialog.
513 setter_.AddDWORDValue(root, kKeyIEMain, run_once_value_names_->last_shown,
515 setter_.AddDWORDValue(root, kKeyIEMain, run_once_value_names_->completed,
517 setter_.AddFILETIMEValue(root, kKeyIEMain,
518 run_once_value_names_->last_shown_timestamp,
519 time.ToFileTime());
520 time += base::TimeDelta::FromMilliseconds(10);
521 setter_.AddFILETIMEValue(root, kKeyIEMain,
522 run_once_value_names_->completion_time,
523 time.ToFileTime());
524 if (ie_version_ < IE_10) {
525 // Don't show a tour of IE 8 and 9.
526 setter_.AddDWORDValue(
527 root,
528 kKeyIEMain,
529 (ie_version_ == IE_8 ? kValueIE8TourNoShow : kValueIE9TourNoShow),
532 // Turn off the phishing filter.
533 setter_.AddDWORDValue(
534 root,
535 kKeyIEPhishingFilter,
536 (ie_version_ == IE_8 ? kValueEnabledV8 : kValueEnabledV9),
538 // Don't download compatibility view lists.
539 setter_.AddDWORDValue(root, kKeyIEBrowserEmulation,
540 kValueMSCompatibilityMode, 0);
543 // Turn off the "'Foo' add-on from 'Bar' is ready for use." prompt via Group
544 // Policy.
545 if (!IsAddonPromptDisabledForChromeFrame()) {
546 setter_.AddDWORDValue(HKEY_LOCAL_MACHINE, kKeyPoliciesExt,
547 kValueIgnoreFrameApprovalCheck, 1);
551 void ModernIEConfigurator::ApplySettings() {
552 setter_.Apply();
555 void ModernIEConfigurator::RevertSettings() {
556 setter_.Revert();
559 } // namespace
561 // Configurator implementation.
563 IEConfigurator::IEConfigurator() {
566 IEConfigurator::~IEConfigurator() {
569 IEConfigurator* CreateConfigurator() {
570 IEConfigurator* configurator = NULL;
572 IEVersion ie_version = GetInstalledIEVersion();
573 switch (ie_version) {
574 case IE_7:
575 configurator = new IE7Configurator();
576 break;
577 case IE_8:
578 case IE_9:
579 case IE_10:
580 configurator = new ModernIEConfigurator(ie_version);
581 break;
582 default:
583 break;
586 return configurator;
589 void InstallIEConfigurator() {
590 IEConfigurator* configurator = CreateConfigurator();
592 if (configurator != NULL) {
593 testing::UnitTest::GetInstance()->listeners().Append(
594 new ConfiguratorDriver(configurator));
598 } // namespace chrome_frame_test