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   @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