Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: chrome/app/app_mode_loader_mac.mm

Issue 2066004: Mac: app mode loader (shim). (Closed)
Patch Set: more changes per mark + merged ToT Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/app/app_mode-Info.plist ('k') | chrome/app/chrome_dll_app_mode_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // On Mac, shortcuts can't have command-line arguments. Instead, produce small
6 // app bundles which locate the Chromium framework and load it, passing the
7 // appropriate data. This is the code for such an app bundle. It should be kept
8 // minimal and do as little work as possible (with as much work done on
9 // framework side as possible).
10
11 #include <dlfcn.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <CoreFoundation/CoreFoundation.h>
17 #import <Foundation/Foundation.h>
18
19 #include "chrome/common/app_mode_common_mac.h"
20
21 namespace {
22
23 // Checks that condition |x| is true. If not, outputs |msg| (together with
24 // source filename and line number) and exits.
25 #define CHECK_MSG(x, msg) if (!(x)) check_msg_helper(__FILE__, __LINE__, msg);
26 void check_msg_helper(const char* file, int line, const char* msg) {
27 fprintf(stderr, "%s (%d): %s\n", file, line, msg);
28 exit(1);
29 }
30
31 // Converts an NSString to a UTF8 C string (which is allocated, and may be freed
32 // using |free()|). If |s| is nil or can't produce such a string, this returns
33 // |NULL|.
34 char* NSStringToUTF8CString(NSString* s) {
35 CHECK_MSG([s isKindOfClass:[NSString class]], "expected an NSString");
36 const char* cstring = [s UTF8String];
37 return cstring ? strdup(cstring) : NULL;
38 }
39
40 // Converts an NSString to a file-system representation C string (which is
41 // allocated, and may be freed using |free()|). If |s| is nil or can't produce
42 // such a string, this returns |NULL|.
43 char* NSStringToFSCString(NSString* s) {
44 CHECK_MSG([s isKindOfClass:[NSString class]], "expected an NSString");
45 const char* cstring = [s fileSystemRepresentation];
46 return cstring ? strdup(cstring) : NULL;
47 }
48
49 } // namespace
50
51 __attribute__((visibility("default")))
52 int main(int argc, char** argv) {
53 app_mode::ChromeAppModeInfo info;
54 info.major_version = 0; // v0.1
55 info.minor_version = 1;
56 info.argc = argc;
57 info.argv = argv;
58
59 // The Cocoa APIs are a bit more convenient; for this an autorelease pool is
60 // needed.
61 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
62
63 // Get the browser bundle path.
64 // TODO(viettrungluu): more fun
65 NSString* cr_bundle_path =
66 [(NSString*)CFPreferencesCopyAppValue(
67 app_mode::kLastRunAppBundlePathPrefsKey,
68 app_mode::kAppPrefsID) autorelease];
69 CHECK_MSG(cr_bundle_path, "couldn't get browser bundle path");
70
71 // Get the browser bundle.
72 NSBundle* cr_bundle = [NSBundle bundleWithPath:cr_bundle_path];
73 CHECK_MSG(cr_bundle, "couldn't get browser bundle");
74
75 // Get the current browser version.
76 NSString* cr_version =
77 [cr_bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
78 CHECK_MSG(cr_version, "couldn't get browser version");
79
80 // Get the current browser versioned directory.
81 NSArray* cr_versioned_path_components =
82 [NSArray arrayWithObjects:cr_bundle_path,
83 @"Contents",
84 @"Versions",
85 cr_version,
86 nil];
87 NSString* cr_versioned_path =
88 [[NSString pathWithComponents:cr_versioned_path_components]
89 stringByStandardizingPath];
90 CHECK_MSG(cr_versioned_path, "couldn't get browser versioned path");
91 // And copy it, since |cr_versioned_path| will go away with the pool.
92 info.chrome_versioned_path = NSStringToFSCString(cr_versioned_path);
93
94 // Get the current main bundle, i.e., that of the app loader that's running.
95 NSBundle* app_bundle = [NSBundle mainBundle];
96 CHECK_MSG(app_bundle, "couldn't get loader bundle");
97 // Optional, so okay if it's NULL.
98 info.app_mode_bundle_path = NSStringToFSCString([app_bundle bundlePath]);
99
100 // Read information about the this app shortcut from the Info.plist.
101 // Don't check for null-ness on optional items.
102 NSDictionary* info_plist = [app_bundle infoDictionary];
103 CHECK_MSG(info_plist, "couldn't get loader Info.plist");
104
105 info.app_mode_id = NSStringToUTF8CString(
106 [info_plist objectForKey:@"CrAppModeShortcutID"]);
107 CHECK_MSG(info.app_mode_id, "couldn't get app shortcut ID");
108
109 info.app_mode_short_name = NSStringToUTF8CString(
110 [info_plist objectForKey:@"CrAppModeShortcutShortName"]);
111
112 info.app_mode_name = NSStringToUTF8CString(
113 [info_plist objectForKey:@"CrAppModeShortcutName"]);
114
115 info.app_mode_url = NSStringToUTF8CString(
116 [info_plist objectForKey:@"CrAppModeShortcutURL"]);
117 CHECK_MSG(info.app_mode_url, "couldn't get app shortcut URL");
118
119 // Get the framework path.
120 NSString* cr_bundle_exe =
121 [cr_bundle objectForInfoDictionaryKey:@"CFBundleExecutable"];
122 NSString* cr_framework_path =
123 [cr_versioned_path stringByAppendingPathComponent:
124 [cr_bundle_exe stringByAppendingString:@" Framework.framework"]];
125 cr_framework_path =
126 [cr_framework_path stringByAppendingPathComponent:
127 [cr_bundle_exe stringByAppendingString:@" Framework"]];
128
129 // Open the framework.
130 void* cr_dylib = dlopen([cr_framework_path fileSystemRepresentation],
131 RTLD_LAZY);
132 CHECK_MSG(cr_dylib, "couldn't load framework");
133
134 // Drain the pool as late as possible.
135 [pool drain];
136
137 typedef int (*StartFun)(const app_mode::ChromeAppModeInfo*);
138 StartFun ChromeAppModeStart = (StartFun)dlsym(cr_dylib, "ChromeAppModeStart");
139 CHECK_MSG(ChromeAppModeStart, "couldn't get entry point");
140
141 // Exit instead of returning to avoid the the removal of |main()| from stack
142 // backtraces under tail call optimization.
143 int rv = ChromeAppModeStart(&info);
144 exit(rv);
145 }
OLDNEW
« no previous file with comments | « chrome/app/app_mode-Info.plist ('k') | chrome/app/chrome_dll_app_mode_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698