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

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: Address comments. Created 8 years, 6 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
« no previous file with comments | « remoting/client/plugin/chromoting_instance.h ('k') | remoting/host/desktop_environment.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 CR_DEFINE_STATIC_LOCAL(scoped_refptr<base::SingleThreadTaskRunner>,
101 g_logging_task_runner, ());
102 CR_DEFINE_STATIC_LOCAL(base::WeakPtr<ChromotingInstance>, g_logging_instance,
Sergey Ulanov 2012/05/30 00:30:37 nit: Might be more readable if formatted as follow
Wez 2012/05/30 00:54:02 Done.
103 ());
101 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; 104 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
102 105
103 static base::LazyInstance<base::Lock>::Leaky 106 static base::LazyInstance<base::Lock>::Leaky
104 g_logging_lock = LAZY_INSTANCE_INITIALIZER; 107 g_logging_lock = LAZY_INSTANCE_INITIALIZER;
105 108
106 // String sent in the "hello" message to the plugin to describe features. 109 // String sent in the "hello" message to the plugin to describe features.
107 const char ChromotingInstance::kApiFeatures[] = 110 const char ChromotingInstance::kApiFeatures[] =
108 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey " 111 "highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey "
109 "notifyClientDimensions pauseVideo"; 112 "notifyClientDimensions pauseVideo";
110 113
(...skipping 21 matching lines...) Expand all
132 135
133 return true; 136 return true;
134 } 137 }
135 138
136 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) 139 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
137 : pp::InstancePrivate(pp_instance), 140 : pp::InstancePrivate(pp_instance),
138 initialized_(false), 141 initialized_(false),
139 plugin_message_loop_( 142 plugin_message_loop_(
140 new PluginMessageLoopProxy(&plugin_thread_delegate_)), 143 new PluginMessageLoopProxy(&plugin_thread_delegate_)),
141 context_(plugin_message_loop_), 144 context_(plugin_message_loop_),
142 thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) { 145 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
143 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); 146 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
144 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); 147 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
145 148
146 // Resister this instance to handle debug log messsages. 149 // Resister this instance to handle debug log messsages.
147 RegisterLoggingInstance(); 150 RegisterLoggingInstance();
148 151
149 // Send hello message. 152 // Send hello message.
150 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); 153 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
151 data->SetInteger("apiVersion", kApiVersion); 154 data->SetInteger("apiVersion", kApiVersion);
152 data->SetString("apiFeatures", kApiFeatures); 155 data->SetString("apiFeatures", kApiFeatures);
153 data->SetInteger("apiMinVersion", kApiMinMessagingVersion); 156 data->SetInteger("apiMinVersion", kApiMinMessagingVersion);
154 PostChromotingMessage("hello", data.Pass()); 157 PostChromotingMessage("hello", data.Pass());
155 } 158 }
156 159
157 ChromotingInstance::~ChromotingInstance() { 160 ChromotingInstance::~ChromotingInstance() {
158 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 161 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
159 162
160 // Detach the log proxy so we don't log anything else to the UI. 163 // 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. 164 // This needs to be done before the instance is unregistered for logging.
162 thread_proxy_->Detach(); 165 //thread_proxy_->Detach();
Sergey Ulanov 2012/05/30 00:30:37 Did you mean to make this part for this CL? I'm no
Wez 2012/05/30 00:54:02 We now identify the ChromotingInstance to direct l
163 166
164 // Unregister this instance so that debug log messages will no longer be sent 167 // 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. 168 // to it. This will stop all logging in all Chromoting instances.
166 UnregisterLoggingInstance(); 169 UnregisterLoggingInstance();
167 170
168 if (client_.get()) { 171 if (client_.get()) {
169 base::WaitableEvent done_event(true, false); 172 base::WaitableEvent done_event(true, false);
170 client_->Stop(base::Bind(&base::WaitableEvent::Signal, 173 client_->Stop(base::Bind(&base::WaitableEvent::Signal,
171 base::Unretained(&done_event))); 174 base::Unretained(&done_event)));
172 done_event.Wait(); 175 done_event.Wait();
173 } 176 }
174 177
175 // Stopping the context shuts down all chromoting threads. 178 // Stopping the context shuts down all chromoting threads.
176 context_.Stop(); 179 context_.Stop();
177 180
178 // Delete |thread_proxy_| before we detach |plugin_message_loop_|, 181 // 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(); 182 plugin_message_loop_->Detach();
183 } 183 }
184 184
185 bool ChromotingInstance::Init(uint32_t argc, 185 bool ChromotingInstance::Init(uint32_t argc,
186 const char* argn[], 186 const char* argn[],
187 const char* argv[]) { 187 const char* argv[]) {
188 CHECK(!initialized_); 188 CHECK(!initialized_);
189 initialized_ = true; 189 initialized_ = true;
190 190
191 VLOG(1) << "Started ChromotingInstance::Init"; 191 VLOG(1) << "Started ChromotingInstance::Init";
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 logging::SetLogMessageHandler(&LogToUI); 607 logging::SetLogMessageHandler(&LogToUI);
608 } 608 }
609 609
610 void ChromotingInstance::RegisterLoggingInstance() { 610 void ChromotingInstance::RegisterLoggingInstance() {
611 base::AutoLock lock(g_logging_lock.Get()); 611 base::AutoLock lock(g_logging_lock.Get());
612 612
613 // Register this instance as the one that will handle all logging calls 613 // Register this instance as the one that will handle all logging calls
614 // and display them to the user. 614 // and display them to the user.
615 // If multiple plugins are run, then the last one registered will handle all 615 // If multiple plugins are run, then the last one registered will handle all
616 // logging for all instances. 616 // logging for all instances.
617 g_logging_instance = this; 617 g_logging_instance = weak_factory_.GetWeakPtr();
618 g_logging_task_runner = plugin_message_loop_;
618 g_has_logging_instance = true; 619 g_has_logging_instance = true;
619 } 620 }
620 621
621 void ChromotingInstance::UnregisterLoggingInstance() { 622 void ChromotingInstance::UnregisterLoggingInstance() {
622 base::AutoLock lock(g_logging_lock.Get()); 623 base::AutoLock lock(g_logging_lock.Get());
623 624
624 // Don't unregister unless we're the currently registered instance. 625 // Don't unregister unless we're the currently registered instance.
625 if (this != g_logging_instance) 626 if (this != g_logging_instance.get())
626 return; 627 return;
627 628
628 // Unregister this instance for logging. 629 // Unregister this instance for logging.
629 g_has_logging_instance = false; 630 g_has_logging_instance = false;
630 g_logging_instance = NULL; 631 g_logging_instance.reset();
632 g_logging_task_runner = NULL;
631 633
632 VLOG(1) << "Unregistering global log handler"; 634 VLOG(1) << "Unregistering global log handler";
633 } 635 }
634 636
635 // static 637 // static
636 bool ChromotingInstance::LogToUI(int severity, const char* file, int line, 638 bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
637 size_t message_start, 639 size_t message_start,
638 const std::string& str) { 640 const std::string& str) {
639 // Note that we're reading |g_has_logging_instance| outside of a lock. 641 // 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 642 // This lockless read is done so that we don't needlessly slow down global
641 // logging with a lock for each log message. 643 // logging with a lock for each log message.
642 // 644 //
643 // This lockless read is safe because: 645 // This lockless read is safe because:
644 // 646 //
645 // Misreading a false value (when it should be true) means that we'll simply 647 // Misreading a false value (when it should be true) means that we'll simply
646 // skip processing a few log messages. 648 // skip processing a few log messages.
647 // 649 //
648 // Misreading a true value (when it should be false) means that we'll take 650 // 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 651 // the lock and check |g_logging_instance| unnecessarily. This is not
650 // problematic because we always set |g_logging_instance| inside a lock. 652 // problematic because we always set |g_logging_instance| inside a lock.
651 if (g_has_logging_instance) { 653 if (g_has_logging_instance) {
652 // Do not LOG anything while holding this lock or else the code will 654 scoped_refptr<base::SingleThreadTaskRunner> logging_task_runner;
653 // deadlock while trying to re-get the lock we're already in. 655
654 base::AutoLock lock(g_logging_lock.Get()); 656 {
655 if (g_logging_instance && 657 base::AutoLock lock(g_logging_lock.Get());
656 // If |g_logging_to_plugin| is set and we're on the logging thread, then 658 // If we're on the logging thread and |g_logging_to_plugin| is set then
657 // this LOG message came from handling a previous LOG message and we 659 // this LOG action was generated while processing a previous one, in which
658 // should skip it to avoid an infinite loop of LOG messages. 660 // case we
Wez 2012/05/30 00:54:02 Gah, uploaded mid-edit!
659 // We don't have a lock around |g_in_processtoui|, but that's OK since 661 // If |g_logging_to_plugin| is set and we're on the logging thread, then
660 // the value is only read/written on the logging thread. 662 // this LOG message came from handling a previous LOG message and we
661 (!g_logging_instance->plugin_message_loop_->BelongsToCurrentThread() || 663 // should skip it to avoid an infinite loop of LOG messages.
662 !g_logging_to_plugin)) { 664 // We don't have a lock around |g_in_processtoui|, but that's OK since
665 // the value is only read/written on the logging thread.
666 if (!g_logging_task_runner->BelongsToCurrentThread() ||
667 !g_logging_to_plugin) {
668 logging_task_runner = g_logging_task_runner;
669 }
670 }
671
672 if (logging_task_runner.get()) {
663 std::string message = remoting::GetTimestampString(); 673 std::string message = remoting::GetTimestampString();
664 message += (str.c_str() + message_start); 674 message += (str.c_str() + message_start);
665 // |thread_proxy_| is safe to use here because we detach it before 675
666 // tearing down the |g_logging_instance|. 676 g_logging_task_runner->PostTask(
667 g_logging_instance->thread_proxy_->PostTask(
668 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI, 677 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
669 base::Unretained(g_logging_instance), message)); 678 g_logging_instance, message));
670 } 679 }
671 } 680 }
672 681
673 if (g_logging_old_handler) 682 if (g_logging_old_handler)
674 return (g_logging_old_handler)(severity, file, line, message_start, str); 683 return (g_logging_old_handler)(severity, file, line, message_start, str);
675 return false; 684 return false;
676 } 685 }
677 686
678 void ChromotingInstance::ProcessLogToUI(const std::string& message) { 687 void ChromotingInstance::ProcessLogToUI(const std::string& message) {
679 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 688 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
(...skipping 12 matching lines...) Expand all
692 } 701 }
693 g_logging_to_plugin = false; 702 g_logging_to_plugin = false;
694 } 703 }
695 704
696 bool ChromotingInstance::IsConnected() { 705 bool ChromotingInstance::IsConnected() {
697 return host_connection_.get() && 706 return host_connection_.get() &&
698 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED); 707 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED);
699 } 708 }
700 709
701 } // namespace remoting 710 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/plugin/chromoting_instance.h ('k') | remoting/host/desktop_environment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698