OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/support/platform_support.h" | 5 #include "webkit/support/platform_support.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 #include <AvailabilityMacros.h> | 8 #include <AvailabilityMacros.h> |
9 #import <Foundation/Foundation.h> | 9 #import <Foundation/Foundation.h> |
10 #import <objc/objc-runtime.h> | 10 #import <objc/objc-runtime.h> |
11 | 11 |
12 #include "base/base_paths.h" | 12 #include "base/base_paths.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/mac/bundle_locations.h" | |
16 #include "base/mac/mac_util.h" | |
17 #include "base/path_service.h" | 15 #include "base/path_service.h" |
18 #include "base/strings/string16.h" | 16 #include "base/strings/string16.h" |
19 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
20 #include "grit/webkit_resources.h" | 18 #include "grit/webkit_resources.h" |
21 #include "ui/base/resource/data_pack.h" | 19 #include "ui/base/resource/data_pack.h" |
22 #import "webkit/support/drt_application_mac.h" | 20 #import "webkit/support/drt_application_mac.h" |
23 #import "webkit/support/mac/DumpRenderTreePasteboard.h" | 21 #import "webkit/support/mac/DumpRenderTreePasteboard.h" |
24 #include "webkit/support/test_webkit_platform_support.h" | 22 #include "webkit/support/test_webkit_platform_support.h" |
25 | 23 |
26 static ui::DataPack* g_resource_data_pack = NULL; | |
27 | |
28 namespace webkit_support { | 24 namespace webkit_support { |
29 | 25 |
30 static NSAutoreleasePool* autorelease_pool; | 26 static NSAutoreleasePool* autorelease_pool; |
31 | 27 |
32 void BeforeInitialize() { | 28 void BeforeInitialize() { |
33 [CrDrtApplication sharedApplication]; | 29 [CrDrtApplication sharedApplication]; |
34 autorelease_pool = [[NSAutoreleasePool alloc] init]; | 30 autorelease_pool = [[NSAutoreleasePool alloc] init]; |
35 DCHECK(autorelease_pool); | 31 DCHECK(autorelease_pool); |
36 } | 32 } |
37 | 33 |
38 #if OBJC_API_VERSION == 2 | |
39 static void SwizzleAllMethods(Class imposter, Class original) { | |
40 unsigned int imposterMethodCount = 0; | |
41 Method* imposterMethods = | |
42 class_copyMethodList(imposter, &imposterMethodCount); | |
43 | |
44 unsigned int originalMethodCount = 0; | |
45 Method* originalMethods = | |
46 class_copyMethodList(original, &originalMethodCount); | |
47 | |
48 for (unsigned int i = 0; i < imposterMethodCount; i++) { | |
49 SEL imposterMethodName = method_getName(imposterMethods[i]); | |
50 | |
51 // Attempt to add the method to the original class. If it fails, the method | |
52 // already exists and we should instead exchange the implementations. | |
53 if (class_addMethod(original, | |
54 imposterMethodName, | |
55 method_getImplementation(originalMethods[i]), | |
56 method_getTypeEncoding(originalMethods[i]))) { | |
57 continue; | |
58 } | |
59 | |
60 unsigned int j = 0; | |
61 for (; j < originalMethodCount; j++) { | |
62 SEL originalMethodName = method_getName(originalMethods[j]); | |
63 if (sel_isEqual(imposterMethodName, originalMethodName)) { | |
64 break; | |
65 } | |
66 } | |
67 | |
68 // If class_addMethod failed above then the method must exist on the | |
69 // original class. | |
70 DCHECK(j < originalMethodCount) << "method wasn't found?"; | |
71 method_exchangeImplementations(imposterMethods[i], originalMethods[j]); | |
72 } | |
73 | |
74 if (imposterMethods) { | |
75 free(imposterMethods); | |
76 } | |
77 if (originalMethods) { | |
78 free(originalMethods); | |
79 } | |
80 } | |
81 #endif | |
82 | |
83 static void SwizzleNSPasteboard() { | |
84 // We replace NSPaseboard w/ the shim (from WebKit) that avoids having | |
85 // sideeffects w/ whatever the user does at the same time. | |
86 | |
87 Class imposterClass = objc_getClass("DumpRenderTreePasteboard"); | |
88 Class originalClass = objc_getClass("NSPasteboard"); | |
89 #if OBJC_API_VERSION == 0 | |
90 class_poseAs(imposterClass, originalClass); | |
91 #else | |
92 // Swizzle instance methods... | |
93 SwizzleAllMethods(imposterClass, originalClass); | |
94 // and then class methods. | |
95 SwizzleAllMethods(object_getClass(imposterClass), | |
96 object_getClass(originalClass)); | |
97 #endif | |
98 } | |
99 | |
100 void AfterInitialize() { | 34 void AfterInitialize() { |
101 // Load a data pack. | |
102 g_resource_data_pack = new ui::DataPack(ui::SCALE_FACTOR_100P); | |
103 base::FilePath resources_pak_path; | |
104 PathService::Get(base::DIR_EXE, &resources_pak_path); | |
105 resources_pak_path = resources_pak_path.Append("Content Shell.app") | |
106 .Append("Contents") | |
107 .Append("Frameworks") | |
108 .Append("Content Shell Framework.framework") | |
109 .Append("Resources") | |
110 .Append("content_shell.pak"); | |
111 if (!g_resource_data_pack->LoadFromPath(resources_pak_path)) { | |
112 LOG(FATAL) << "failed to load DumpRenderTree.pak"; | |
113 } | |
114 } | 35 } |
115 | 36 |
116 void BeforeShutdown() { | 37 void BeforeShutdown() { |
117 } | 38 } |
118 | 39 |
119 void AfterShutdown() { | 40 void AfterShutdown() { |
120 [DumpRenderTreePasteboard releaseLocalPasteboards]; | 41 [DumpRenderTreePasteboard releaseLocalPasteboards]; |
121 [autorelease_pool drain]; | 42 [autorelease_pool drain]; |
122 delete g_resource_data_pack; | |
123 } | 43 } |
124 | 44 |
125 } // namespace webkit_support | 45 } // namespace webkit_support |
126 | 46 |
127 base::string16 TestWebKitPlatformSupport::GetLocalizedString(int message_id) { | |
128 // |g_resource_data_pack| is null on unit tests. | |
129 // But som unit tests reach GetLocalizedString(). | |
130 if (!g_resource_data_pack) | |
131 return base::string16(); | |
132 base::StringPiece res; | |
133 if (!g_resource_data_pack->GetStringPiece(message_id, &res)) { | |
134 LOG(FATAL) << "failed to load webkit string with id " << message_id; | |
135 } | |
136 | |
137 // Data packs hold strings as either UTF8 or UTF16. | |
138 base::string16 msg; | |
139 switch (g_resource_data_pack->GetTextEncodingType()) { | |
140 case ui::DataPack::UTF8: | |
141 msg = UTF8ToUTF16(res); | |
142 break; | |
143 case ui::DataPack::UTF16: | |
144 msg = base::string16(reinterpret_cast<const char16*>(res.data()), | |
145 res.length() / 2); | |
146 break; | |
147 case ui::DataPack::BINARY: | |
148 NOTREACHED(); | |
149 break; | |
150 } | |
151 | |
152 return msg; | |
153 } | |
154 | |
155 // Helper method for getting the path to the test shell resources directory. | |
156 static base::FilePath GetResourcesFilePath() { | |
157 base::FilePath path; | |
158 // We assume the application is bundled. | |
159 if (!base::mac::AmIBundled()) { | |
160 LOG(FATAL) << "Failed to locate resources. The applicaiton is not bundled."; | |
161 } | |
162 PathService::Get(base::DIR_EXE, &path); | |
163 path = path.Append(base::FilePath::kParentDirectory); | |
164 return path.AppendASCII("Resources"); | |
165 } | |
166 | |
167 base::StringPiece TestWebKitPlatformSupport::GetDataResource( | |
168 int resource_id, | |
169 ui::ScaleFactor scale_factor) { | |
170 switch (resource_id) { | |
171 case IDR_BROKENIMAGE: { | |
172 // Use webkit's broken image icon (16x16) | |
173 CR_DEFINE_STATIC_LOCAL(std::string, broken_image_data, ()); | |
174 if (broken_image_data.empty()) { | |
175 base::FilePath path = GetResourcesFilePath(); | |
176 // In order to match WebKit's colors for the missing image, we have to | |
177 // use a PNG. The GIF doesn't have the color range needed to correctly | |
178 // match the TIFF they use in Safari. | |
179 path = base::MakeAbsoluteFilePath(path.AppendASCII("missingImage.png")); | |
180 bool success = file_util::ReadFileToString(path, &broken_image_data); | |
181 if (!success) { | |
182 LOG(FATAL) << "Failed reading: " << path.value(); | |
183 } | |
184 } | |
185 return broken_image_data; | |
186 } | |
187 case IDR_TEXTAREA_RESIZER: { | |
188 // Use webkit's text area resizer image. | |
189 CR_DEFINE_STATIC_LOCAL(std::string, resize_corner_data, ()); | |
190 if (resize_corner_data.empty()) { | |
191 base::FilePath path = GetResourcesFilePath(); | |
192 path = base::MakeAbsoluteFilePath( | |
193 path.AppendASCII("textAreaResizeCorner.png")); | |
194 bool success = file_util::ReadFileToString(path, &resize_corner_data); | |
195 if (!success) { | |
196 LOG(FATAL) << "Failed reading: " << path.value(); | |
197 } | |
198 } | |
199 return resize_corner_data; | |
200 } | |
201 } | |
202 base::StringPiece res; | |
203 if (g_resource_data_pack) | |
204 g_resource_data_pack->GetStringPiece(resource_id, &res); | |
205 return res; | |
206 } | |
OLD | NEW |