Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 05674404a4
Fetching contributors…

Cannot retrieve contributors at this time

241 lines (187 sloc) 8.666 kb
from validator.contextgenerator import ContextGenerator
class ChromeManifest(object):
"""This class enables convenient parsing and iteration of
chrome.manifest files."""
def __init__(self, data, path):
self.context = ContextGenerator(data)
self.lines = data.split("\n")
# Extract the data from the triples in the manifest
triples = []
counter = 0
for line in self.lines:
line = line.strip()
counter += 1
# Skip weird lines.
if line.startswith("#"):
continue
triple = line.split(None, 2)
if not triple:
continue
elif len(triple) == 2:
triple.append("")
if len(triple) < 3:
continue
triples.append({"subject": triple[0],
"predicate": triple[1],
"object": triple[2],
"line": counter,
"filename": path,
"context": self.context})
self.triples = triples
def get_value(self, subject=None, predicate=None, object_=None):
"""Returns the first triple value matching the given subject,
predicate, and/or object"""
for triple in self.triples:
# Filter out non-matches
if (subject and triple["subject"] != subject) or \
(predicate and triple["predicate"] != predicate) or \
(object_ and triple["object"] != object_): # pragma: no cover
continue
# Return the first found.
return triple
return None
def get_objects(self, subject=None, predicate=None):
"""Returns a generator of objects that correspond to the
specified subjects and predicates."""
for triple in self.triples:
# Filter out non-matches
if (subject and
triple["subject"] != subject) or \
(predicate and
triple["predicate"] != predicate): # pragma: no cover
continue
yield triple["object"]
def get_triples(self, subject=None, predicate=None, object_=None):
"""Returns triples that correspond to the specified subject,
predicates, and objects."""
for triple in self.triples:
# Filter out non-matches
if subject is not None and triple["subject"] != subject:
continue
if predicate is not None and triple["predicate"] != predicate:
continue
if object_ is not None and triple["object"] != object_:
continue
yield triple
def get_applicable_overlays(self, error_bundle):
"""
Given an error bundle, a list of overlays that are present in the
current package or subpackage are returned.
"""
content_paths = self.get_triples(subject="content")
if not content_paths:
return set()
# Create some variables that will store where the applicable content
# instruction path references and where it links to.
chrome_path = ""
content_root_path = "/"
# Look through each of the listed packages and paths.
for path in content_paths:
chrome_name = path["predicate"]
if not path["object"]:
continue
path_location = path["object"].strip().split()[0]
# Handle jarred paths differently.
if path_location.startswith("jar:"):
if not error_bundle.is_nested_package():
continue
# Parse out the JAR and it's location within the chrome.
split_jar_url = path_location[4:].split("!", 2)
# Ignore invalid/unsupported JAR URLs.
if len(split_jar_url) != 2:
continue
# Unpack the JAR URL.
jar_path, package_path = split_jar_url
# Ignore the instruction if the JAR it points to doesn't match
# up with the current subpackage tree.
if jar_path != error_bundle.package_stack[0]:
continue
chrome_path = self._url_chunk_join(chrome_name, package_path)
# content_root_path stays at the default: /
break
else:
# If we're in a subpackage, a content instruction referring to
# the root of the package obviously doesn't apply.
if error_bundle.is_nested_package():
continue
chrome_path = self._url_chunk_join(chrome_name, "content")
content_root_path = "/%s/" % path_location.strip("/")
break
if not chrome_path:
return set()
applicable_overlays = set()
chrome_path = "chrome://%s" % self._url_chunk_join(chrome_path + "/")
for overlay in self.get_triples(subject="overlay"):
if not overlay["object"]:
error_bundle.error(
err_id=("chromemanifest", "get_applicable_overalys",
"object"),
error="Overlay instruction missing a property.",
description="When overlays are registered in a chrome "
"manifest file, they require a namespace and "
"a chrome URL at minimum.",
filename=overlay["filename"],
line=overlay["line"],
context=self.context) #TODO(basta): Update this!
continue
overlay_url = overlay["object"].split()[0]
if overlay_url.startswith(chrome_path):
overlay_relative_path = overlay_url[len(chrome_path):]
applicable_overlays.add("/%s" %
self._url_chunk_join(content_root_path,
overlay_relative_path))
return applicable_overlays
def reverse_lookup(self, state, path):
"""
Returns a chrome URL for a given path, given the current package depth
in an error bundle.
State may either be an error bundle or the actual package stack.
"""
# Make sure the path starts with a forward slash.
if not path.startswith("/"):
path = "/%s" % path
# If the state is an error bundle, extract the package stack.
if not isinstance(state, list):
state = state.package_stack
content_paths = self.get_triples(subject="content")
for content_path in content_paths:
chrome_name = content_path["predicate"]
if not content_path["object"]:
continue
path_location = content_path["object"].split()[0]
if path_location.startswith("jar:"):
if not state:
continue
# Parse out the JAR and it's location within the chrome.
split_jar_url = path_location[4:].split("!", 2)
# Ignore invalid/unsupported JAR URLs.
if len(split_jar_url) != 2:
continue
# Unpack the JAR URL.
jar_path, package_path = split_jar_url
if jar_path != state[0]:
continue
return "chrome://%s" % self._url_chunk_join(chrome_name,
package_path,
path)
else:
if state:
continue
path_location = "/%s/" % path_location.strip("/")
if not path.startswith(path_location):
continue
sliced_path = "/%s" % path[len(path_location):]
return "chrome://%s" % self._url_chunk_join(chrome_name,
sliced_path)
return None
def _url_chunk_join(self, *args):
"""Join the arguments together to form a predictable URL chunk."""
# Strip slashes from either side of each path piece.
pathlets = map(lambda s: s.strip("/"), args)
# Remove empty pieces.
pathlets = filter(None, pathlets)
url = "/".join(pathlets)
# If this is a directory, add a trailing slash.
if args[-1].endswith("/"):
url = "%s/" % url
return url
Jump to Line
Something went wrong with that request. Please try again.