Files
mitmproxy/mitmproxy/addons.py
Aldo Cortesi 9a0195bf64 scripts: keep scripts just after the ScriptLoader in addon chain
We need scripts to run _before_ filestreamer, so we can't just add them to the
end of the chain. This patch also fixes an issue that could cause scripts to be
initialised un-necessarily if only the order of scripts in options changed.
2016-10-16 20:26:06 +13:00

86 lines
2.4 KiB
Python

from __future__ import absolute_import, print_function, division
from mitmproxy import exceptions
import pprint
def _get_name(itm):
return getattr(itm, "name", itm.__class__.__name__.lower())
class Addons(object):
def __init__(self, master):
self.chain = []
self.master = master
master.options.changed.connect(self._options_update)
def get(self, name):
"""
Retrieve an addon by name. Addon names are equal to the .name
attribute on the instance, or the lower case class name if that
does not exist.
"""
for i in self.chain:
if name == _get_name(i):
return i
def _options_update(self, options, updated):
for i in self.chain:
with self.master.handlecontext():
i.configure(options, updated)
def startup(self, s):
"""
Run startup events on addon.
"""
self.invoke_with_context(s, "start")
self.invoke_with_context(
s,
"configure",
self.master.options,
self.master.options.keys()
)
def add(self, *addons):
"""
Add addons to the end of the chain, and run their startup events.
"""
if not addons:
raise ValueError("No addons specified.")
self.chain.extend(addons)
for i in addons:
self.startup(i)
def remove(self, addon):
"""
Remove an addon from the chain, and run its done events.
"""
self.chain = [i for i in self.chain if i is not addon]
self.invoke_with_context(addon, "done")
def done(self):
for i in self.chain:
self.invoke_with_context(i, "done")
def __len__(self):
return len(self.chain)
def __str__(self):
return pprint.pformat([str(i) for i in self.chain])
def invoke_with_context(self, addon, name, *args, **kwargs):
with self.master.handlecontext():
self.invoke(addon, name, *args, **kwargs)
def invoke(self, addon, name, *args, **kwargs):
func = getattr(addon, name, None)
if func:
if not callable(func):
raise exceptions.AddonError(
"Addon handler %s not callable" % name
)
func(*args, **kwargs)
def __call__(self, name, *args, **kwargs):
for i in self.chain:
self.invoke(i, name, *args, **kwargs)