blob: d53b8db0d8cf1f21edf0de88e42ad55d5824e617 [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/dom/event_listener.h"
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "cobalt/base/user_log.h"
#include "cobalt/dom/event_target.h"
namespace cobalt {
namespace dom {
namespace {
// This class records the nested events and manages the user log information.
class ScriptEventLog {
public:
ScriptEventLog() : current_stack_depth_(0) {
base::UserLog::Register(base::UserLog::kEventStackLevelCountIndex,
"EventLevelCnt", &current_stack_depth_,
sizeof(current_stack_depth_));
memset(event_log_stack_, 0, sizeof(event_log_stack_));
const int kLogNameBufferSize = 16;
char log_name_buffer[kLogNameBufferSize];
for (int i = 0; i < base::UserLog::kEventStackMaxDepth; i++) {
snprintf(log_name_buffer, kLogNameBufferSize, "EventLevel%d", i);
base::UserLog::Register(static_cast<base::UserLog::Index>(
base::UserLog::kEventStackMinLevelIndex + i),
log_name_buffer, event_log_stack_[i],
kLogEntryMaxLength);
}
}
~ScriptEventLog() {
base::UserLog::Deregister(base::UserLog::kEventStackLevelCountIndex);
for (int i = 0; i < base::UserLog::kEventStackMaxDepth; i++) {
base::UserLog::Deregister(static_cast<base::UserLog::Index>(
base::UserLog::kEventStackMinLevelIndex + i));
}
}
void PushEvent(Event* event) {
if (current_stack_depth_ < base::UserLog::kEventStackMaxDepth) {
snprintf(event_log_stack_[current_stack_depth_], kLogEntryMaxLength,
"%s@%s", event->type().c_str(),
event->current_target()->GetDebugName().c_str());
} else if (current_stack_depth_ == base::UserLog::kEventStackMaxDepth) {
DLOG(WARNING) << "Reached maximum depth of " << kLogEntryMaxLength
<< ". Subsequent events will not be logged.";
}
current_stack_depth_++;
}
void PopEvent() {
DCHECK(current_stack_depth_);
current_stack_depth_--;
if (current_stack_depth_ < base::UserLog::kEventStackMaxDepth) {
memset(event_log_stack_[current_stack_depth_], 0, kLogEntryMaxLength);
}
}
private:
static const size_t kLogEntryMaxLength = 64;
int current_stack_depth_;
char event_log_stack_[base::UserLog::kEventStackMaxDepth][kLogEntryMaxLength];
DISALLOW_COPY_AND_ASSIGN(ScriptEventLog);
};
base::LazyInstance<ScriptEventLog> script_event_log = LAZY_INSTANCE_INITIALIZER;
} // namespace
void EventListener::HandleEvent(const scoped_refptr<Event>& event,
Type listener_type) const {
TRACE_EVENT1("cobalt::dom", "EventListener::HandleEvent", "Event Name",
TRACE_STR_COPY(event->type().c_str()));
script_event_log.Get().PushEvent(event);
bool had_exception;
base::optional<bool> result =
HandleEvent(event->current_target(), event, &had_exception);
script_event_log.Get().PopEvent();
if (had_exception) {
return;
}
// EventHandlers (EventListeners set as attributes) may return false rather
// than call event.preventDefault() in the handler function.
if (listener_type == kAttribute && result && !result.value()) {
event->PreventDefault();
}
}
} // namespace dom
} // namespace cobalt