1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import json
6import logging
7import os
8import threading
9import time
10
11
12class Blacklist(object):
13
14  def __init__(self, path):
15    self._blacklist_lock = threading.RLock()
16    self._path = path
17
18  def Read(self):
19    """Reads the blacklist from the blacklist file.
20
21    Returns:
22      A dict containing bad devices.
23    """
24    with self._blacklist_lock:
25      if not os.path.exists(self._path):
26        return dict()
27
28      with open(self._path, 'r') as f:
29        blacklist = json.load(f)
30      if not isinstance(blacklist, dict):
31        logging.warning('Ignoring %s: %s (a dict was expected instead)',
32                        self._path, blacklist)
33        blacklist = dict()
34      return blacklist
35
36  def Write(self, blacklist):
37    """Writes the provided blacklist to the blacklist file.
38
39    Args:
40      blacklist: list of bad devices to write to the blacklist file.
41    """
42    with self._blacklist_lock:
43      with open(self._path, 'w') as f:
44        json.dump(blacklist, f)
45
46  def Extend(self, devices, reason='unknown'):
47    """Adds devices to blacklist file.
48
49    Args:
50      devices: list of bad devices to be added to the blacklist file.
51      reason: string specifying the reason for blacklist (eg: 'unauthorized')
52    """
53    timestamp = time.time()
54    event_info = {
55        'timestamp': timestamp,
56        'reason': reason,
57    }
58    device_dicts = {device: event_info for device in devices}
59    logging.info('Adding %s to blacklist %s for reason: %s',
60                 ','.join(devices), self._path, reason)
61    with self._blacklist_lock:
62      blacklist = self.Read()
63      blacklist.update(device_dicts)
64      self.Write(blacklist)
65
66  def Reset(self):
67    """Erases the blacklist file if it exists."""
68    logging.info('Resetting blacklist %s', self._path)
69    with self._blacklist_lock:
70      if os.path.exists(self._path):
71        os.remove(self._path)
72