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

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 review points and tweak 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(
101 scoped_refptr<base::SingleThreadTaskRunner>, g_logging_task_runner, ());
102 CR_DEFINE_STATIC_LOCAL(
103 base::WeakPtr<ChromotingInstance>, g_logging_instance, ());
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 15 matching lines...) Expand all
126 129
127 return true; 130 return true;
128 } 131 }
129 132
130 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) 133 ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
131 : pp::InstancePrivate(pp_instance), 134 : pp::InstancePrivate(pp_instance),
132 initialized_(false), 135 initialized_(false),
133 plugin_message_loop_( 136 plugin_message_loop_(
134 new PluginMessageLoopProxy(&plugin_thread_delegate_)), 137 new PluginMessageLoopProxy(&plugin_thread_delegate_)),
135 context_(plugin_message_loop_), 138 context_(plugin_message_loop_),
136 thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) { 139 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
137 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); 140 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
138 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); 141 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
139 142
140 // Resister this instance to handle debug log messsages. 143 // Resister this instance to handle debug log messsages.
141 RegisterLoggingInstance(); 144 RegisterLoggingInstance();
142 145
143 // Send hello message. 146 // Send hello message.
144 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); 147 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
145 data->SetInteger("apiVersion", kApiVersion); 148 data->SetInteger("apiVersion", kApiVersion);
146 data->SetString("apiFeatures", kApiFeatures); 149 data->SetString("apiFeatures", kApiFeatures);
147 data->SetInteger("apiMinVersion", kApiMinMessagingVersion); 150 data->SetInteger("apiMinVersion", kApiMinMessagingVersion);
148 PostChromotingMessage("hello", data.Pass()); 151 PostChromotingMessage("hello", data.Pass());
149 } 152 }
150 153
151 ChromotingInstance::~ChromotingInstance() { 154 ChromotingInstance::~ChromotingInstance() {
152 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 155 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
153 156
154 // Detach the log proxy so we don't log anything else to the UI.
155 // This needs to be done before the instance is unregistered for logging.
156 thread_proxy_->Detach();
157
158 // Unregister this instance so that debug log messages will no longer be sent 157 // Unregister this instance so that debug log messages will no longer be sent
159 // to it. This will stop all logging in all Chromoting instances. 158 // to it. This will stop all logging in all Chromoting instances.
160 UnregisterLoggingInstance(); 159 UnregisterLoggingInstance();
161 160
162 if (client_.get()) { 161 if (client_.get()) {
163 base::WaitableEvent done_event(true, false); 162 base::WaitableEvent done_event(true, false);
164 client_->Stop(base::Bind(&base::WaitableEvent::Signal, 163 client_->Stop(base::Bind(&base::WaitableEvent::Signal,
165 base::Unretained(&done_event))); 164 base::Unretained(&done_event)));
166 done_event.Wait(); 165 done_event.Wait();
167 } 166 }
168 167
169 // Stopping the context shuts down all chromoting threads. 168 // Stopping the context shuts down all chromoting threads.
170 context_.Stop(); 169 context_.Stop();
171 170
172 // Delete |thread_proxy_| before we detach |plugin_message_loop_|, 171 // Ensure that nothing touches the plugin thread delegate after this point.
173 // otherwise ScopedThreadProxy may DCHECK when being destroyed.
174 thread_proxy_.reset();
175
176 plugin_message_loop_->Detach(); 172 plugin_message_loop_->Detach();
177 } 173 }
178 174
179 bool ChromotingInstance::Init(uint32_t argc, 175 bool ChromotingInstance::Init(uint32_t argc,
180 const char* argn[], 176 const char* argn[],
181 const char* argv[]) { 177 const char* argv[]) {
182 CHECK(!initialized_); 178 CHECK(!initialized_);
183 initialized_ = true; 179 initialized_ = true;
184 180
185 VLOG(1) << "Started ChromotingInstance::Init"; 181 VLOG(1) << "Started ChromotingInstance::Init";
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 logging::SetLogMessageHandler(&LogToUI); 597 logging::SetLogMessageHandler(&LogToUI);
602 } 598 }
603 599
604 void ChromotingInstance::RegisterLoggingInstance() { 600 void ChromotingInstance::RegisterLoggingInstance() {
605 base::AutoLock lock(g_logging_lock.Get()); 601 base::AutoLock lock(g_logging_lock.Get());
606 602
607 // Register this instance as the one that will handle all logging calls 603 // Register this instance as the one that will handle all logging calls
608 // and display them to the user. 604 // and display them to the user.
609 // If multiple plugins are run, then the last one registered will handle all 605 // If multiple plugins are run, then the last one registered will handle all
610 // logging for all instances. 606 // logging for all instances.
611 g_logging_instance = this; 607 g_logging_instance = weak_factory_.GetWeakPtr();
608 g_logging_task_runner = plugin_message_loop_;
612 g_has_logging_instance = true; 609 g_has_logging_instance = true;
613 } 610 }
614 611
615 void ChromotingInstance::UnregisterLoggingInstance() { 612 void ChromotingInstance::UnregisterLoggingInstance() {
616 base::AutoLock lock(g_logging_lock.Get()); 613 base::AutoLock lock(g_logging_lock.Get());
617 614
618 // Don't unregister unless we're the currently registered instance. 615 // Don't unregister unless we're the currently registered instance.
619 if (this != g_logging_instance) 616 if (this != g_logging_instance.get())
620 return; 617 return;
621 618
622 // Unregister this instance for logging. 619 // Unregister this instance for logging.
623 g_has_logging_instance = false; 620 g_has_logging_instance = false;
624 g_logging_instance = NULL; 621 g_logging_instance.reset();
622 g_logging_task_runner = NULL;
625 623
626 VLOG(1) << "Unregistering global log handler"; 624 VLOG(1) << "Unregistering global log handler";
627 } 625 }
628 626
629 // static 627 // static
630 bool ChromotingInstance::LogToUI(int severity, const char* file, int line, 628 bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
631 size_t message_start, 629 size_t message_start,
632 const std::string& str) { 630 const std::string& str) {
633 // Note that we're reading |g_has_logging_instance| outside of a lock. 631 // Note that we're reading |g_has_logging_instance| outside of a lock.
634 // This lockless read is done so that we don't needlessly slow down global 632 // This lockless read is done so that we don't needlessly slow down global
635 // logging with a lock for each log message. 633 // logging with a lock for each log message.
636 // 634 //
637 // This lockless read is safe because: 635 // This lockless read is safe because:
638 // 636 //
639 // Misreading a false value (when it should be true) means that we'll simply 637 // Misreading a false value (when it should be true) means that we'll simply
640 // skip processing a few log messages. 638 // skip processing a few log messages.
641 // 639 //
642 // Misreading a true value (when it should be false) means that we'll take 640 // Misreading a true value (when it should be false) means that we'll take
643 // the lock and check |g_logging_instance| unnecessarily. This is not 641 // the lock and check |g_logging_instance| unnecessarily. This is not
644 // problematic because we always set |g_logging_instance| inside a lock. 642 // problematic because we always set |g_logging_instance| inside a lock.
645 if (g_has_logging_instance) { 643 if (g_has_logging_instance) {
646 // Do not LOG anything while holding this lock or else the code will 644 scoped_refptr<base::SingleThreadTaskRunner> logging_task_runner;
647 // deadlock while trying to re-get the lock we're already in. 645
648 base::AutoLock lock(g_logging_lock.Get()); 646 {
649 if (g_logging_instance && 647 base::AutoLock lock(g_logging_lock.Get());
650 // If |g_logging_to_plugin| is set and we're on the logging thread, then 648 // If we're on the logging thread and |g_logging_to_plugin| is set then
651 // this LOG message came from handling a previous LOG message and we 649 // this LOG message came from handling a previous LOG message and we
652 // should skip it to avoid an infinite loop of LOG messages. 650 // should skip it to avoid an infinite loop of LOG messages.
653 // We don't have a lock around |g_in_processtoui|, but that's OK since 651 if (!g_logging_task_runner->BelongsToCurrentThread() ||
654 // the value is only read/written on the logging thread. 652 !g_logging_to_plugin) {
655 (!g_logging_instance->plugin_message_loop_->BelongsToCurrentThread() || 653 logging_task_runner = g_logging_task_runner;
656 !g_logging_to_plugin)) { 654 }
655 }
656
657 if (logging_task_runner.get()) {
657 std::string message = remoting::GetTimestampString(); 658 std::string message = remoting::GetTimestampString();
658 message += (str.c_str() + message_start); 659 message += (str.c_str() + message_start);
659 // |thread_proxy_| is safe to use here because we detach it before 660
660 // tearing down the |g_logging_instance|. 661 g_logging_task_runner->PostTask(
661 g_logging_instance->thread_proxy_->PostTask(
662 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI, 662 FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
663 base::Unretained(g_logging_instance), message)); 663 g_logging_instance, message));
664 } 664 }
665 } 665 }
666 666
667 if (g_logging_old_handler) 667 if (g_logging_old_handler)
668 return (g_logging_old_handler)(severity, file, line, message_start, str); 668 return (g_logging_old_handler)(severity, file, line, message_start, str);
669 return false; 669 return false;
670 } 670 }
671 671
672 void ChromotingInstance::ProcessLogToUI(const std::string& message) { 672 void ChromotingInstance::ProcessLogToUI(const std::string& message) {
673 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 673 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
674 674
675 // This flag (which is set only here) is used to prevent LogToUI from posting 675 // This flag (which is set only here) is used to prevent LogToUI from posting
676 // new tasks while we're in the middle of servicing a LOG call. This can 676 // new tasks while we're in the middle of servicing a LOG call. This can
677 // happen if the call to LogDebugInfo tries to LOG anything. 677 // happen if the call to LogDebugInfo tries to LOG anything.
678 // Since it is read on the plugin thread, we don't need to lock to set it.
678 g_logging_to_plugin = true; 679 g_logging_to_plugin = true;
679 ChromotingScriptableObject* scriptable_object = GetScriptableObject(); 680 ChromotingScriptableObject* scriptable_object = GetScriptableObject();
680 if (scriptable_object) { 681 if (scriptable_object) {
681 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); 682 scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
682 data->SetString("message", message); 683 data->SetString("message", message);
683 PostChromotingMessage("logDebugMessage", data.Pass()); 684 PostChromotingMessage("logDebugMessage", data.Pass());
684 685
685 scriptable_object->LogDebugInfo(message); 686 scriptable_object->LogDebugInfo(message);
686 } 687 }
687 g_logging_to_plugin = false; 688 g_logging_to_plugin = false;
688 } 689 }
689 690
690 bool ChromotingInstance::IsConnected() { 691 bool ChromotingInstance::IsConnected() {
691 return host_connection_.get() && 692 return host_connection_.get() &&
692 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED); 693 (host_connection_->state() == protocol::ConnectionToHost::CONNECTED);
693 } 694 }
694 695
695 } // namespace remoting 696 } // 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