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

Unified Diff: components/update_client/updater_state_mac.mm

Issue 2862723002: Add updater state for Mac. (Closed)
Patch Set: Scoped pointers for NSObject instances; removed a memory leak when reading different type. Created 3 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
« no previous file with comments | « components/update_client/updater_state.cc ('k') | components/update_client/updater_state_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/update_client/updater_state_mac.mm
diff --git a/components/update_client/updater_state_mac.mm b/components/update_client/updater_state_mac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..d2656ceaa340f634c038066c1ffeec90364db3c0
--- /dev/null
+++ b/components/update_client/updater_state_mac.mm
@@ -0,0 +1,186 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+#import <OpenDirectory/OpenDirectory.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/version.h"
+#include "components/update_client/updater_state.h"
+
+namespace update_client {
+
+namespace {
+
+const base::FilePath::CharType kKeystonePlist[] = FILE_PATH_LITERAL(
+ "Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/"
+ "Contents/Info.plist");
+
+// Gets a value from the updater settings. Returns a retained object.
+// T should be a toll-free Foundation framework type. See Apple's
+// documentation for toll-free bridging.
+template<class T>
+base::scoped_nsobject<T> GetUpdaterSettingsValue(NSString* value_name) {
+ CFStringRef app_id = CFSTR("com.google.Keystone.Agent");
+ CFPropertyListRef plist =
Robert Sesek 2017/05/08 17:14:13 Switch this to a base::ScopedCFTypeRef and then yo
Boris Vidolov 2017/05/08 18:18:07 Thanks, Robert. One more scoped pointer type that
+ CFPreferencesCopyAppValue(base::mac::NSToCFCast(value_name), app_id);
+ if (!plist) return base::scoped_nsobject<T>(nil);
+ T* value = base::mac::ObjCCastStrict<T>(static_cast<id>(plist));
+ if (!value) {
+ // Some other type, do not leak:
+ CFRelease(value);
+ return base::scoped_nsobject<T>(nil);
+ }
+ return base::scoped_nsobject<T>(value);
+}
+
+base::Time GetUpdaterSettingsTime(NSString* value_name) {
+ base::scoped_nsobject<NSDate> date =
+ GetUpdaterSettingsValue<NSDate>(value_name);
+ base::Time result =
+ base::Time::FromCFAbsoluteTime([date timeIntervalSinceReferenceDate]);
+
+ return result;
+}
+
+base::Version GetVersionFromPlist(const base::FilePath& info_plist) {
+ base::mac::ScopedNSAutoreleasePool scoped_pool;
+ NSData* data =
+ [NSData dataWithContentsOfFile:
+ base::mac::FilePathToNSString(info_plist)];
+ if ([data length] == 0) {
+ return base::Version();
+ }
+ NSDictionary* all_keys = base::mac::ObjCCastStrict<NSDictionary>(
+ [NSPropertyListSerialization propertyListWithData:data
+ options:NSPropertyListImmutable
+ format:nil
+ error:nil]);
+ if (all_keys == nil) {
+ return base::Version();
+ }
+ CFStringRef version =
+ base::mac::GetValueFromDictionary<CFStringRef>(
+ base::mac::NSToCFCast(all_keys),
+ kCFBundleVersionKey);
+ if (version == NULL) {
+ return base::Version();
+ }
+ return base::Version(base::SysCFStringRefToUTF8(version));
+}
+
+} // namespace
+
+std::string UpdaterState::GetUpdaterName() {
+ return std::string("Keystone");
+}
+
+base::Version UpdaterState::GetUpdaterVersion(bool /*is_machine*/) {
+ // System Keystone trumps user one, so check this one first
+ base::FilePath local_library;
+ bool success = base::mac::GetLocalDirectory(NSLibraryDirectory,
+ &local_library);
+ DCHECK(success);
+ base::FilePath system_bundle_plist = local_library.Append(kKeystonePlist);
+ base::Version system_keystone = GetVersionFromPlist(system_bundle_plist);
+ if (system_keystone.IsValid()) {
+ return system_keystone;
+ }
+
+ base::FilePath user_bundle_plist =
+ base::mac::GetUserLibraryPath().Append(kKeystonePlist);
+ return GetVersionFromPlist(user_bundle_plist);
+}
+
+base::Time UpdaterState::GetUpdaterLastStartedAU(bool /*is_machine*/) {
+ return GetUpdaterSettingsTime(@"lastCheckStartDate");
+}
+
+base::Time UpdaterState::GetUpdaterLastChecked(bool /*is_machine*/) {
+ return GetUpdaterSettingsTime(@"lastServerCheckDate");
+}
+
+bool UpdaterState::IsAutoupdateCheckEnabled() {
+ // Auto-update check period override (in seconds).
+ // Applies only to older versions of Keystone.
+ base::scoped_nsobject<NSNumber> timeInterval =
+ GetUpdaterSettingsValue<NSNumber>(@"checkInterval");
+ if (!timeInterval.get()) return true;
+ int value = [timeInterval intValue];
+
+ return 0 < value && value < (24 * 60 * 60);
+}
+
+int UpdaterState::GetUpdatePolicy() {
+ return -1; // Keystone does not support update policies.
+}
+
+bool UpdaterState::IsJoinedToDomain() {
+ base::mac::ScopedNSAutoreleasePool scoped_pool;
+
+ ODSession* session = [ODSession defaultSession];
+ if (session == nil) {
+ DLOG(WARNING) << "ODSession defult session is nil.";
+ return false;
+ }
+
+ NSError* error = nil;
+ ODNode* node = [ODNode nodeWithSession:session
+ type:kODNodeTypeAuthentication
+ error:&error];
+ if (node == nil) {
+ DLOG(WARNING) << "ODSession cannot obtain the authentication node: "
+ << base::mac::NSToCFCast(error);
+ return false;
+ }
+
+ ODQuery* query = [ODQuery queryWithNode:node
+ forRecordTypes:kODRecordTypeUsers
+ attribute:kODAttributeTypeRecordName
+ matchType:kODMatchEqualTo
+ queryValues:NSUserName()
+ returnAttributes:kODAttributeTypeAllAttributes
+ maximumResults:0
+ error:&error];
+ if (query == nil) {
+ DLOG(WARNING) << "ODSession cannot create user query: "
+ << base::mac::NSToCFCast(error);
+ return false;
+ }
+
+ NSArray* results = [query resultsAllowingPartial:NO error:&error];
+ if (!results) {
+ DLOG(WARNING) << "ODSession cannot obtain current user node: "
+ << base::mac::NSToCFCast(error);
+ return false;
+ }
+ if (results.count != 1) {
+ DLOG(WARNING) << @"ODSession unexpected number of nodes: "
+ << results.count;
+ }
+ for (id element in results) {
+ ODRecord* record = base::mac::ObjCCastStrict<ODRecord>(element);
+ NSArray* attributes =
+ [record valuesForAttribute:kODAttributeTypeMetaRecordName
+ error:NULL];
+ for (id attribute in attributes) {
+ NSString* attribute_value =
+ base::mac::ObjCCastStrict<NSString>(attribute);
+ // Example: "uid=johnsmith,ou=People,dc=chromium,dc=org
+ NSRange dc = [attribute_value rangeOfString:@"(^|,)\\s*dc="
+ options:NSRegularExpressionSearch];
+ if (dc.length > 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace update_client
« no previous file with comments | « components/update_client/updater_state.cc ('k') | components/update_client/updater_state_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698