Home | History | Annotate | Download | only in sync
      1 // Copyright (c) 2011 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/js_event_handler_list.h"
      6 
      7 #include <cstddef>
      8 
      9 #include "base/logging.h"
     10 #include "chrome/browser/sync/js_backend.h"
     11 #include "chrome/browser/sync/js_event_handler.h"
     12 
     13 namespace browser_sync {
     14 
     15 JsEventHandlerList::PendingMessage::PendingMessage(
     16     const std::string& name, const JsArgList& args,
     17     const JsEventHandler* sender)
     18     : name(name), args(args), sender(sender) {}
     19 
     20 JsEventHandlerList::JsEventHandlerList() : backend_(NULL) {}
     21 
     22 JsEventHandlerList::~JsEventHandlerList() {
     23   RemoveBackend();
     24 }
     25 
     26 // We connect to the backend only when necessary, i.e. when there is
     27 // at least one handler.
     28 
     29 void JsEventHandlerList::AddHandler(JsEventHandler* handler) {
     30   handlers_.AddObserver(handler);
     31   if (backend_) {
     32     backend_->SetParentJsEventRouter(this);
     33   }
     34 }
     35 
     36 void JsEventHandlerList::RemoveHandler(JsEventHandler* handler) {
     37   handlers_.RemoveObserver(handler);
     38   if (backend_ && handlers_.size() == 0) {
     39     backend_->RemoveParentJsEventRouter();
     40   }
     41 }
     42 
     43 void JsEventHandlerList::SetBackend(JsBackend* backend) {
     44   DCHECK(!backend_);
     45   DCHECK(backend);
     46   backend_ = backend;
     47 
     48   if (handlers_.size() > 0) {
     49     backend_->SetParentJsEventRouter(this);
     50 
     51     // Process any queued messages.
     52     PendingMessageList pending_messages;
     53     pending_messages_.swap(pending_messages);
     54     for (PendingMessageList::const_iterator it = pending_messages.begin();
     55          it != pending_messages.end(); ++it) {
     56       backend_->ProcessMessage(it->name, it->args, it->sender);
     57     }
     58   }
     59 }
     60 
     61 void JsEventHandlerList::RemoveBackend() {
     62   if (backend_) {
     63     backend_->RemoveParentJsEventRouter();
     64     backend_ = NULL;
     65   }
     66 }
     67 
     68 void JsEventHandlerList::ProcessMessage(
     69     const std::string& name, const JsArgList& args,
     70     const JsEventHandler* sender) {
     71   if (backend_) {
     72     backend_->ProcessMessage(name, args, sender);
     73   } else {
     74     pending_messages_.push_back(PendingMessage(name, args, sender));
     75   }
     76 }
     77 
     78 void JsEventHandlerList::RouteJsEvent(const std::string& name,
     79                                       const JsArgList& args,
     80                                       const JsEventHandler* target) {
     81   if (target) {
     82     JsEventHandler* non_const_target(const_cast<JsEventHandler*>(target));
     83     if (handlers_.HasObserver(non_const_target)) {
     84       non_const_target->HandleJsEvent(name, args);
     85     } else {
     86       VLOG(1) << "Unknown target; dropping event " << name
     87               << " with args " << args.ToString();
     88     }
     89   } else {
     90     FOR_EACH_OBSERVER(JsEventHandler, handlers_, HandleJsEvent(name, args));
     91   }
     92 }
     93 
     94 }  // namespace browser_sync
     95