1 // Copyright 2013 Samsung Electronics. 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.
5 #include "message_pump_for_ui_efl.h"
8 #include "base/run_loop.h"
10 #include "base/command_line.h"
11 #include "base/time/time.h"
12 #include "cc/base/switches.h"
13 #include "common/content_switches_efl.h"
18 static const char dummy_pipe_message[] = "W";
19 static const int dummy_pipe_message_size = 1;
22 MessagePumpForUIEfl::MessagePumpForUIEfl()
23 : pipe_(ecore_pipe_add(&PipeCallback, this))
24 , schedule_delayed_work_timer_(NULL)
26 , work_scheduled_(false) {
29 MessagePumpForUIEfl::~MessagePumpForUIEfl() {
30 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
31 if (!cmdline->HasSwitch(switches::kLimitMemoryAllocationInScheduleDelayedWork)) {
32 for (std::unordered_set<TimerPair*>::iterator it = pending_timers_.begin();
33 it != pending_timers_.end(); ++it) {
34 ecore_timer_del((*it)->second);
38 // Since we pass |this| object to timer's callback, deactivate the timer
39 // to prevent it from accessing invalid |this| object.
40 if (schedule_delayed_work_timer_)
41 ecore_timer_del(schedule_delayed_work_timer_);
45 // FIXME: need to be implemented for tests.
46 void MessagePumpForUIEfl::Run(base::MessagePump::Delegate* delegate) {
50 // FIXME: need to be implemented for tests.
51 void MessagePumpForUIEfl::Quit() {
52 // RunLoop must be destroyed before chromium cleanup
53 ecore_pipe_del(pipe_);
54 if (schedule_delayed_work_timer_)
55 ecore_timer_del(schedule_delayed_work_timer_);
57 DCHECK(run_loop_->running());
58 run_loop_->AfterRun();
63 schedule_delayed_work_timer_ = NULL;
66 void MessagePumpForUIEfl::ScheduleWork() {
68 base::AutoLock locker(schedule_work_lock_);
71 work_scheduled_ = true;
75 bool ok = ecore_pipe_write(pipe_, dummy_pipe_message, dummy_pipe_message_size);
79 void MessagePumpForUIEfl::ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) {
80 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
81 base::TimeTicks now = base::TimeTicks::Now();
83 if (delayed_work_time > now)
84 delay = base::TimeDelta(delayed_work_time - now).InSecondsF();
86 if (!cmdline->HasSwitch(switches::kLimitMemoryAllocationInScheduleDelayedWork)) {
87 TimerPair* new_pair = new TimerPair();
88 new_pair->first = this;
89 new_pair->second = ecore_timer_add(delay, &TimerCallback, new_pair);
90 pending_timers_.insert(new_pair);
92 if (schedule_delayed_work_timer_) {
93 ecore_timer_delay(schedule_delayed_work_timer_, delay - ecore_timer_pending_get(schedule_delayed_work_timer_));
95 schedule_delayed_work_timer_ = ecore_timer_add(delay, &TimerCallback, this);
100 void MessagePumpForUIEfl::PipeCallback(void *data, void*, unsigned int) {
101 static_cast<MessagePumpForUIEfl*>(data)->DoWork();
104 Eina_Bool MessagePumpForUIEfl::TimerCallback(void* data) {
105 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
106 if (!cmdline->HasSwitch(switches::kLimitMemoryAllocationInScheduleDelayedWork)) {
107 TimerPair* current_timer_pair = static_cast<TimerPair*>(data);
108 current_timer_pair->first->DoDelayedWork();
109 current_timer_pair->first->pending_timers_.erase(current_timer_pair);
110 delete current_timer_pair;
112 MessagePumpForUIEfl* messagePumpForUIEfl = static_cast<MessagePumpForUIEfl*>(data);
113 messagePumpForUIEfl->DoDelayedWork();
114 messagePumpForUIEfl->schedule_delayed_work_timer_ = NULL;
117 return ECORE_CALLBACK_CANCEL;
120 void MessagePumpForUIEfl::DoWork() {
122 base::AutoLock locker(schedule_work_lock_);
123 DCHECK(work_scheduled_);
124 work_scheduled_ = false;
127 Delegate* delegate = base::MessageLoopForUI::current();
129 run_loop_ = new RunLoop();
130 bool result = run_loop_->BeforeRun();
134 bool more_work_is_plausible = delegate->DoWork();
136 base::TimeTicks delayed_work_time;
137 more_work_is_plausible |= delegate->DoDelayedWork(&delayed_work_time);
139 if (more_work_is_plausible) {
144 more_work_is_plausible |= delegate->DoIdleWork();
145 if (more_work_is_plausible) {
150 if (!delayed_work_time.is_null())
151 ScheduleDelayedWork(delayed_work_time);
154 void MessagePumpForUIEfl::DoDelayedWork() {
155 base::TimeTicks next_delayed_work_time;
156 base::MessageLoopForUI::current()->DoDelayedWork(&next_delayed_work_time);
158 if (!next_delayed_work_time.is_null())
159 ScheduleDelayedWork(next_delayed_work_time);