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
PendingMessage(const std::string & name,const JsArgList & args,const JsEventHandler * sender)15 JsEventHandlerList::PendingMessage::PendingMessage(
16 const std::string& name, const JsArgList& args,
17 const JsEventHandler* sender)
18 : name(name), args(args), sender(sender) {}
19
JsEventHandlerList()20 JsEventHandlerList::JsEventHandlerList() : backend_(NULL) {}
21
~JsEventHandlerList()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
AddHandler(JsEventHandler * handler)29 void JsEventHandlerList::AddHandler(JsEventHandler* handler) {
30 handlers_.AddObserver(handler);
31 if (backend_) {
32 backend_->SetParentJsEventRouter(this);
33 }
34 }
35
RemoveHandler(JsEventHandler * handler)36 void JsEventHandlerList::RemoveHandler(JsEventHandler* handler) {
37 handlers_.RemoveObserver(handler);
38 if (backend_ && handlers_.size() == 0) {
39 backend_->RemoveParentJsEventRouter();
40 }
41 }
42
SetBackend(JsBackend * backend)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
RemoveBackend()61 void JsEventHandlerList::RemoveBackend() {
62 if (backend_) {
63 backend_->RemoveParentJsEventRouter();
64 backend_ = NULL;
65 }
66 }
67
ProcessMessage(const std::string & name,const JsArgList & args,const JsEventHandler * sender)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
RouteJsEvent(const std::string & name,const JsArgList & args,const JsEventHandler * target)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