extensions_activity_monitor.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2009 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
5#include "chrome/browser/sync/util/extensions_activity_monitor.h"
6
7#include "base/task.h"
8#include "chrome/browser/browser_thread.h"
9#include "chrome/browser/extensions/extension_bookmarks_module.h"
10#include "chrome/common/extensions/extension.h"
11#include "chrome/common/notification_service.h"
12
13namespace browser_sync {
14
15namespace {
16// A helper task to register an ExtensionsActivityMonitor as an observer of
17// events on the UI thread (even though the monitor may live on another thread).
18// This liberates ExtensionsActivityMonitor from having to be ref counted.
19class RegistrationTask : public Task {
20 public:
21  RegistrationTask(ExtensionsActivityMonitor* monitor,
22                   NotificationRegistrar* registrar)
23      : monitor_(monitor), registrar_(registrar) {}
24  virtual ~RegistrationTask() {}
25
26  virtual void Run() {
27    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
28
29    // It would be nice if we could specify a Source for each specific function
30    // we wanted to observe, but the actual function objects are allocated on
31    // the fly so there is no reliable object to point to (same problem if we
32    // wanted to use the string name).  Thus, we use all sources and filter in
33    // Observe.
34    registrar_->Add(monitor_, NotificationType::EXTENSION_BOOKMARKS_API_INVOKED,
35                    NotificationService::AllSources());
36  }
37
38 private:
39  ExtensionsActivityMonitor* monitor_;
40  NotificationRegistrar* registrar_;
41  DISALLOW_COPY_AND_ASSIGN(RegistrationTask);
42};
43}  // namespace
44
45ExtensionsActivityMonitor::ExtensionsActivityMonitor() {
46  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
47                          new RegistrationTask(this, &registrar_));
48}
49
50ExtensionsActivityMonitor::~ExtensionsActivityMonitor() {
51  // In some unrelated unit tests, there is no running UI loop.  In this case,
52  // the PostTask in our ctor will not result in anything running, so |this|
53  // won't be used for anything. In this case (or whenever no registration took
54  // place) and only this case we allow destruction on another loop, but this
55  // isn't something a client of this class can control; it happens implicitly
56  // by not having a running UI thread.
57  if (!registrar_.IsEmpty()) {
58    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
59
60    // The registrar calls RemoveAll in its dtor (which would happen in a
61    // moment but explicitly call this so it is clear why we need to be on the
62    // ui_loop_.
63    registrar_.RemoveAll();
64  }
65}
66
67void ExtensionsActivityMonitor::GetAndClearRecords(Records* buffer) {
68  AutoLock lock(records_lock_);
69  buffer->clear();
70  buffer->swap(records_);
71}
72
73void ExtensionsActivityMonitor::PutRecords(const Records& records) {
74  AutoLock lock(records_lock_);
75  for (Records::const_iterator i = records.begin(); i != records.end(); ++i) {
76    records_[i->first].extension_id = i->second.extension_id;
77    records_[i->first].bookmark_write_count += i->second.bookmark_write_count;
78  }
79}
80
81void ExtensionsActivityMonitor::Observe(NotificationType type,
82                                        const NotificationSource& source,
83                                        const NotificationDetails& details) {
84  AutoLock lock(records_lock_);
85  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86  const Extension* extension = Source<const Extension>(source).ptr();
87  const BookmarksFunction* f = Details<const BookmarksFunction>(details).ptr();
88  if (f->name() == "bookmarks.update" ||
89      f->name() == "bookmarks.move" ||
90      f->name() == "bookmarks.create" ||
91      f->name() == "bookmarks.removeTree" ||
92      f->name() == "bookmarks.remove") {
93    Record& record = records_[extension->id()];
94    record.extension_id = extension->id();
95    record.bookmark_write_count++;
96  }
97}
98
99}  // namespace browser_sync
100