summaryrefslogtreecommitdiffstats
path: root/ui/base/resource/resource_bundle_mac.mm
blob: 6e4002d0ff8f774400046d8ebf86da41cc17a24c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/resource/resource_bundle.h"

#import <AppKit/AppKit.h>

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
#include "base/memory/scoped_nsobject.h"
#include "base/synchronization/lock.h"
#include "base/sys_string_conversions.h"
#include "ui/base/resource/resource_handle.h"
#include "ui/gfx/image/image.h"

namespace ui {

namespace {

FilePath GetResourcesPakFilePath(NSString* name, NSString* mac_locale) {
  NSString *resource_path;
  // Some of the helper processes need to be able to fetch resources
  // (chrome_main.cc: SubprocessNeedsResourceBundle()). Fetch the same locale
  // as the already-running browser instead of using what NSBundle might pick
  // based on values at helper launch time.
  if ([mac_locale length]) {
    resource_path = [base::mac::FrameworkBundle() pathForResource:name
                                                           ofType:@"pak"
                                                      inDirectory:@""
                                                  forLocalization:mac_locale];
  } else {
    resource_path = [base::mac::FrameworkBundle() pathForResource:name
                                                           ofType:@"pak"];
  }
  if (!resource_path)
    return FilePath();
  return FilePath([resource_path fileSystemRepresentation]);
}

}  // namespace

void ResourceBundle::LoadCommonResources() {
  AddDataPack(GetResourcesPakFilePath(@"chrome", nil));
  AddDataPack(GetResourcesPakFilePath(@"theme_resources_standard", nil));
  AddDataPack(GetResourcesPakFilePath(@"ui_resources_standard", nil));

  // On Windows and ChromeOS we load either the 1x resource or the 2x resource.
  // On Mac we load both and let the UI framework decide which one to use.
#if defined(ENABLE_HIDPI)
  if (base::mac::IsOSLionOrLater()) {
    AddDataPack(GetResourcesPakFilePath(@"theme_resources_2x", nil));
    AddDataPack(GetResourcesPakFilePath(@"theme_resources_standard_2x", nil));
    AddDataPack(GetResourcesPakFilePath(@"ui_resources_standard_2x", nil));
  }
#endif
}

// static
FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale) {
  NSString* mac_locale = base::SysUTF8ToNSString(app_locale);

  // Mac OS X uses "_" instead of "-", so swap to get a Mac-style value.
  mac_locale = [mac_locale stringByReplacingOccurrencesOfString:@"-"
                                                     withString:@"_"];

  // On disk, the "en_US" resources are just "en" (http://crbug.com/25578).
  if ([mac_locale isEqual:@"en_US"])
    mac_locale = @"en";

  return GetResourcesPakFilePath(@"locale", mac_locale);
}

gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
  // Flipped images are not used on Mac.
  DCHECK_EQ(rtl, RTL_DISABLED);

  // Check to see if the image is already in the cache.
  {
    base::AutoLock lock(*images_and_fonts_lock_);
    ImageMap::const_iterator found = images_.find(resource_id);
    if (found != images_.end()) {
      if (!found->second->HasRepresentation(gfx::Image::kImageRepCocoa)) {
        DLOG(WARNING) << "ResourceBundle::GetNativeImageNamed() is returning a"
          << " cached gfx::Image that isn't backed by an NSImage. The image"
          << " will be converted, rather than going through the NSImage loader."
          << " resource_id = " << resource_id;
      }
      return *found->second;
    }
  }

  scoped_nsobject<NSImage> ns_image;
  for (size_t i = 0; i < data_packs_.size(); ++i) {
    scoped_refptr<RefCountedStaticMemory> data(
        data_packs_[i]->GetStaticMemory(resource_id));
    if (!data.get())
      continue;

    scoped_nsobject<NSData> ns_data(
        [[NSData alloc] initWithBytes:data->front()
                               length:data->size()]);
    if (!ns_image.get()) {
      ns_image.reset([[NSImage alloc] initWithData:ns_data]);
    } else {
      NSImageRep* image_rep = [NSBitmapImageRep imageRepWithData:ns_data];
      if (image_rep)
        [ns_image addRepresentation:image_rep];
    }
  }

  if (!ns_image.get()) {
    LOG(WARNING) << "Unable to load image with id " << resource_id;
    NOTREACHED();  // Want to assert in debug mode.
    return *GetEmptyImage();
  }

  base::AutoLock lock(*images_and_fonts_lock_);

  // Another thread raced the load and has already cached the image.
  if (images_.count(resource_id)) {
    return *images_[resource_id];
  }

  gfx::Image* image = new gfx::Image(ns_image.release());
  images_[resource_id] = image;
  return *image;
}

}  // namespace ui