Add support for favicon scale factor.
[chromium-blink-merge.git] / webkit / support / platform_support_mac.mm
blob6b723afac698cb70ed55d9c39045b1b2714c4b72
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 "webkit/support/platform_support.h"
7 #import <AppKit/AppKit.h>
8 #include <AvailabilityMacros.h>
9 #import <Foundation/Foundation.h>
10 #import <objc/objc-runtime.h>
12 #include "base/base_paths.h"
13 #include "base/file_util.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"
18 #include "base/string16.h"
19 #include "base/utf_string_conversions.h"
20 #include "grit/webkit_resources.h"
21 #include "ui/base/resource/data_pack.h"
22 #include "webkit/plugins/npapi/plugin_list.h"
23 #include "webkit/support/test_webkit_platform_support.h"
24 #import "webkit/support/drt_application_mac.h"
25 #import "webkit/tools/test_shell/mac/DumpRenderTreePasteboard.h"
27 static ui::DataPack* g_resource_data_pack = NULL;
29 namespace webkit_support {
31 static NSAutoreleasePool* autorelease_pool;
33 void BeforeInitialize(bool unit_test_mode) {
34   [CrDrtApplication sharedApplication];
35   autorelease_pool = [[NSAutoreleasePool alloc] init];
36   DCHECK(autorelease_pool);
39 #if OBJC_API_VERSION == 2
40 static void SwizzleAllMethods(Class imposter, Class original) {
41   unsigned int imposterMethodCount = 0;
42   Method* imposterMethods =
43       class_copyMethodList(imposter, &imposterMethodCount);
45   unsigned int originalMethodCount = 0;
46   Method* originalMethods =
47       class_copyMethodList(original, &originalMethodCount);
49   for (unsigned int i = 0; i < imposterMethodCount; i++) {
50     SEL imposterMethodName = method_getName(imposterMethods[i]);
52     // Attempt to add the method to the original class.  If it fails, the method
53     // already exists and we should instead exchange the implementations.
54     if (class_addMethod(original,
55                         imposterMethodName,
56                         method_getImplementation(originalMethods[i]),
57                         method_getTypeEncoding(originalMethods[i]))) {
58       continue;
59     }
61     unsigned int j = 0;
62     for (; j < originalMethodCount; j++) {
63       SEL originalMethodName = method_getName(originalMethods[j]);
64       if (sel_isEqual(imposterMethodName, originalMethodName)) {
65         break;
66       }
67     }
69     // If class_addMethod failed above then the method must exist on the
70     // original class.
71     DCHECK(j < originalMethodCount) << "method wasn't found?";
72     method_exchangeImplementations(imposterMethods[i], originalMethods[j]);
73   }
75   if (imposterMethods) {
76     free(imposterMethods);
77   }
78   if (originalMethods) {
79     free(originalMethods);
80   }
82 #endif
84 static void SwizzleNSPasteboard() {
85   // We replace NSPaseboard w/ the shim (from WebKit) that avoids having
86   // sideeffects w/ whatever the user does at the same time.
88   Class imposterClass = objc_getClass("DumpRenderTreePasteboard");
89   Class originalClass = objc_getClass("NSPasteboard");
90 #if OBJC_API_VERSION == 0
91   class_poseAs(imposterClass, originalClass);
92 #else
93   // Swizzle instance methods...
94   SwizzleAllMethods(imposterClass, originalClass);
95   // and then class methods.
96   SwizzleAllMethods(object_getClass(imposterClass),
97                     object_getClass(originalClass));
98 #endif
101 void AfterInitialize(bool unit_test_mode) {
102   // Load a data pack.
103   g_resource_data_pack = new ui::DataPack(ui::SCALE_FACTOR_100P);
104   FilePath resources_pak_path;
105   if (unit_test_mode) {
106     PathService::Get(base::DIR_EXE, &resources_pak_path);
107     resources_pak_path = resources_pak_path.Append("DumpRenderTree.app")
108         .Append("Contents")
109         .Append("Resources")
110         .Append("DumpRenderTree.pak");
111   } else {
112     NSString* resource_path =
113         [base::mac::FrameworkBundle() pathForResource:@"DumpRenderTree"
114                                                ofType:@"pak"];
115     resources_pak_path = FilePath([resource_path fileSystemRepresentation]);
116   }
117   if (!g_resource_data_pack->LoadFromPath(resources_pak_path)) {
118     LOG(FATAL) << "failed to load DumpRenderTree.pak";
119   }
121   if (unit_test_mode)
122     return;
124   // Load font files in the resource folder.
125   static const char* const fontFileNames[] = {
126       "AHEM____.TTF",
127       "WebKitWeightWatcher100.ttf",
128       "WebKitWeightWatcher200.ttf",
129       "WebKitWeightWatcher300.ttf",
130       "WebKitWeightWatcher400.ttf",
131       "WebKitWeightWatcher500.ttf",
132       "WebKitWeightWatcher600.ttf",
133       "WebKitWeightWatcher700.ttf",
134       "WebKitWeightWatcher800.ttf",
135       "WebKitWeightWatcher900.ttf",
136   };
138   NSMutableArray* font_urls = [NSMutableArray array];
139   NSURL* resources_directory = [[NSBundle mainBundle] resourceURL];
140   for (unsigned i = 0; i < arraysize(fontFileNames); ++i) {
141     NSURL* font_url = [resources_directory
142         URLByAppendingPathComponent:[NSString
143             stringWithUTF8String:fontFileNames[i]]];
144     [font_urls addObject:[font_url absoluteURL]];
145   }
147   CFArrayRef errors = 0;
148   if (!CTFontManagerRegisterFontsForURLs((CFArrayRef)font_urls,
149                                          kCTFontManagerScopeProcess,
150                                          &errors)) {
151     DLOG(FATAL) << "Fail to activate fonts.";
152     CFRelease(errors);
153   }
155   SwizzleNSPasteboard();
157   // Add <app bundle's parent dir>/plugins to the plugin path so we can load
158   // test plugins.
159   FilePath plugins_dir;
160   PathService::Get(base::DIR_EXE, &plugins_dir);
161   plugins_dir = plugins_dir.AppendASCII("../../../plugins");
162   webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(plugins_dir);
165 void BeforeShutdown() {
168 void AfterShutdown() {
169   [DumpRenderTreePasteboard releaseLocalPasteboards];
170   [autorelease_pool drain];
171   delete g_resource_data_pack;
174 }  // namespace webkit_support
176 string16 TestWebKitPlatformSupport::GetLocalizedString(int message_id) {
177   // |g_resource_data_pack| is null on unit tests.
178   // But som unit tests reach GetLocalizedString().
179   if (!g_resource_data_pack)
180     return string16();
181   base::StringPiece res;
182   if (!g_resource_data_pack->GetStringPiece(message_id, &res)) {
183     LOG(FATAL) << "failed to load webkit string with id " << message_id;
184   }
186   // Data packs hold strings as either UTF8 or UTF16.
187   string16 msg;
188   switch (g_resource_data_pack->GetTextEncodingType()) {
189   case ui::DataPack::UTF8:
190     msg = UTF8ToUTF16(res);
191     break;
192   case ui::DataPack::UTF16:
193     msg = string16(reinterpret_cast<const char16*>(res.data()),
194                    res.length() / 2);
195     break;
196   case ui::DataPack::BINARY:
197     NOTREACHED();
198     break;
199   }
201   return msg;
204 // Helper method for getting the path to the test shell resources directory.
205 static FilePath GetResourcesFilePath() {
206   FilePath path;
207   // We assume the application is bundled.
208   if (!base::mac::AmIBundled()) {
209     LOG(FATAL) << "Failed to locate resources. The applicaiton is not bundled.";
210   }
211   PathService::Get(base::DIR_EXE, &path);
212   path = path.Append(FilePath::kParentDirectory);
213   return path.AppendASCII("Resources");
216 base::StringPiece TestWebKitPlatformSupport::GetDataResource(
217     int resource_id,
218     ui::ScaleFactor scale_factor) {
219   switch (resource_id) {
220   case IDR_BROKENIMAGE: {
221     // Use webkit's broken image icon (16x16)
222     CR_DEFINE_STATIC_LOCAL(std::string, broken_image_data, ());
223     if (broken_image_data.empty()) {
224       FilePath path = GetResourcesFilePath();
225       // In order to match WebKit's colors for the missing image, we have to
226       // use a PNG. The GIF doesn't have the color range needed to correctly
227       // match the TIFF they use in Safari.
228       path = path.AppendASCII("missingImage.png");
229       bool success = file_util::ReadFileToString(path, &broken_image_data);
230       if (!success) {
231         LOG(FATAL) << "Failed reading: " << path.value();
232       }
233     }
234     return broken_image_data;
235   }
236   case IDR_TEXTAREA_RESIZER: {
237     // Use webkit's text area resizer image.
238     CR_DEFINE_STATIC_LOCAL(std::string, resize_corner_data, ());
239     if (resize_corner_data.empty()) {
240       FilePath path = GetResourcesFilePath();
241       path = path.AppendASCII("textAreaResizeCorner.png");
242       bool success = file_util::ReadFileToString(path, &resize_corner_data);
243       if (!success) {
244         LOG(FATAL) << "Failed reading: " << path.value();
245       }
246     }
247     return resize_corner_data;
248   }
249   }
250   base::StringPiece res;
251   if (g_resource_data_pack)
252     g_resource_data_pack->GetStringPiece(resource_id, &res);
253   return res;