[M47_2526] Chromium upversion to m47_2526 branch
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / message_pump_for_ui_efl.cc
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.
4
5 #include "message_pump_for_ui_efl.h"
6
7 #define private public
8 #include "base/run_loop.h"
9 #undef private
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"
14
15 namespace base {
16
17 namespace {
18 static const char dummy_pipe_message[] = "W";
19 static const int dummy_pipe_message_size = 1;
20 }
21
22 MessagePumpForUIEfl::MessagePumpForUIEfl()
23   : pipe_(ecore_pipe_add(&PipeCallback, this))
24   , schedule_delayed_work_timer_(NULL)
25   , run_loop_(NULL)
26   , work_scheduled_(false) {
27 }
28
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);
35       delete *it;
36     }
37   } else {
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_);
42   }
43 }
44
45 // FIXME: need to be implemented for tests.
46 void MessagePumpForUIEfl::Run(base::MessagePump::Delegate* delegate) {
47   NOTREACHED();
48 }
49
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_);
56   if (run_loop_) {
57     DCHECK(run_loop_->running());
58     run_loop_->AfterRun();
59     delete run_loop_;
60     run_loop_ = NULL;
61   }
62   pipe_ = NULL;
63   schedule_delayed_work_timer_ = NULL;
64 }
65
66 void MessagePumpForUIEfl::ScheduleWork() {
67   {
68     base::AutoLock locker(schedule_work_lock_);
69     if (work_scheduled_)
70       return;
71     work_scheduled_ = true;
72   }
73
74   DCHECK(pipe_);
75   bool ok = ecore_pipe_write(pipe_, dummy_pipe_message, dummy_pipe_message_size);
76   DCHECK(ok);
77 }
78
79 void MessagePumpForUIEfl::ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) {
80   base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
81   base::TimeTicks now = base::TimeTicks::Now();
82   double delay = 0;
83   if (delayed_work_time > now)
84     delay = base::TimeDelta(delayed_work_time - now).InSecondsF();
85
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);
91   } else {
92     if (schedule_delayed_work_timer_) {
93         ecore_timer_delay(schedule_delayed_work_timer_, delay - ecore_timer_pending_get(schedule_delayed_work_timer_));
94     } else {
95         schedule_delayed_work_timer_ = ecore_timer_add(delay, &TimerCallback, this);
96     }
97   }
98 }
99
100 void MessagePumpForUIEfl::PipeCallback(void *data, void*, unsigned int) {
101   static_cast<MessagePumpForUIEfl*>(data)->DoWork();
102 }
103
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;
111   } else {
112     MessagePumpForUIEfl* messagePumpForUIEfl = static_cast<MessagePumpForUIEfl*>(data);
113     messagePumpForUIEfl->DoDelayedWork();
114     messagePumpForUIEfl->schedule_delayed_work_timer_ = NULL;
115   }
116
117   return ECORE_CALLBACK_CANCEL;
118 }
119
120 void MessagePumpForUIEfl::DoWork() {
121   {
122     base::AutoLock locker(schedule_work_lock_);
123     DCHECK(work_scheduled_);
124     work_scheduled_ = false;
125   }
126
127   Delegate* delegate = base::MessageLoopForUI::current();
128   if (!run_loop_) {
129     run_loop_ = new RunLoop();
130     bool result = run_loop_->BeforeRun();
131     DCHECK(result);
132   }
133
134   bool more_work_is_plausible = delegate->DoWork();
135
136   base::TimeTicks delayed_work_time;
137   more_work_is_plausible |= delegate->DoDelayedWork(&delayed_work_time);
138
139   if (more_work_is_plausible) {
140     ScheduleWork();
141     return;
142   }
143
144   more_work_is_plausible |= delegate->DoIdleWork();
145   if (more_work_is_plausible) {
146     ScheduleWork();
147     return;
148   }
149
150   if (!delayed_work_time.is_null())
151     ScheduleDelayedWork(delayed_work_time);
152 }
153
154 void MessagePumpForUIEfl::DoDelayedWork() {
155   base::TimeTicks next_delayed_work_time;
156   base::MessageLoopForUI::current()->DoDelayedWork(&next_delayed_work_time);
157
158   if (!next_delayed_work_time.is_null())
159     ScheduleDelayedWork(next_delayed_work_time);
160 }
161
162 }