1 #!/usr/bin/env python 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 """Handling of the <include> element. 7 """ 8 9 import os 10 11 import grit.format.html_inline 12 import grit.format.rc_header 13 import grit.format.rc 14 15 from grit.node import base 16 from grit import util 17 18 class IncludeNode(base.Node): 19 """An <include> element.""" 20 def __init__(self): 21 super(IncludeNode, self).__init__() 22 23 # Cache flattened data so that we don't flatten the same file 24 # multiple times. 25 self._flattened_data = None 26 # Also keep track of the last filename we flattened to, so we can 27 # avoid doing it more than once. 28 self._last_flat_filename = None 29 30 def _IsValidChild(self, child): 31 return False 32 33 def _GetFlattenedData(self, allow_external_script=False): 34 if not self._flattened_data: 35 filename = self.ToRealPath(self.GetInputPath()) 36 self._flattened_data = ( 37 grit.format.html_inline.InlineToString(filename, self, 38 allow_external_script=allow_external_script)) 39 return self._flattened_data 40 41 def MandatoryAttributes(self): 42 return ['name', 'type', 'file'] 43 44 def DefaultAttributes(self): 45 return {'translateable' : 'true', 46 'generateid': 'true', 47 'filenameonly': 'false', 48 'mkoutput': 'false', 49 'flattenhtml': 'false', 50 'allowexternalscript': 'false', 51 'relativepath': 'false', 52 'use_base_dir': 'true', 53 } 54 55 def GetInputPath(self): 56 # Do not mess with absolute paths, that would make them invalid. 57 if os.path.isabs(os.path.expandvars(self.attrs['file'])): 58 return self.attrs['file'] 59 60 # We have no control over code that calles ToRealPath later, so convert 61 # the path to be relative against our basedir. 62 if self.attrs.get('use_base_dir', 'true') != 'true': 63 return os.path.relpath(self.attrs['file'], self.GetRoot().GetBaseDir()) 64 65 return self.attrs['file'] 66 67 def FileForLanguage(self, lang, output_dir): 68 """Returns the file for the specified language. This allows us to return 69 different files for different language variants of the include file. 70 """ 71 return self.ToRealPath(self.GetInputPath()) 72 73 def GetDataPackPair(self, lang, encoding): 74 """Returns a (id, string) pair that represents the resource id and raw 75 bytes of the data. This is used to generate the data pack data file. 76 """ 77 # TODO(benrg/joi): Move this and other implementations of GetDataPackPair 78 # to grit.format.data_pack? 79 from grit.format import rc_header 80 id_map = rc_header.GetIds(self.GetRoot()) 81 id = id_map[self.GetTextualIds()[0]] 82 if self.attrs['flattenhtml'] == 'true': 83 allow_external_script = self.attrs['allowexternalscript'] == 'true' 84 data = self._GetFlattenedData(allow_external_script=allow_external_script) 85 else: 86 filename = self.ToRealPath(self.GetInputPath()) 87 data = util.ReadFile(filename, util.BINARY) 88 89 # Include does not care about the encoding, because it only returns binary 90 # data. 91 return id, data 92 93 def Process(self, output_dir): 94 """Rewrite file references to be base64 encoded data URLs. The new file 95 will be written to output_dir and the name of the new file is returned.""" 96 filename = self.ToRealPath(self.GetInputPath()) 97 flat_filename = os.path.join(output_dir, 98 self.attrs['name'] + '_' + os.path.basename(filename)) 99 100 if self._last_flat_filename == flat_filename: 101 return 102 103 with open(flat_filename, 'wb') as outfile: 104 outfile.write(self._GetFlattenedData()) 105 106 self._last_flat_filename = flat_filename 107 return os.path.basename(flat_filename) 108 109 def GetHtmlResourceFilenames(self): 110 """Returns a set of all filenames inlined by this file.""" 111 allow_external_script = self.attrs['allowexternalscript'] == 'true' 112 return grit.format.html_inline.GetResourceFilenames( 113 self.ToRealPath(self.GetInputPath()), 114 allow_external_script=allow_external_script) 115 116 @staticmethod 117 def Construct(parent, name, type, file, translateable=True, 118 filenameonly=False, mkoutput=False, relativepath=False): 119 """Creates a new node which is a child of 'parent', with attributes set 120 by parameters of the same name. 121 """ 122 # Convert types to appropriate strings 123 translateable = util.BoolToString(translateable) 124 filenameonly = util.BoolToString(filenameonly) 125 mkoutput = util.BoolToString(mkoutput) 126 relativepath = util.BoolToString(relativepath) 127 128 node = IncludeNode() 129 node.StartParsing('include', parent) 130 node.HandleAttribute('name', name) 131 node.HandleAttribute('type', type) 132 node.HandleAttribute('file', file) 133 node.HandleAttribute('translateable', translateable) 134 node.HandleAttribute('filenameonly', filenameonly) 135 node.HandleAttribute('mkoutput', mkoutput) 136 node.HandleAttribute('relativepath', relativepath) 137 node.EndParsing() 138 return node 139