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