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

Side by Side Diff: chrome/tools/build/mac/tweak_info_plist

Issue 9513006: First pass at content shell for the Mac. Doesn't work yet. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase only, no code change Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 #
8 # Xcode supports build variable substitutions and CPP; sadly, that doesn't work
9 # because:
10 #
11 # 1. Xcode wants to do the Info.plist work before it runs any build phases,
12 # this means if we were to generate a .h file for INFOPLIST_PREFIX_HEADER
13 # we'd have to put it in another target so it runs in time.
14 # 2. Xcode also doesn't check to see if the header being used as a prefix for
15 # the Info.plist has changed. So even if we updated it, it's only looking
16 # at the modtime of the info.plist to see if that's changed.
17 #
18 # So, we work around all of this by making a script build phase that will run
19 # during the app build, and simply update the info.plist in place. This way
20 # by the time the app target is done, the info.plist is correct.
21 #
22
23 import optparse
24 import os
25 from os import environ as env
26 import plistlib
27 import re
28 import subprocess
29 import sys
30 import tempfile
31
32 TOP = os.path.join(env['SRCROOT'], '..')
33
34 sys.path.insert(0, os.path.join(TOP, "build/util"))
35 import lastchange
36
37
38 def _GetOutput(args):
39 """Runs a subprocess and waits for termination. Returns (stdout, returncode)
40 of the process. stderr is attached to the parent."""
41 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
42 (stdout, stderr) = proc.communicate()
43 return (stdout, proc.returncode)
44
45
46 def _GetOutputNoError(args):
47 """Similar to _GetOutput() but ignores stderr. If there's an error launching
48 the child (like file not found), the exception will be caught and (None, 1)
49 will be returned to mimic quiet failure."""
50 try:
51 proc = subprocess.Popen(args, stdout=subprocess.PIPE,
52 stderr=subprocess.PIPE)
53 except OSError:
54 return (None, 1)
55 (stdout, stderr) = proc.communicate()
56 return (stdout, proc.returncode)
57
58
59 def _RemoveKeys(plist, *keys):
60 """Removes a varargs of keys from the plist."""
61 for key in keys:
62 try:
63 del plist[key]
64 except KeyError:
65 pass
66
67
68 def _AddVersionKeys(plist):
69 """Adds the product version number into the plist. Returns True on success and
70 False on error. The error will be printed to stderr."""
71 # Pull in the Chrome version number.
72 VERSION_TOOL = os.path.join(TOP, 'chrome/tools/build/version.py')
73 VERSION_FILE = os.path.join(TOP, 'chrome/VERSION')
74
75 (stdout, retval1) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
76 '@MAJOR@.@MINOR@.@BUILD@.@PATCH@'])
77 full_version = stdout.rstrip()
78
79 (stdout, retval2) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
80 '@BUILD@.@PATCH@'])
81 bundle_version = stdout.rstrip()
82
83 # If either of the two version commands finished with non-zero returncode,
84 # report the error up.
85 if retval1 or retval2:
86 return False
87
88 # Add public version info so "Get Info" works.
89 plist['CFBundleShortVersionString'] = full_version
90
91 # Honor the 429496.72.95 limit. The maximum comes from splitting 2^32 - 1
92 # into 6, 2, 2 digits. The limitation was present in Tiger, but it could
93 # have been fixed in later OS release, but hasn't been tested (it's easy
94 # enough to find out with "lsregister -dump).
95 # http://lists.apple.com/archives/carbon-dev/2006/Jun/msg00139.html
96 # BUILD will always be an increasing value, so BUILD_PATH gives us something
97 # unique that meetings what LS wants.
98 plist['CFBundleVersion'] = bundle_version
99
100 # Return with no error.
101 return True
102
103
104 def _DoSVNKeys(plist, add_keys):
105 """Adds the SVN information, visible in about:version, to property list. If
106 |add_keys| is True, it will insert the keys, otherwise it will remove them."""
107 scm_path, scm_revision = None, None
108 if add_keys:
109 version_info = lastchange.FetchVersionInfo(
110 default_lastchange=None, directory=TOP)
111 scm_path, scm_revision = version_info.url, version_info.revision
112
113 # See if the operation failed.
114 _RemoveKeys(plist, 'SVNRevision')
115 if scm_revision != None:
116 plist['SVNRevision'] = scm_revision
117 elif add_keys:
118 print >>sys.stderr, 'Could not determine svn revision. This may be OK.'
119
120 if scm_path != None:
121 plist['SVNPath'] = scm_path
122 else:
123 _RemoveKeys(plist, 'SVNPath')
124
125
126 def _DoPDFKeys(plist, add_keys):
127 """Adds PDF support to the document types list. If add_keys is True, it will
128 add the type information dictionary. If it is False, it will remove it if
129 present."""
130
131 PDF_FILE_EXTENSION = 'pdf'
132
133 def __AddPDFKeys(sub_plist):
134 """Writes the keys into a sub-dictionary of the plist."""
135 sub_plist['CFBundleTypeExtensions'] = [PDF_FILE_EXTENSION]
136 sub_plist['CFBundleTypeIconFile'] = 'document.icns'
137 sub_plist['CFBundleTypeMIMETypes'] = 'application/pdf'
138 sub_plist['CFBundleTypeName'] = 'PDF Document'
139 sub_plist['CFBundleTypeRole'] = 'Viewer'
140
141 DOCUMENT_TYPES_KEY = 'CFBundleDocumentTypes'
142
143 # First get the list of document types, creating it if necessary.
144 try:
145 extensions = plist[DOCUMENT_TYPES_KEY]
146 except KeyError:
147 # If this plist doesn't have a type dictionary, create one if set to add the
148 # keys. If not, bail.
149 if not add_keys:
150 return
151 extensions = plist[DOCUMENT_TYPES_KEY] = []
152
153 # Loop over each entry in the list, looking for one that handles PDF types.
154 for i, ext in enumerate(extensions):
155 # If an entry for .pdf files is found...
156 if 'CFBundleTypeExtensions' not in ext:
157 continue
158 if PDF_FILE_EXTENSION in ext['CFBundleTypeExtensions']:
159 if add_keys:
160 # Overwrite the existing keys with new ones.
161 __AddPDFKeys(ext)
162 else:
163 # Otherwise, delete the entry entirely.
164 del extensions[i]
165 return
166
167 # No PDF entry exists. If one needs to be added, do so now.
168 if add_keys:
169 pdf_entry = {}
170 __AddPDFKeys(pdf_entry)
171 extensions.append(pdf_entry)
172
173
174 def _AddBreakpadKeys(plist, branding):
175 """Adds the Breakpad keys. This must be called AFTER _AddVersionKeys() and
176 also requires the |branding| argument."""
177 plist['BreakpadReportInterval'] = '3600' # Deliberately a string.
178 plist['BreakpadProduct'] = '%s_Mac' % branding
179 plist['BreakpadProductDisplay'] = branding
180 plist['BreakpadVersion'] = plist['CFBundleShortVersionString']
181 # These are both deliberately strings and not boolean.
182 plist['BreakpadSendAndExit'] = 'YES'
183 plist['BreakpadSkipConfirm'] = 'YES'
184
185
186 def _RemoveBreakpadKeys(plist):
187 """Removes any set Breakpad keys."""
188 _RemoveKeys(plist,
189 'BreakpadURL',
190 'BreakpadReportInterval',
191 'BreakpadProduct',
192 'BreakpadProductDisplay',
193 'BreakpadVersion',
194 'BreakpadSendAndExit',
195 'BreakpadSkipConfirm')
196
197
198 def _AddKeystoneKeys(plist, bundle_identifier):
199 """Adds the Keystone keys. This must be called AFTER _AddVersionKeys() and
200 also requires the |bundle_identifier| argument (com.example.product)."""
201 plist['KSVersion'] = plist['CFBundleShortVersionString']
202 plist['KSProductID'] = bundle_identifier
203 plist['KSUpdateURL'] = 'https://tools.google.com/service/update2'
204
205
206 def _RemoveKeystoneKeys(plist):
207 """Removes any set Keystone keys."""
208 _RemoveKeys(plist,
209 'KSVersion',
210 'KSProductID',
211 'KSUpdateURL')
212
213
214 def Main(argv):
215 parser = optparse.OptionParser('%prog [options] branding bundle-id')
216 parser.add_option('--breakpad', dest='use_breakpad', action='store',
217 type='int', default=False, help='Enable Breakpad [1 or 0]')
218 parser.add_option('--breakpad_uploads', dest='breakpad_uploads',
219 action='store', type='int', default=False,
220 help='Enable Breakpad\'s uploading of crash dumps [1 or 0]')
221 parser.add_option('-k', dest='use_keystone', action='store', type='int',
222 default=False, help='Enable Keystone [1 or 0]')
223 parser.add_option('-s', dest='add_svn_info', action='store', type='int',
224 default=True, help='Add SVN metadata [1 or 0]')
225 parser.add_option('-p', dest='add_pdf_support', action='store', type='int',
226 default=False, help='Add PDF file handler support [1 or 0]')
227 (options, args) = parser.parse_args(argv)
228
229 if len(args) < 2:
230 print >>sys.stderr, parser.get_usage()
231 return 1
232
233 # Extract remaining arguments.
234 branding = args[0]
235 bundle_identifier = args[1]
236
237 # Read the plist into its parsed format.
238 DEST_INFO_PLIST = os.path.join(env['TARGET_BUILD_DIR'], env['INFOPLIST_PATH'])
239 plist = plistlib.readPlist(DEST_INFO_PLIST)
240
241 # Insert the product version.
242 if not _AddVersionKeys(plist):
243 return 2
244
245 # Add Breakpad if configured to do so.
246 if options.use_breakpad:
247 _AddBreakpadKeys(plist, branding)
248 if options.breakpad_uploads:
249 plist['BreakpadURL'] = 'https://clients2.google.com/cr/report'
250 else:
251 # This allows crash dumping to a file without uploading the
252 # dump, for testing purposes. Breakpad does not recognise
253 # "none" as a special value, but this does stop crash dump
254 # uploading from happening. We need to specify something
255 # because if "BreakpadURL" is not present, Breakpad will not
256 # register its crash handler and no crash dumping will occur.
257 plist['BreakpadURL'] = 'none'
258 else:
259 _RemoveBreakpadKeys(plist)
260
261 # Only add Keystone in Release builds.
262 if options.use_keystone and env['CONFIGURATION'] == 'Release':
263 _AddKeystoneKeys(plist, bundle_identifier)
264 else:
265 _RemoveKeystoneKeys(plist)
266
267 # Adds or removes any SVN keys.
268 _DoSVNKeys(plist, options.add_svn_info)
269
270 # Adds or removes the PDF file handler entry.
271 _DoPDFKeys(plist, options.add_pdf_support)
272
273 # Now that all keys have been mutated, rewrite the file.
274 temp_info_plist = tempfile.NamedTemporaryFile()
275 plistlib.writePlist(plist, temp_info_plist.name)
276
277 # Info.plist will work perfectly well in any plist format, but traditionally
278 # applications use xml1 for this, so convert it to ensure that it's valid.
279 proc = subprocess.Popen(['plutil', '-convert', 'xml1', '-o', DEST_INFO_PLIST,
280 temp_info_plist.name])
281 proc.wait()
282 return proc.returncode
283
284
285 if __name__ == '__main__':
286 sys.exit(Main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « chrome/tools/build/mac/copy_framework_unversioned ('k') | chrome/tools/build/mac/verify_no_objc.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698