1 // Copyright (c) 2013 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. 4 5 #include "chrome/test/perf/perf_ui_test_suite.h" 6 7 #include "base/file_util.h" 8 #include "base/json/json_file_value_serializer.h" 9 #include "base/lazy_instance.h" 10 #include "base/logging.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/path_service.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/threading/platform_thread.h" 16 #include "chrome/browser/themes/browser_theme_pack.h" 17 #include "chrome/common/chrome_constants.h" 18 #include "chrome/common/chrome_paths.h" 19 #include "chrome/test/perf/generate_profile.h" 20 #include "content/public/test/test_browser_thread.h" 21 #include "extensions/common/extension.h" 22 23 #if defined(OS_WIN) 24 #include <atlbase.h> 25 #include "ui/base/resource/resource_bundle_win.h" 26 #endif 27 28 using content::BrowserThread; 29 using extensions::Extension; 30 31 namespace { 32 33 const int kNumURLs = 20000; 34 35 const char kThemeExtension[] = "mblmlcbknbnfebdfjnolmcapmdofhmme"; 36 37 base::LazyInstance<base::FilePath> g_default_profile_dir = 38 LAZY_INSTANCE_INITIALIZER; 39 base::LazyInstance<base::FilePath> g_complex_profile_dir = 40 LAZY_INSTANCE_INITIALIZER; 41 42 } // namespace 43 44 PerfUITestSuite::PerfUITestSuite(int argc, char** argv) 45 : UITestSuite(argc, argv) { 46 base::PlatformThread::SetName("Tests_Main"); 47 } 48 49 PerfUITestSuite::~PerfUITestSuite() { 50 } 51 52 base::FilePath PerfUITestSuite::GetPathForProfileType( 53 ProfileType profile_type) { 54 switch (profile_type) { 55 case DEFAULT_THEME: 56 return g_default_profile_dir.Get(); 57 case COMPLEX_THEME: 58 return g_complex_profile_dir.Get(); 59 default: 60 NOTREACHED(); 61 return base::FilePath(); 62 } 63 } 64 65 void PerfUITestSuite::Initialize() { 66 #if defined(OS_WIN) 67 // On Windows, make sure we've loaded the main chrome dll for its resource 68 // before we let our parent class initialize the shared resource bundle 69 // infrastructure. We have to do this manually because the extension system 70 // uses several resources which, on Windows, are only compiled into the 71 // browser DLL, but the base chrome testing stuff is used outside of browser. 72 // 73 // TODO(darin): Kill this once http://crbug.com/52609 is fixed. 74 base::FilePath dll; 75 PathService::Get(base::DIR_MODULE, &dll); 76 dll = dll.Append(chrome::kBrowserResourcesDll); 77 HMODULE res_mod = ::LoadLibraryExW(dll.value().c_str(), 78 NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); 79 DCHECK(res_mod); 80 _AtlBaseModule.SetResourceInstance(res_mod); 81 82 ui::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance()); 83 #endif 84 85 UITestSuite::Initialize(); 86 87 if (!default_profile_dir_.CreateUniqueTempDir()) { 88 LOG(FATAL) << "Failed to create default profile directory..."; 89 } 90 91 // Build a profile in default profile dir. 92 base::FilePath default_path = 93 default_profile_dir_.path().AppendASCII("Default"); 94 if (!GenerateProfile(TOP_SITES, kNumURLs, default_path)) { 95 LOG(FATAL) << "Failed to generate default profile for tests..."; 96 } 97 98 g_default_profile_dir.Get() = default_profile_dir_.path(); 99 100 if (!complex_profile_dir_.CreateUniqueTempDir()) { 101 LOG(FATAL) << "Failed to create complex profile directory..."; 102 } 103 104 if (!base::CopyDirectory(default_path, 105 complex_profile_dir_.path(), 106 true)) { 107 LOG(FATAL) << "Failed to copy data to complex profile directory..."; 108 } 109 110 // Copy the Extensions directory from the template into the 111 // complex_profile_dir dir. 112 base::FilePath base_data_dir; 113 if (!PathService::Get(chrome::DIR_TEST_DATA, &base_data_dir)) 114 LOG(FATAL) << "Failed to fetch test data dir"; 115 116 base_data_dir = base_data_dir.AppendASCII("profiles"); 117 base_data_dir = base_data_dir.AppendASCII("profile_with_complex_theme"); 118 base_data_dir = base_data_dir.AppendASCII("Default"); 119 120 if (!base::CopyDirectory(base_data_dir, complex_profile_dir_.path(), true)) 121 LOG(FATAL) << "Failed to copy default to complex profile"; 122 123 // Parse the manifest and make a temporary extension object because the 124 // theme system takes extensions as input. 125 base::FilePath extension_base = 126 complex_profile_dir_.path() 127 .AppendASCII("Default") 128 .AppendASCII("Extensions") 129 .AppendASCII(kThemeExtension) 130 .AppendASCII("1.1"); 131 BuildCachedThemePakIn(extension_base); 132 133 g_complex_profile_dir.Get() = complex_profile_dir_.path(); 134 } 135 136 void PerfUITestSuite::BuildCachedThemePakIn( 137 const base::FilePath& extension_base) { 138 int error_code = 0; 139 std::string error; 140 JSONFileValueSerializer serializer( 141 extension_base.AppendASCII("manifest.json")); 142 scoped_ptr<DictionaryValue> valid_value(static_cast<DictionaryValue*>( 143 serializer.Deserialize(&error_code, &error))); 144 if (error_code != 0 || !valid_value) 145 LOG(FATAL) << "Error parsing theme manifest: " << error; 146 147 scoped_refptr<Extension> extension = 148 Extension::Create(extension_base, 149 extensions::Manifest::INVALID_LOCATION, 150 *valid_value, 151 Extension::NO_FLAGS, 152 &error); 153 if (!extension.get()) 154 LOG(FATAL) << "Error loading theme extension: " << error; 155 156 // Build the "Cached Theme.pak" file in the template. (It's not committed 157 // both because committing large binary files is bad in a git world and 158 // because people don't remember to update it anyway, meaning we usually 159 // have the theme rebuild penalty in our data.) 160 base::MessageLoopForUI message_loop_; 161 content::TestBrowserThread ui_thread_(BrowserThread::UI, &message_loop_); 162 content::TestBrowserThread file_thread_(BrowserThread::FILE, 163 &message_loop_); 164 165 scoped_refptr<BrowserThemePack> theme( 166 BrowserThemePack::BuildFromExtension(extension.get())); 167 if (!theme.get()) 168 LOG(FATAL) << "Failed to load theme from extension"; 169 170 theme->WriteToDisk(extension_base.AppendASCII("Cached Theme.pak")); 171 } 172