Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: remoting/client/plugin/chromoting_instance.cc

Issue 10454040: Replace ScopedThreadProxy with MessageLoopProxy & WeakPtrs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/client/plugin/chromoting_instance.h" 5 #include "remoting/client/plugin/chromoting_instance.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 return ""; 90 return "";
91 } 91 }
92 92
93 } // namespace 93 } // namespace
94 94
95 // This flag blocks LOGs to the UI if we're already in the middle of logging 95 // This flag blocks LOGs to the UI if we're already in the middle of logging
96 // to the UI. This prevents a potential infinite loop if we encounter an error 96 // to the UI. This prevents a potential infinite loop if we encounter an error
97 // while sending the log message to the UI. 97 // while sending the log message to the UI.
98 static bool g_logging_to_plugin = false; 98 static bool g_logging_to_plugin = false;
99 static bool g_has_logging_instance = false; 99 static bool g_has_logging_instance = false;
100 static ChromotingInstance* g_logging_instance = NULL; 100 static scoped_refptr<base::MessageLoopProxy> g_logging_message_loop;
Sergey Ulanov 2012/05/29 18:58:30 This adds a static finalizer. Use CR_DEFINE_STATIC
Sergey Ulanov 2012/05/29 18:58:30 SingleThreadTaskRunner please.
Wez 2012/05/30 00:18:39 Done.
Wez 2012/05/30 00:18:39 Done.
101 static base::WeakPtr<ChromotingInstance> g_logging_instance;
Sergey Ulanov 2012/05/29 18:58:30 This adds a static finalizer. Use CR_DEFINE_STATIC
Wez 2012/05/30 00:18:39 Done.
101 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; 102 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
102 103
103 static base::LazyInstance<base::Lock>::Leaky 104 static base::LazyInstance<base::Lock>::Leaky
104 g_logging_lock = LAZY_INSTANCE_INITIALIZER; 105 g_logging_lock = LAZY_INSTANCE_INITIALIZER;
105 106
106 // String sent in the "hello" message to the plugin to describe features. 107 // String sent in the "hello" message to the plugin to describe features.
107 const char ChromotingInstance::kApiFeatures[] = 108 const char ChromotingInstance::kApiFeatures[] =
108 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey " 109 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey "
109 "notifyClientDimensions pauseVideo"; 110 "notifyClientDimensions pauseVideo";
110 111
(...skipping 21 matching lines...) Expand all
132 133
133 return true; 134 return true;
134 } 135 }
135 136
136 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) 137 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
137 : pp::InstancePrivate(pp_instance), 138 : pp::InstancePrivate(pp_instance),
138 initialized_(false), 139 initialized_(false),
139 plugin_message_loop_( 140 plugin_message_loop_(
140 new PluginMessageLoopProxy(&plugin_thread_delegate_)), 141 new PluginMessageLoopProxy(&plugin_thread_delegate_)),
141 context_(plugin_message_loop_), 142 context_(plugin_message_loop_),
142 thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) { 143 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
143 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); 144 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
144 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); 145 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
145 146
146 // Resister this instance to handle debug log messsages. 147 // Resister this instance to handle debug log messsages.
147 RegisterLoggingInstance(); 148 RegisterLoggingInstance();
148 149
149 // Send hello message. 150 // Send hello message.
150 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); 151 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
151 data->SetInteger("apiVersion", kApiVersion); 152 data->SetInteger("apiVersion", kApiVersion);
152 data->SetString("apiFeatures", kApiFeatures); 153 data->SetString("apiFeatures", kApiFeatures);
153 data->SetInteger("apiMinVersion", kApiMinMessagingVersion); 154 data->SetInteger("apiMinVersion", kApiMinMessagingVersion);
154 PostChromotingMessage("hello", data.Pass()); 155 PostChromotingMessage("hello", data.Pass());
155 } 156 }
156 157
157 ChromotingInstance::~ChromotingInstance() { 158 ChromotingInstance::~ChromotingInstance() {
158 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 159 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
159 160
160 // Detach the log proxy so we don't log anything else to the UI. 161 // Detach the log proxy so we don't log anything else to the UI.
161 // This needs to be done before the instance is unregistered for logging. 162 // This needs to be done before the instance is unregistered for logging.
162 thread_proxy_->Detach(); 163 //thread_proxy_->Detach();
163 164
164 // Unregister this instance so that debug log messages will no longer be sent 165 // Unregister this instance so that debug log messages will no longer be sent
165 // to it. This will stop all logging in all Chromoting instances. 166 // to it. This will stop all logging in all Chromoting instances.
166 UnregisterLoggingInstance(); 167 UnregisterLoggingInstance();
167 168
168 if (client_.get()) { 169 if (client_.get()) {
169 base::WaitableEvent done_event(true, false); 170 base::WaitableEvent done_event(true, false);
170 client_->Stop(base::Bind(&base::WaitableEvent::Signal, 171 client_->Stop(base::Bind(&base::WaitableEvent::Signal,
171 base::Unretained(&done_event))); 172 base::Unretained(&done_event)));
172 done_event.Wait(); 173 done_event.Wait();
173 } 174 }
174 175
175 // Stopping the context shuts down all chromoting threads. 176 // Stopping the context shuts down all chromoting threads.
176 context_.Stop(); 177 context_.Stop();
177 178
178 // Delete |thread_proxy_| before we detach |plugin_message_loop_|, 179 // Ensure that nothing touches the plugin thread delegate after this point.
179 // otherwise ScopedThreadProxy may DCHECK when being destroyed.
180 thread_proxy_.reset();
181
182 plugin_message_loop_->Detach(); 180 plugin_message_loop_->Detach();
183 } 181 }
184 182
185 bool ChromotingInstance::Init(uint32_t argc, 183 bool ChromotingInstance::Init(uint32_t argc,
186 const char* argn[], 184 const char* argn[],
187 const char* argv[]) { 185 const char* argv[]) {
188 CHECK(!initialized_); 186 CHECK(!initialized_);
189 initialized_ = true; 187 initialized_ = true;
190 188
191 VLOG(1) << "Started ChromotingInstance::Init"; 189 VLOG(1) << "Started ChromotingInstance::Init";
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 logging::SetLogMessageHandler(&LogToUI); 605 logging::SetLogMessageHandler(&LogToUI);
608 } 606 }
609 607
610 void ChromotingInstance::RegisterLoggingInstance() { 608 void ChromotingInstance::RegisterLoggingInstance() {
611 base::AutoLock lock(g_logging_lock.Get()); 609 base::AutoLock lock(g_logging_lock.Get());
612 610
613 // Register this instance as the one that will handle all logging calls 611 // Register this instance as the one that will handle all logging calls
614 // and display them to the user. 612 // and display them to the user.
615 // If multiple plugins are run, then the last one registered will handle all 613 // If multiple plugins are run, then the last one registered will handle all
616 // logging for all instances. 614 // logging for all instances.
617 g_logging_instance = this; 615 g_logging_instance = weak_factory_.GetWeakPtr();
616 g_logging_message_loop = plugin_message_loop_;
618 g_has_logging_instance = true; 617 g_has_logging_instance = true;
619 } 618 }
620 619
621 void ChromotingInstance::UnregisterLoggingInstance() { 620 void ChromotingInstance::UnregisterLoggingInstance() {
622 base::AutoLock lock(g_logging_lock.Get()); 621 base::AutoLock lock(g_logging_lock.Get());
623 622
624 // Don't unregister unless we're the currently registered instance. 623 // Don't unregister unless we're the currently registered instance.
625 if (this != g_logging_instance) 624 if (this != g_logging_instance.get())
626 return; 625 return;
627 626
628 // Unregister this instance for logging. 627 // Unregister this instance for logging.
629 g_has_logging_instance = false; 628 g_has_logging_instance = false;
630 g_logging_instance = NULL; 629 g_logging_instance.reset();
630 g_logging_message_loop = NULL;
631 631
632 VLOG(1) << "Unregistering global log handler"; 632 VLOG(1) << "Unregistering global log handler";
633 } 633 }
634 634
635 // static 635 // static
636 bool ChromotingInstance::LogToUI(int severity, const char* file, int line, 636 bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
637 size_t message_start, 637 size_t message_start,
638 const std::string& str) { 638 const std::string& str) {
639 // Note that we're reading |g_has_logging_instance| outside of a lock. 639 // Note that we're reading |g_has_logging_instance| outside of a lock.
640 // This lockless read is done so that we don't needlessly slow down global 640 // This lockless read is done so that we don't needlessly slow down global
641 // logging with a lock for each log message. 641 // logging with a lock for each log message.
642 // 642 //
643 // This lockless read is safe because: 643 // This lockless read is safe because:
644 // 644 //
645 // Misreading a false value (when it should be true) means that we'll simply 645 // Misreading a false value (when it should be true) means that we'll simply
646 // skip processing a few log messages. 646 // skip processing a few log messages.
647 // 647 //
648 // Misreading a true value (when it should be false) means that we'll take 648 // Misreading a true value (when it should be false) means that we'll take
649 // the lock and check |g_logging_instance| unnecessarily. This is not 649 // the lock and check |g_logging_instance| unnecessarily. This is not
650 // problematic because we always set |g_logging_instance| inside a lock. 650 // problematic because we always set |g_logging_instance| inside a lock.
651 if (g_has_logging_instance) { 651 if (g_has_logging_instance) {
652 // Do not LOG anything while holding this lock or else the code will 652 // Do not LOG anything while holding this lock or else the code will
653 // deadlock while trying to re-get the lock we're already in. 653 // deadlock while trying to re-get the lock we're already in.
654 base::AutoLock lock(g_logging_lock.Get()); 654 base::AutoLock lock(g_logging_lock.Get());
655 if (g_logging_instance && 655 if (g_logging_message_loop.get() &&
656 // If |g_logging_to_plugin| is set and we're on the logging thread, then 656 // If |g_logging_to_plugin| is set and we're on the logging thread, then
657 // this LOG message came from handling a previous LOG message and we 657 // this LOG message came from handling a previous LOG message and we
658 // should skip it to avoid an infinite loop of LOG messages. 658 // should skip it to avoid an infinite loop of LOG messages.
659 // We don't have a lock around |g_in_processtoui|, but that's OK since 659 // We don't have a lock around |g_in_processtoui|, but that's OK since
660 // the value is only read/written on the logging thread. 660 // the value is only read/written on the logging thread.
661 (!g_logging_instance->plugin_message_loop_->BelongsToCurrentThread() || 661 (!g_logging_message_loop->BelongsToCurrentThread() ||
Sergey Ulanov 2012/05/29 18:58:30 Races are still possible in this code. The logging
Wez 2012/05/30 00:18:39 There is already a lock held at this point (g_logg
662 !g_logging_to_plugin)) { 662 !g_logging_to_plugin)) {
663 std::string message = remoting::GetTimestampString(); 663 std::string message = remoting::GetTimestampString();
664 message += (str.c_str() + message_start); 664 message += (str.c_str() + message_start);
665 // |thread_proxy_| is safe to use here because we detach it before 665
666 // tearing down the |g_logging_instance|. 666 g_logging_message_loop->PostTask(
667 g_logging_instance->thread_proxy_->PostTask(
668 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI, 667 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
669 base::Unretained(g_logging_instance), message)); 668 g_logging_instance, message));
670 } 669 }
671 } 670 }
672 671
673 if (g_logging_old_handler) 672 if (g_logging_old_handler)
674 return (g_logging_old_handler)(severity, file, line, message_start, str); 673 return (g_logging_old_handler)(severity, file, line, message_start, str);
675 return false; 674 return false;
676 } 675 }
677 676
678 void ChromotingInstance::ProcessLogToUI(const std::string& message) { 677 void ChromotingInstance::ProcessLogToUI(const std::string& message) {
679 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 678 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
(...skipping 12 matching lines...) Expand all
692 } 691 }
693 g_logging_to_plugin = false; 692 g_logging_to_plugin = false;
694 } 693 }
695 694
696 bool ChromotingInstance::IsConnected() { 695 bool ChromotingInstance::IsConnected() {
697 return host_connection_.get() && 696 return host_connection_.get() &&
698 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED); 697 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED);
699 } 698 }
700 699
701 } // namespace remoting 700 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698