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

Unified Diff: remoting/host/plugin/daemon_controller_mac.cc

Issue 10386128: Use distributed notifications instead of polling to determine success/failure of the preference pan… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove observer in dtor. 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 side-by-side diff with in-line comments
Download patch
Index: remoting/host/plugin/daemon_controller_mac.cc
diff --git a/remoting/host/plugin/daemon_controller_mac.cc b/remoting/host/plugin/daemon_controller_mac.cc
index f05bcdc9a74216f154ab552d2b4080f668a09ad9..acb43613a35428e698d19b815bd7442ba120c00c 100644
--- a/remoting/host/plugin/daemon_controller_mac.cc
+++ b/remoting/host/plugin/daemon_controller_mac.cc
@@ -37,6 +37,8 @@ const int NSLibraryDirectory = 5;
// The name of the Remoting Host service that is registered with launchd.
#define kServiceName "org.chromium.chromoting"
+
+#define kUpdateCompleteNotificationName kServiceName ".update_complete"
#define kConfigDir "/Library/PrivilegedHelperTools/"
// This helper script is used to get the installed host version.
@@ -48,9 +50,6 @@ const char kHostHelperScript[] = kConfigDir kServiceName ".me2me.sh";
// knowledge of which keys belong in which files.
const char kHostConfigFile[] = kConfigDir kServiceName ".json";
-const int kPrefPaneWaitRetryLimit = 60;
-const int kPrefPaneWaitTimeout = 1000;
-
class DaemonControllerMac : public remoting::DaemonController {
public:
DaemonControllerMac();
@@ -75,13 +74,22 @@ class DaemonControllerMac : public remoting::DaemonController {
void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback);
void DoStop(const CompletionCallback& done_callback);
- void NotifyOnState(DaemonController::State state,
- const CompletionCallback& done_callback,
- int tries_remaining,
- const base::TimeDelta& sleep);
- bool ShowPreferencePane(const std::string& config_data);
+
+ void ShowPreferencePane(const std::string& config_data,
+ const CompletionCallback& done_callback);
+ void RegisterForPreferencePaneNotifications(
+ const CompletionCallback &done_callback);
+ void PreferencePaneCallbackDelegate(CFStringRef name,
+ CFDictionaryRef user_info);
+ static bool DoShowPreferencePane(const std::string& config_data);
+ static void PreferencePaneCallback(CFNotificationCenterRef center,
+ void* observer,
+ CFStringRef name,
+ const void* object,
+ CFDictionaryRef user_info);
base::Thread auth_thread_;
+ CompletionCallback current_callback_;
DISALLOW_COPY_AND_ASSIGN(DaemonControllerMac);
};
@@ -93,6 +101,11 @@ DaemonControllerMac::DaemonControllerMac()
DaemonControllerMac::~DaemonControllerMac() {
auth_thread_.Stop();
+ CFNotificationCenterRemoveObserver(
+ CFNotificationCenterGetDistributedCenter(),
+ this,
+ CFSTR(kUpdateCompleteNotificationName),
+ NULL);
}
DaemonController::State DaemonControllerMac::GetState() {
@@ -196,18 +209,7 @@ void DaemonControllerMac::DoSetConfigAndStart(
const CompletionCallback& done_callback) {
std::string config_data;
base::JSONWriter::Write(config.get(), &config_data);
-
- bool result = ShowPreferencePane(config_data);
-
- if (!result) {
- done_callback.Run(RESULT_FAILED);
- }
-
- // TODO(jamiewalch): Replace this with something a bit more robust
- NotifyOnState(DaemonController::STATE_STARTED,
- done_callback,
- kPrefPaneWaitRetryLimit,
- base::TimeDelta::FromMilliseconds(kPrefPaneWaitTimeout));
+ ShowPreferencePane(config_data, done_callback);
}
void DaemonControllerMac::DoUpdateConfig(
@@ -231,12 +233,19 @@ void DaemonControllerMac::DoUpdateConfig(
}
std::string config_data = config_file.GetSerializedData();
- bool success = ShowPreferencePane(config_data);
+ ShowPreferencePane(config_data, done_callback);
+}
- done_callback.Run(success ? RESULT_OK : RESULT_FAILED);
+void DaemonControllerMac::ShowPreferencePane(
+ const std::string& config_data, const CompletionCallback& done_callback) {
+ if (DoShowPreferencePane(config_data)) {
+ RegisterForPreferencePaneNotifications(done_callback);
+ } else {
+ done_callback.Run(RESULT_FAILED);
+ }
}
-bool DaemonControllerMac::ShowPreferencePane(const std::string& config_data) {
+bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) {
if (!config_data.empty()) {
FilePath config_path;
if (!file_util::GetTempDir(&config_path)) {
@@ -284,37 +293,67 @@ bool DaemonControllerMac::ShowPreferencePane(const std::string& config_data) {
}
void DaemonControllerMac::DoStop(const CompletionCallback& done_callback) {
- if (!ShowPreferencePane("")) {
- done_callback.Run(RESULT_FAILED);
+ ShowPreferencePane("", done_callback);
+}
+
+// CFNotificationCenterAddObserver ties the thread on which distributed
+// notifications are received to the one on which it is first called.
+// This is safe because HostNPScriptObject::InvokeAsyncResultCallback
+// bounces the invocation to the correct thread, so it doesn't matter
+// which thread CompletionCallbacks are called on.
+void DaemonControllerMac::RegisterForPreferencePaneNotifications(
+ const CompletionCallback& done_callback) {
+ // We can only have one callback registered at a time. This is enforced by the
+ // UX flow of the web-app.
+ DCHECK(current_callback_.is_null());
Lambros 2012/05/15 18:55:35 DCHECK seems too strong. Maybe the user could hit
Jamie 2012/05/15 20:53:50 I think DCHECK is correct. If the user refreshes t
+ current_callback_ = done_callback;
+
+ CFNotificationCenterAddObserver(
+ CFNotificationCenterGetDistributedCenter(),
+ this,
+ &DaemonControllerMac::PreferencePaneCallback,
+ CFSTR(kUpdateCompleteNotificationName),
+ NULL,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+}
+
+void DaemonControllerMac::PreferencePaneCallbackDelegate(
+ CFStringRef name,
+ CFDictionaryRef result_dictionary) {
+ if (CFStringCompare(name, CFSTR(kUpdateCompleteNotificationName), 0) !=
+ kCFCompareEqualTo) {
+ LOG(WARNING) << "Ignoring unexpected notification: " << name;
return;
}
-
- // TODO(jamiewalch): Replace this with something a bit more robust
- NotifyOnState(DaemonController::STATE_STOPPED,
- done_callback,
- kPrefPaneWaitRetryLimit,
- base::TimeDelta::FromMilliseconds(kPrefPaneWaitTimeout));
+ AsyncResult result = RESULT_FAILED;
+ CFStringRef result_string =
+ base::mac::GetValueFromDictionary<CFStringRef>(result_dictionary,
+ CFSTR("result"));
+ if (CFStringCompare(result_string, CFSTR("OK"), 0) == kCFCompareEqualTo) {
+ result = RESULT_OK;
+ } else if (CFStringCompare(result_string,
+ CFSTR("CANCEL"), 0) == kCFCompareEqualTo) {
+ result = RESULT_CANCELLED;
+ }
+ current_callback_.Run(result);
Lambros 2012/05/15 18:55:35 DCHECK current_callback_ ?
Jamie 2012/05/15 20:53:50 Done.
+ current_callback_.Reset();
+ CFNotificationCenterRemoveObserver(
+ CFNotificationCenterGetDistributedCenter(),
+ this,
+ CFSTR(kUpdateCompleteNotificationName),
+ NULL);
}
-void DaemonControllerMac::NotifyOnState(
- DaemonController::State state,
- const CompletionCallback& done_callback,
- int tries_remaining,
- const base::TimeDelta& sleep) {
- if (GetState() == state) {
- done_callback.Run(RESULT_OK);
- } else if (tries_remaining == 0) {
- done_callback.Run(RESULT_FAILED);
+void DaemonControllerMac::PreferencePaneCallback(CFNotificationCenterRef center,
+ void* observer,
+ CFStringRef name,
+ const void* object,
+ CFDictionaryRef user_info) {
+ DaemonControllerMac* self = reinterpret_cast<DaemonControllerMac*>(observer);
+ if (self) {
+ self->PreferencePaneCallbackDelegate(name, user_info);
} else {
- auth_thread_.message_loop_proxy()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DaemonControllerMac::NotifyOnState,
- base::Unretained(this),
- state,
- done_callback,
- tries_remaining - 1,
- sleep),
- sleep);
+ LOG(WARNING) << "Ignoring notification with NULL observer: " << name;
}
}
« remoting/host/me2me_preference_pane.mm ('K') | « remoting/host/me2me_preference_pane.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698