Home | History | Annotate | Download | only in node
      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   def IsResourceMapSource(self):
    117     return True
    118 
    119   def GeneratesResourceMapEntry(self, output_all_resource_defines,
    120                                 is_active_descendant):
    121     # includes always generate resource entries.
    122     if output_all_resource_defines:
    123       return True
    124     return is_active_descendant
    125 
    126   @staticmethod
    127   def Construct(parent, name, type, file, translateable=True,
    128                 filenameonly=False, mkoutput=False, relativepath=False):
    129     """Creates a new node which is a child of 'parent', with attributes set
    130     by parameters of the same name.
    131     """
    132     # Convert types to appropriate strings
    133     translateable = util.BoolToString(translateable)
    134     filenameonly = util.BoolToString(filenameonly)
    135     mkoutput = util.BoolToString(mkoutput)
    136     relativepath = util.BoolToString(relativepath)
    137 
    138     node = IncludeNode()
    139     node.StartParsing('include', parent)
    140     node.HandleAttribute('name', name)
    141     node.HandleAttribute('type', type)
    142     node.HandleAttribute('file', file)
    143     node.HandleAttribute('translateable', translateable)
    144     node.HandleAttribute('filenameonly', filenameonly)
    145     node.HandleAttribute('mkoutput', mkoutput)
    146     node.HandleAttribute('relativepath', relativepath)
    147     node.EndParsing()
    148     return node
    149