diff options
author | Hidehiko Abe <hidehiko@google.com> | 2018-02-13 13:48:01 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-02-13 13:48:01 +0000 |
commit | 777fba1ec208c9ec9725a18b9067652e3d3eac35 (patch) | |
tree | ca6c9dbf6bd7520a57b311141490d6bffa3da904 | |
parent | 52b745c8b04810c69091150d9843627452e20abf (diff) | |
parent | cac76aa5bcdfb401945ec4398a093b017126a6a4 (diff) | |
download | libchrome-777fba1ec208c9ec9725a18b9067652e3d3eac35.tar.gz |
Clean up Mac related files. am: 24af70ee32
am: cac76aa5bc
Change-Id: Ib412f5ed787e7b9f5343a621c8e06e1dc4d040fe
60 files changed, 11 insertions, 8887 deletions
diff --git a/Android.bp b/Android.bp index b89574bf4c..bf4809e30e 100644 --- a/Android.bp +++ b/Android.bp @@ -276,34 +276,15 @@ libchromeLinuxSrc = [ "components/timers/alarm_timer_chromeos.cc", ] -libchromeMacSrc = [ - "base/files/file_path_watcher_fsevents.cc", - "base/files/file_path_watcher_kqueue.cc", - "base/files/file_path_watcher_mac.cc", - "base/files/file_util_mac.mm", - "base/mac/bundle_locations.mm", - "base/mac/call_with_eh_frame.cc", - "base/mac/foundation_util.mm", - "base/mac/mach_logging.cc", - "base/mac/scoped_mach_port.cc", - "base/mac/scoped_mach_vm.cc", - "base/mac/scoped_nsautorelease_pool.mm", - "base/mac/sdk_forward_declarations.mm", - "base/memory/shared_memory_mac.cc", - "base/memory/shared_memory_handle_mac.cc", - "base/message_loop/message_pump_mac.mm", - "base/process/launch_mac.cc", - "base/process/port_provider_mac.cc", - "base/process/process_handle_mac.cc", - "base/process/process_info_mac.cc", - "base/process/process_iterator_mac.cc", - "base/process/process_metrics_mac.cc", - "base/strings/sys_string_conversions_mac.mm", - "base/sys_info_mac.mm", - "base/time/time_mac.cc", - "base/threading/platform_thread_mac.mm", +libchromeLinuxGlibcSrc = [ + "base/allocator/allocator_shim.cc", + "base/allocator/allocator_shim_default_dispatch_to_glibc.cc" ] +libchromeAndroidSrc = [ + "base/memory/shared_memory_android.cc", + "base/sys_info_chromeos.cc", +] // libchrome static+shared for host and device // ======================================================== @@ -328,25 +309,16 @@ cc_library { linux: { srcs: libchromeLinuxSrc, }, + linux_glibc: { + srcs: libchromeLinuxGlibcSrc, + }, android: { - srcs: [ - "base/memory/shared_memory_android.cc", - "base/sys_info_chromeos.cc", - ], + srcs: libchromeAndroidSrc, shared_libs: [ "liblog", "libcutils", ], }, - linux_glibc: { - srcs: [ - "base/allocator/allocator_shim.cc", - "base/allocator/allocator_shim_default_dispatch_to_glibc.cc" - ], - }, - darwin: { - srcs: libchromeMacSrc, - }, }, } @@ -388,11 +360,6 @@ cc_library_static { "base/test/test_switches.cc", "base/test/test_timeouts.cc", ], - target: { - darwin: { - enabled: false, - }, - }, } // Helpers needed for unit tests (for host). @@ -403,11 +370,6 @@ cc_library_host_static { shared_libs: ["libchrome"], srcs: ["base/test/simple_test_clock.cc"], - target: { - darwin: { - enabled: false, - }, - }, } // Host and target unit tests. Run (from repo root) with: @@ -594,8 +556,5 @@ cc_test { ], cflags: ["-DDONT_EMBED_BUILD_METADATA"], }, - darwin: { - enabled: false, - }, }, } diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc deleted file mode 100644 index e9a87b0e05..0000000000 --- a/base/files/file_path_watcher_fsevents.cc +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2014 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. - -#include "base/files/file_path_watcher_fsevents.h" - -#include <dispatch/dispatch.h> - -#include <list> - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/strings/stringprintf.h" -#include "base/threading/sequenced_task_runner_handle.h" - -namespace base { - -namespace { - -// The latency parameter passed to FSEventsStreamCreate(). -const CFAbsoluteTime kEventLatencySeconds = 0.3; - -// Resolve any symlinks in the path. -FilePath ResolvePath(const FilePath& path) { - const unsigned kMaxLinksToResolve = 255; - - std::vector<FilePath::StringType> component_vector; - path.GetComponents(&component_vector); - std::list<FilePath::StringType> - components(component_vector.begin(), component_vector.end()); - - FilePath result; - unsigned resolve_count = 0; - while (resolve_count < kMaxLinksToResolve && !components.empty()) { - FilePath component(*components.begin()); - components.pop_front(); - - FilePath current; - if (component.IsAbsolute()) { - current = component; - } else { - current = result.Append(component); - } - - FilePath target; - if (ReadSymbolicLink(current, &target)) { - if (target.IsAbsolute()) - result.clear(); - std::vector<FilePath::StringType> target_components; - target.GetComponents(&target_components); - components.insert(components.begin(), target_components.begin(), - target_components.end()); - resolve_count++; - } else { - result = current; - } - } - - if (resolve_count >= kMaxLinksToResolve) - result.clear(); - return result; -} - -} // namespace - -FilePathWatcherFSEvents::FilePathWatcherFSEvents() - : queue_(dispatch_queue_create( - base::StringPrintf("org.chromium.base.FilePathWatcher.%p", this) - .c_str(), - DISPATCH_QUEUE_SERIAL)), - fsevent_stream_(nullptr), - weak_factory_(this) {} - -FilePathWatcherFSEvents::~FilePathWatcherFSEvents() { - DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread()); - DCHECK(callback_.is_null()) - << "Cancel() must be called before FilePathWatcher is destroyed."; -} - -bool FilePathWatcherFSEvents::Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) { - DCHECK(!callback.is_null()); - DCHECK(callback_.is_null()); - - // This class could support non-recursive watches, but that is currently - // left to FilePathWatcherKQueue. - if (!recursive) - return false; - - set_task_runner(SequencedTaskRunnerHandle::Get()); - callback_ = callback; - - FSEventStreamEventId start_event = FSEventsGetCurrentEventId(); - // The block runtime would implicitly capture the reference, not the object - // it's referencing. Copy the path into a local, so that the value is - // captured by the block's scope. - const FilePath path_copy(path); - - dispatch_async(queue_, ^{ - StartEventStream(start_event, path_copy); - }); - return true; -} - -void FilePathWatcherFSEvents::Cancel() { - set_cancelled(); - callback_.Reset(); - - // Switch to the dispatch queue to tear down the event stream. As the queue is - // owned by |this|, and this method is called from the destructor, execute the - // block synchronously. - dispatch_sync(queue_, ^{ - if (fsevent_stream_) { - DestroyEventStream(); - target_.clear(); - resolved_target_.clear(); - } - }); -} - -// static -void FilePathWatcherFSEvents::FSEventsCallback( - ConstFSEventStreamRef stream, - void* event_watcher, - size_t num_events, - void* event_paths, - const FSEventStreamEventFlags flags[], - const FSEventStreamEventId event_ids[]) { - FilePathWatcherFSEvents* watcher = - reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher); - bool root_changed = watcher->ResolveTargetPath(); - std::vector<FilePath> paths; - FSEventStreamEventId root_change_at = FSEventStreamGetLatestEventId(stream); - for (size_t i = 0; i < num_events; i++) { - if (flags[i] & kFSEventStreamEventFlagRootChanged) - root_changed = true; - if (event_ids[i]) - root_change_at = std::min(root_change_at, event_ids[i]); - paths.push_back(FilePath( - reinterpret_cast<char**>(event_paths)[i]).StripTrailingSeparators()); - } - - // Reinitialize the event stream if we find changes to the root. This is - // necessary since FSEvents doesn't report any events for the subtree after - // the directory to be watched gets created. - if (root_changed) { - // Resetting the event stream from within the callback fails (FSEvents spews - // bad file descriptor errors), so do the reset asynchronously. - // - // We can't dispatch_async a call to UpdateEventStream() directly because - // there would be no guarantee that |watcher| still exists when it runs. - // - // Instead, bounce on task_runner() and use a WeakPtr to verify that - // |watcher| still exists. If it does, dispatch_async a call to - // UpdateEventStream(). Because the destructor of |watcher| runs on - // task_runner() and calls dispatch_sync, it is guaranteed that |watcher| - // still exists when UpdateEventStream() runs. - watcher->task_runner()->PostTask( - FROM_HERE, Bind( - [](WeakPtr<FilePathWatcherFSEvents> weak_watcher, - FSEventStreamEventId root_change_at) { - if (!weak_watcher) - return; - FilePathWatcherFSEvents* watcher = weak_watcher.get(); - dispatch_async(watcher->queue_, ^{ - watcher->UpdateEventStream(root_change_at); - }); - }, - watcher->weak_factory_.GetWeakPtr(), root_change_at)); - } - - watcher->OnFilePathsChanged(paths); -} - -void FilePathWatcherFSEvents::OnFilePathsChanged( - const std::vector<FilePath>& paths) { - DCHECK(!resolved_target_.empty()); - task_runner()->PostTask( - FROM_HERE, - Bind(&FilePathWatcherFSEvents::DispatchEvents, weak_factory_.GetWeakPtr(), - paths, target_, resolved_target_)); -} - -void FilePathWatcherFSEvents::DispatchEvents(const std::vector<FilePath>& paths, - const FilePath& target, - const FilePath& resolved_target) { - DCHECK(task_runner()->RunsTasksOnCurrentThread()); - - // Don't issue callbacks after Cancel() has been called. - if (is_cancelled() || callback_.is_null()) { - return; - } - - for (const FilePath& path : paths) { - if (resolved_target.IsParent(path) || resolved_target == path) { - callback_.Run(target, false); - return; - } - } -} - -void FilePathWatcherFSEvents::UpdateEventStream( - FSEventStreamEventId start_event) { - // It can happen that the watcher gets canceled while tasks that call this - // function are still in flight, so abort if this situation is detected. - if (resolved_target_.empty()) - return; - - if (fsevent_stream_) - DestroyEventStream(); - - ScopedCFTypeRef<CFStringRef> cf_path(CFStringCreateWithCString( - NULL, resolved_target_.value().c_str(), kCFStringEncodingMacHFS)); - ScopedCFTypeRef<CFStringRef> cf_dir_path(CFStringCreateWithCString( - NULL, resolved_target_.DirName().value().c_str(), - kCFStringEncodingMacHFS)); - CFStringRef paths_array[] = { cf_path.get(), cf_dir_path.get() }; - ScopedCFTypeRef<CFArrayRef> watched_paths(CFArrayCreate( - NULL, reinterpret_cast<const void**>(paths_array), arraysize(paths_array), - &kCFTypeArrayCallBacks)); - - FSEventStreamContext context; - context.version = 0; - context.info = this; - context.retain = NULL; - context.release = NULL; - context.copyDescription = NULL; - - fsevent_stream_ = FSEventStreamCreate(NULL, &FSEventsCallback, &context, - watched_paths, - start_event, - kEventLatencySeconds, - kFSEventStreamCreateFlagWatchRoot); - FSEventStreamSetDispatchQueue(fsevent_stream_, queue_); - - if (!FSEventStreamStart(fsevent_stream_)) { - task_runner()->PostTask(FROM_HERE, - Bind(&FilePathWatcherFSEvents::ReportError, - weak_factory_.GetWeakPtr(), target_)); - } -} - -bool FilePathWatcherFSEvents::ResolveTargetPath() { - FilePath resolved = ResolvePath(target_).StripTrailingSeparators(); - bool changed = resolved != resolved_target_; - resolved_target_ = resolved; - if (resolved_target_.empty()) { - task_runner()->PostTask(FROM_HERE, - Bind(&FilePathWatcherFSEvents::ReportError, - weak_factory_.GetWeakPtr(), target_)); - } - return changed; -} - -void FilePathWatcherFSEvents::ReportError(const FilePath& target) { - DCHECK(task_runner()->RunsTasksOnCurrentThread()); - if (!callback_.is_null()) { - callback_.Run(target, true); - } -} - -void FilePathWatcherFSEvents::DestroyEventStream() { - FSEventStreamStop(fsevent_stream_); - FSEventStreamInvalidate(fsevent_stream_); - FSEventStreamRelease(fsevent_stream_); - fsevent_stream_ = NULL; -} - -void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event, - const FilePath& path) { - DCHECK(resolved_target_.empty()); - - target_ = path; - ResolveTargetPath(); - UpdateEventStream(start_event); -} - -} // namespace base diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h deleted file mode 100644 index dcdf2fbf9d..0000000000 --- a/base/files/file_path_watcher_fsevents.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 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. - -#ifndef BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_ -#define BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_ - -#include <CoreServices/CoreServices.h> -#include <stddef.h> - -#include <vector> - -#include "base/files/file_path.h" -#include "base/files/file_path_watcher.h" -#include "base/mac/scoped_dispatch_object.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" - -namespace base { - -// Mac-specific file watcher implementation based on FSEvents. -// There are trade-offs between the FSEvents implementation and a kqueue -// implementation. The biggest issues are that FSEvents on 10.6 sometimes drops -// events and kqueue does not trigger for modifications to a file in a watched -// directory. See file_path_watcher_mac.cc for the code that decides when to -// use which one. -class FilePathWatcherFSEvents : public FilePathWatcher::PlatformDelegate { - public: - FilePathWatcherFSEvents(); - ~FilePathWatcherFSEvents() override; - - // FilePathWatcher::PlatformDelegate overrides. - bool Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) override; - void Cancel() override; - - private: - static void FSEventsCallback(ConstFSEventStreamRef stream, - void* event_watcher, - size_t num_events, - void* event_paths, - const FSEventStreamEventFlags flags[], - const FSEventStreamEventId event_ids[]); - - // Called from FSEventsCallback whenever there is a change to the paths. - void OnFilePathsChanged(const std::vector<FilePath>& paths); - - // Called on the message_loop() thread to dispatch path events. Can't access - // target_ and resolved_target_ directly as those are modified on the - // libdispatch thread. - void DispatchEvents(const std::vector<FilePath>& paths, - const FilePath& target, - const FilePath& resolved_target); - - // (Re-)Initialize the event stream to start reporting events from - // |start_event|. - void UpdateEventStream(FSEventStreamEventId start_event); - - // Returns true if resolving the target path got a different result than - // last time it was done. - bool ResolveTargetPath(); - - // Report an error watching the given target. - void ReportError(const FilePath& target); - - // Destroy the event stream. - void DestroyEventStream(); - - // Start watching the FSEventStream. - void StartEventStream(FSEventStreamEventId start_event, const FilePath& path); - - // Callback to notify upon changes. - // (Only accessed from the message_loop() thread.) - FilePathWatcher::Callback callback_; - - // The dispatch queue on which the the event stream is scheduled. - ScopedDispatchObject<dispatch_queue_t> queue_; - - // Target path to watch (passed to callback). - // (Only accessed from the libdispatch queue.) - FilePath target_; - - // Target path with all symbolic links resolved. - // (Only accessed from the libdispatch queue.) - FilePath resolved_target_; - - // Backend stream we receive event callbacks from (strong reference). - // (Only accessed from the libdispatch queue.) - FSEventStreamRef fsevent_stream_; - - WeakPtrFactory<FilePathWatcherFSEvents> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents); -}; - -} // namespace base - -#endif // BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_ diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc deleted file mode 100644 index a28726acb0..0000000000 --- a/base/files/file_path_watcher_kqueue.cc +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/files/file_path_watcher_kqueue.h" - -#include <fcntl.h> -#include <stddef.h> -#include <sys/param.h> - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/threading/sequenced_task_runner_handle.h" - -// On some platforms these are not defined. -#if !defined(EV_RECEIPT) -#define EV_RECEIPT 0 -#endif -#if !defined(O_EVTONLY) -#define O_EVTONLY O_RDONLY -#endif - -namespace base { - -FilePathWatcherKQueue::FilePathWatcherKQueue() : kqueue_(-1) {} - -FilePathWatcherKQueue::~FilePathWatcherKQueue() { - DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread()); -} - -void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) { - CloseFileDescriptor(&event.ident); - EventData* entry = EventDataForKevent(event); - delete entry; - event.udata = NULL; -} - -int FilePathWatcherKQueue::EventsForPath(FilePath path, EventVector* events) { - // Make sure that we are working with a clean slate. - DCHECK(events->empty()); - - std::vector<FilePath::StringType> components; - path.GetComponents(&components); - - if (components.size() < 1) { - return -1; - } - - int last_existing_entry = 0; - FilePath built_path; - bool path_still_exists = true; - for (std::vector<FilePath::StringType>::iterator i = components.begin(); - i != components.end(); ++i) { - if (i == components.begin()) { - built_path = FilePath(*i); - } else { - built_path = built_path.Append(*i); - } - uintptr_t fd = kNoFileDescriptor; - if (path_still_exists) { - fd = FileDescriptorForPath(built_path); - if (fd == kNoFileDescriptor) { - path_still_exists = false; - } else { - ++last_existing_entry; - } - } - FilePath::StringType subdir = (i != (components.end() - 1)) ? *(i + 1) : ""; - EventData* data = new EventData(built_path, subdir); - struct kevent event; - EV_SET(&event, fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR | EV_RECEIPT), - (NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB | - NOTE_RENAME | NOTE_REVOKE | NOTE_EXTEND), 0, data); - events->push_back(event); - } - return last_existing_entry; -} - -uintptr_t FilePathWatcherKQueue::FileDescriptorForPath(const FilePath& path) { - int fd = HANDLE_EINTR(open(path.value().c_str(), O_EVTONLY)); - if (fd == -1) - return kNoFileDescriptor; - return fd; -} - -void FilePathWatcherKQueue::CloseFileDescriptor(uintptr_t* fd) { - if (*fd == kNoFileDescriptor) { - return; - } - - if (IGNORE_EINTR(close(*fd)) != 0) { - DPLOG(ERROR) << "close"; - } - *fd = kNoFileDescriptor; -} - -bool FilePathWatcherKQueue::AreKeventValuesValid(struct kevent* kevents, - int count) { - if (count < 0) { - DPLOG(ERROR) << "kevent"; - return false; - } - bool valid = true; - for (int i = 0; i < count; ++i) { - if (kevents[i].flags & EV_ERROR && kevents[i].data) { - // Find the kevent in |events_| that matches the kevent with the error. - EventVector::iterator event = events_.begin(); - for (; event != events_.end(); ++event) { - if (event->ident == kevents[i].ident) { - break; - } - } - std::string path_name; - if (event != events_.end()) { - EventData* event_data = EventDataForKevent(*event); - if (event_data != NULL) { - path_name = event_data->path_.value(); - } - } - if (path_name.empty()) { - path_name = base::StringPrintf( - "fd %ld", reinterpret_cast<long>(&kevents[i].ident)); - } - DLOG(ERROR) << "Error: " << kevents[i].data << " for " << path_name; - valid = false; - } - } - return valid; -} - -void FilePathWatcherKQueue::HandleAttributesChange( - const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches) { - EventVector::iterator next_event = event + 1; - EventData* next_event_data = EventDataForKevent(*next_event); - // Check to see if the next item in path is still accessible. - uintptr_t have_access = FileDescriptorForPath(next_event_data->path_); - if (have_access == kNoFileDescriptor) { - *target_file_affected = true; - *update_watches = true; - EventVector::iterator local_event(event); - for (; local_event != events_.end(); ++local_event) { - // Close all nodes from the event down. This has the side effect of - // potentially rendering other events in |updates| invalid. - // There is no need to remove the events from |kqueue_| because this - // happens as a side effect of closing the file descriptor. - CloseFileDescriptor(&local_event->ident); - } - } else { - CloseFileDescriptor(&have_access); - } -} - -void FilePathWatcherKQueue::HandleDeleteOrMoveChange( - const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches) { - *target_file_affected = true; - *update_watches = true; - EventVector::iterator local_event(event); - for (; local_event != events_.end(); ++local_event) { - // Close all nodes from the event down. This has the side effect of - // potentially rendering other events in |updates| invalid. - // There is no need to remove the events from |kqueue_| because this - // happens as a side effect of closing the file descriptor. - CloseFileDescriptor(&local_event->ident); - } -} - -void FilePathWatcherKQueue::HandleCreateItemChange( - const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches) { - // Get the next item in the path. - EventVector::iterator next_event = event + 1; - // Check to see if it already has a valid file descriptor. - if (!IsKeventFileDescriptorOpen(*next_event)) { - EventData* next_event_data = EventDataForKevent(*next_event); - // If not, attempt to open a file descriptor for it. - next_event->ident = FileDescriptorForPath(next_event_data->path_); - if (IsKeventFileDescriptorOpen(*next_event)) { - *update_watches = true; - if (next_event_data->subdir_.empty()) { - *target_file_affected = true; - } - } - } -} - -bool FilePathWatcherKQueue::UpdateWatches(bool* target_file_affected) { - // Iterate over events adding kevents for items that exist to the kqueue. - // Then check to see if new components in the path have been created. - // Repeat until no new components in the path are detected. - // This is to get around races in directory creation in a watched path. - bool update_watches = true; - while (update_watches) { - size_t valid; - for (valid = 0; valid < events_.size(); ++valid) { - if (!IsKeventFileDescriptorOpen(events_[valid])) { - break; - } - } - if (valid == 0) { - // The root of the file path is inaccessible? - return false; - } - - EventVector updates(valid); - int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], valid, &updates[0], - valid, NULL)); - if (!AreKeventValuesValid(&updates[0], count)) { - return false; - } - update_watches = false; - for (; valid < events_.size(); ++valid) { - EventData* event_data = EventDataForKevent(events_[valid]); - events_[valid].ident = FileDescriptorForPath(event_data->path_); - if (IsKeventFileDescriptorOpen(events_[valid])) { - update_watches = true; - if (event_data->subdir_.empty()) { - *target_file_affected = true; - } - } else { - break; - } - } - } - return true; -} - -bool FilePathWatcherKQueue::Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) { - DCHECK(target_.value().empty()); // Can only watch one path. - DCHECK(!callback.is_null()); - DCHECK_EQ(kqueue_, -1); - // Recursive watch is not supported using kqueue. - DCHECK(!recursive); - - callback_ = callback; - target_ = path; - - set_task_runner(SequencedTaskRunnerHandle::Get()); - - kqueue_ = kqueue(); - if (kqueue_ == -1) { - DPLOG(ERROR) << "kqueue"; - return false; - } - - int last_entry = EventsForPath(target_, &events_); - DCHECK_NE(last_entry, 0); - - EventVector responses(last_entry); - - int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, - &responses[0], last_entry, NULL)); - if (!AreKeventValuesValid(&responses[0], count)) { - // Calling Cancel() here to close any file descriptors that were opened. - // This would happen in the destructor anyways, but FilePathWatchers tend to - // be long lived, and if an error has occurred, there is no reason to waste - // the file descriptors. - Cancel(); - return false; - } - - // It's safe to use Unretained() because the watch is cancelled and the - // callback cannot be invoked after |kqueue_watch_controller_| (which is a - // member of |this|) has been deleted. - kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable( - kqueue_, - Bind(&FilePathWatcherKQueue::OnKQueueReadable, Unretained(this))); - - return true; -} - -void FilePathWatcherKQueue::Cancel() { - if (!task_runner()) { - set_cancelled(); - return; - } - - DCHECK(task_runner()->RunsTasksOnCurrentThread()); - if (!is_cancelled()) { - set_cancelled(); - kqueue_watch_controller_.reset(); - if (IGNORE_EINTR(close(kqueue_)) != 0) { - DPLOG(ERROR) << "close kqueue"; - } - kqueue_ = -1; - std::for_each(events_.begin(), events_.end(), ReleaseEvent); - events_.clear(); - callback_.Reset(); - } -} - -void FilePathWatcherKQueue::OnKQueueReadable() { - DCHECK(task_runner()->RunsTasksOnCurrentThread()); - DCHECK(events_.size()); - - // Request the file system update notifications that have occurred and return - // them in |updates|. |count| will contain the number of updates that have - // occurred. - EventVector updates(events_.size()); - struct timespec timeout = {0, 0}; - int count = HANDLE_EINTR(kevent(kqueue_, NULL, 0, &updates[0], updates.size(), - &timeout)); - - // Error values are stored within updates, so check to make sure that no - // errors occurred. - if (!AreKeventValuesValid(&updates[0], count)) { - callback_.Run(target_, true /* error */); - Cancel(); - return; - } - - bool update_watches = false; - bool send_notification = false; - - // Iterate through each of the updates and react to them. - for (int i = 0; i < count; ++i) { - // Find our kevent record that matches the update notification. - EventVector::iterator event = events_.begin(); - for (; event != events_.end(); ++event) { - if (!IsKeventFileDescriptorOpen(*event) || - event->ident == updates[i].ident) { - break; - } - } - if (event == events_.end() || !IsKeventFileDescriptorOpen(*event)) { - // The event may no longer exist in |events_| because another event - // modified |events_| in such a way to make it invalid. For example if - // the path is /foo/bar/bam and foo is deleted, NOTE_DELETE events for - // foo, bar and bam will be sent. If foo is processed first, then - // the file descriptors for bar and bam will already be closed and set - // to -1 before they get a chance to be processed. - continue; - } - - EventData* event_data = EventDataForKevent(*event); - - // If the subdir is empty, this is the last item on the path and is the - // target file. - bool target_file_affected = event_data->subdir_.empty(); - if ((updates[i].fflags & NOTE_ATTRIB) && !target_file_affected) { - HandleAttributesChange(event, &target_file_affected, &update_watches); - } - if (updates[i].fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) { - HandleDeleteOrMoveChange(event, &target_file_affected, &update_watches); - } - if ((updates[i].fflags & NOTE_WRITE) && !target_file_affected) { - HandleCreateItemChange(event, &target_file_affected, &update_watches); - } - send_notification |= target_file_affected; - } - - if (update_watches) { - if (!UpdateWatches(&send_notification)) { - callback_.Run(target_, true /* error */); - Cancel(); - } - } - - if (send_notification) { - callback_.Run(target_, false); - } -} - -} // namespace base diff --git a/base/files/file_path_watcher_kqueue.h b/base/files/file_path_watcher_kqueue.h deleted file mode 100644 index ef79be5596..0000000000 --- a/base/files/file_path_watcher_kqueue.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2014 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. - -#ifndef BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_ -#define BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_ - -#include <sys/event.h> - -#include <memory> -#include <vector> - -#include "base/files/file_descriptor_watcher_posix.h" -#include "base/files/file_path.h" -#include "base/files/file_path_watcher.h" -#include "base/macros.h" - -namespace base { - -// Mac-specific file watcher implementation based on kqueue. -// The Linux and Windows versions are able to detect: -// - file creation/deletion/modification in a watched directory -// - file creation/deletion/modification for a watched file -// - modifications to the paths to a watched object that would affect the -// object such as renaming/attibute changes etc. -// The kqueue implementation will handle all of the items in the list above -// except for detecting modifications to files in a watched directory. It will -// detect the creation and deletion of files, just not the modification of -// files. It does however detect the attribute changes that the FSEvents impl -// would miss. -class FilePathWatcherKQueue : public FilePathWatcher::PlatformDelegate { - public: - FilePathWatcherKQueue(); - ~FilePathWatcherKQueue() override; - - // FilePathWatcher::PlatformDelegate overrides. - bool Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) override; - void Cancel() override; - - private: - class EventData { - public: - EventData(const FilePath& path, const FilePath::StringType& subdir) - : path_(path), subdir_(subdir) { } - FilePath path_; // Full path to this item. - FilePath::StringType subdir_; // Path to any sub item. - }; - - typedef std::vector<struct kevent> EventVector; - - // Called when data is available in |kqueue_|. - void OnKQueueReadable(); - - // Returns true if the kevent values are error free. - bool AreKeventValuesValid(struct kevent* kevents, int count); - - // Respond to a change of attributes of the path component represented by - // |event|. Sets |target_file_affected| to true if |target_| is affected. - // Sets |update_watches| to true if |events_| need to be updated. - void HandleAttributesChange(const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches); - - // Respond to a move or deletion of the path component represented by - // |event|. Sets |target_file_affected| to true if |target_| is affected. - // Sets |update_watches| to true if |events_| need to be updated. - void HandleDeleteOrMoveChange(const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches); - - // Respond to a creation of an item in the path component represented by - // |event|. Sets |target_file_affected| to true if |target_| is affected. - // Sets |update_watches| to true if |events_| need to be updated. - void HandleCreateItemChange(const EventVector::iterator& event, - bool* target_file_affected, - bool* update_watches); - - // Update |events_| with the current status of the system. - // Sets |target_file_affected| to true if |target_| is affected. - // Returns false if an error occurs. - bool UpdateWatches(bool* target_file_affected); - - // Fills |events| with one kevent per component in |path|. - // Returns the number of valid events created where a valid event is - // defined as one that has a ident (file descriptor) field != -1. - static int EventsForPath(FilePath path, EventVector *events); - - // Release a kevent generated by EventsForPath. - static void ReleaseEvent(struct kevent& event); - - // Returns a file descriptor that will not block the system from deleting - // the file it references. - static uintptr_t FileDescriptorForPath(const FilePath& path); - - static const uintptr_t kNoFileDescriptor = static_cast<uintptr_t>(-1); - - // Closes |*fd| and sets |*fd| to -1. - static void CloseFileDescriptor(uintptr_t* fd); - - // Returns true if kevent has open file descriptor. - static bool IsKeventFileDescriptorOpen(const struct kevent& event) { - return event.ident != kNoFileDescriptor; - } - - static EventData* EventDataForKevent(const struct kevent& event) { - return reinterpret_cast<EventData*>(event.udata); - } - - EventVector events_; - FilePathWatcher::Callback callback_; - FilePath target_; - int kqueue_; - - // Throughout the lifetime of this, OnKQueueReadable() will be called when - // data is available in |kqueue_|. - std::unique_ptr<FileDescriptorWatcher::Controller> kqueue_watch_controller_; - - DISALLOW_COPY_AND_ASSIGN(FilePathWatcherKQueue); -}; - -} // namespace base - -#endif // BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_ diff --git a/base/files/file_path_watcher_mac.cc b/base/files/file_path_watcher_mac.cc deleted file mode 100644 index 2520b9288a..0000000000 --- a/base/files/file_path_watcher_mac.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 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. - -#include <memory> - -#include "base/files/file_path_watcher.h" -#include "base/files/file_path_watcher_kqueue.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "build/build_config.h" - -#if !defined(OS_IOS) -#include "base/files/file_path_watcher_fsevents.h" -#endif - -namespace base { - -namespace { - -class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { - public: - FilePathWatcherImpl() = default; - ~FilePathWatcherImpl() override = default; - - bool Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) override { - // Use kqueue for non-recursive watches and FSEvents for recursive ones. - DCHECK(!impl_.get()); - if (recursive) { - if (!FilePathWatcher::RecursiveWatchAvailable()) - return false; -#if !defined(OS_IOS) - impl_ = MakeUnique<FilePathWatcherFSEvents>(); -#endif // OS_IOS - } else { - impl_ = MakeUnique<FilePathWatcherKQueue>(); - } - DCHECK(impl_.get()); - return impl_->Watch(path, recursive, callback); - } - - void Cancel() override { - if (impl_.get()) - impl_->Cancel(); - set_cancelled(); - } - - private: - std::unique_ptr<PlatformDelegate> impl_; - - DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); -}; - -} // namespace - -FilePathWatcher::FilePathWatcher() { - sequence_checker_.DetachFromSequence(); - impl_ = MakeUnique<FilePathWatcherImpl>(); -} - -} // namespace base diff --git a/base/files/file_util_mac.mm b/base/files/file_util_mac.mm deleted file mode 100644 index 5a99aa0e81..0000000000 --- a/base/files/file_util_mac.mm +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/files/file_util.h" - -#import <Foundation/Foundation.h> -#include <copyfile.h> -#include <stdlib.h> - -#include "base/files/file_path.h" -#include "base/mac/foundation_util.h" -#include "base/strings/string_util.h" -#include "base/threading/thread_restrictions.h" - -namespace base { - -bool CopyFile(const FilePath& from_path, const FilePath& to_path) { - ThreadRestrictions::AssertIOAllowed(); - if (from_path.ReferencesParent() || to_path.ReferencesParent()) - return false; - return (copyfile(from_path.value().c_str(), - to_path.value().c_str(), NULL, COPYFILE_DATA) == 0); -} - -bool GetTempDir(base::FilePath* path) { - // In order to facilitate hermetic runs on macOS, first check $TMPDIR. - // NOTE: $TMPDIR is ALMOST ALWAYS set on macOS (unless the user un-set it). - const char* env_tmpdir = getenv("TMPDIR"); - if (env_tmpdir) { - *path = base::FilePath(env_tmpdir); - return true; - } - - // If we didn't find it, fall back to the native function. - NSString* tmp = NSTemporaryDirectory(); - if (tmp == nil) - return false; - *path = base::mac::NSStringToFilePath(tmp); - return true; -} - -FilePath GetHomeDir() { - NSString* tmp = NSHomeDirectory(); - if (tmp != nil) { - FilePath mac_home_dir = base::mac::NSStringToFilePath(tmp); - if (!mac_home_dir.empty()) - return mac_home_dir; - } - - // Fall back on temp dir if no home directory is defined. - FilePath rv; - if (GetTempDir(&rv)) - return rv; - - // Last resort. - return FilePath("/tmp"); -} - -} // namespace base diff --git a/base/mac/bind_objc_block.h b/base/mac/bind_objc_block.h deleted file mode 100644 index 9a481ed987..0000000000 --- a/base/mac/bind_objc_block.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_BIND_OBJC_BLOCK_H_ -#define BASE_MAC_BIND_OBJC_BLOCK_H_ - -#include <Block.h> - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/compiler_specific.h" -#include "base/mac/scoped_block.h" - -// BindBlock builds a callback from an Objective-C block. Example usages: -// -// Closure closure = BindBlock(^{DoSomething();}); -// -// Callback<int(void)> callback = BindBlock(^{return 42;}); -// -// Callback<void(const std::string&, const std::string&)> callback = -// BindBlock(^(const std::string& arg0, const std::string& arg1) { -// ... -// }); -// -// These variadic templates will accommodate any number of arguments, however -// the underlying templates in bind_internal.h and callback.h are limited to -// seven total arguments, and the bound block itself is used as one of these -// arguments, so functionally the templates are limited to binding blocks with -// zero through six arguments. -// -// For code compiled with ARC (automatic reference counting), use BindBlockArc. -// This is because the method has a different implementation (to avoid over- -// retaining the block) and need to have a different name not to break the ODR -// (one definition rule). Another subtle difference is that the implementation -// will call a different version of ScopedBlock constructor thus the linker must -// not merge both functions. - -namespace base { - -namespace internal { - -// Helper function to run the block contained in the parameter. -template<typename R, typename... Args> -R RunBlock(base::mac::ScopedBlock<R(^)(Args...)> block, Args... args) { - R(^extracted_block)(Args...) = block.get(); - return extracted_block(args...); -} - -} // namespace internal - -#if !defined(__has_feature) || !__has_feature(objc_arc) - -// Construct a callback from an objective-C block with up to six arguments (see -// note above). -template<typename R, typename... Args> -base::Callback<R(Args...)> BindBlock(R(^block)(Args...)) { - return base::Bind( - &base::internal::RunBlock<R, Args...>, - base::mac::ScopedBlock<R (^)(Args...)>( - base::mac::internal::ScopedBlockTraits<R (^)(Args...)>::Retain( - block))); -} - -#else - -// Construct a callback from an objective-C block with up to six arguments (see -// note above). -template <typename R, typename... Args> -base::Callback<R(Args...)> BindBlockArc(R (^block)(Args...)) { - return base::Bind(&base::internal::RunBlock<R, Args...>, - base::mac::ScopedBlock<R (^)(Args...)>(block)); -} - -#endif - -} // namespace base - -#endif // BASE_MAC_BIND_OBJC_BLOCK_H_ diff --git a/base/mac/bundle_locations.h b/base/mac/bundle_locations.h deleted file mode 100644 index 5cc44ba966..0000000000 --- a/base/mac/bundle_locations.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_BUNDLE_LOCATIONS_H_ -#define BASE_MAC_BUNDLE_LOCATIONS_H_ - -#include "base/base_export.h" -#include "base/files/file_path.h" - -#if defined(__OBJC__) -#import <Foundation/Foundation.h> -#else // __OBJC__ -class NSBundle; -#endif // __OBJC__ - -namespace base { - -class FilePath; - -namespace mac { - -// This file provides several functions to explicitly request the various -// component bundles of Chrome. Please use these methods rather than calling -// +[NSBundle mainBundle] or CFBundleGetMainBundle(). -// -// Terminology -// - "Outer Bundle" - This is the main bundle for Chrome; it's what -// +[NSBundle mainBundle] returns when Chrome is launched normally. -// -// - "Main Bundle" - This is the bundle from which Chrome was launched. -// This will be the same as the outer bundle except when Chrome is launched -// via an app shortcut, in which case this will return the app shortcut's -// bundle rather than the main Chrome bundle. -// -// - "Framework Bundle" - This is the bundle corresponding to the Chrome -// framework. -// -// Guidelines for use: -// - To access a resource, the Framework bundle should be used. -// - If the choice is between the Outer or Main bundles then please choose -// carefully. Most often the Outer bundle will be the right choice, but for -// cases such as adding an app to the "launch on startup" list, the Main -// bundle is probably the one to use. - -// Methods for retrieving the various bundles. -BASE_EXPORT NSBundle* MainBundle(); -BASE_EXPORT FilePath MainBundlePath(); -BASE_EXPORT NSBundle* OuterBundle(); -BASE_EXPORT FilePath OuterBundlePath(); -BASE_EXPORT NSBundle* FrameworkBundle(); -BASE_EXPORT FilePath FrameworkBundlePath(); - -// Set the bundle that the preceding functions will return, overriding the -// default values. Restore the default by passing in |nil|. -BASE_EXPORT void SetOverrideOuterBundle(NSBundle* bundle); -BASE_EXPORT void SetOverrideFrameworkBundle(NSBundle* bundle); - -// Same as above but accepting a FilePath argument. -BASE_EXPORT void SetOverrideOuterBundlePath(const FilePath& file_path); -BASE_EXPORT void SetOverrideFrameworkBundlePath(const FilePath& file_path); - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_BUNDLE_LOCATIONS_H_ diff --git a/base/mac/bundle_locations.mm b/base/mac/bundle_locations.mm deleted file mode 100644 index 54021b85ee..0000000000 --- a/base/mac/bundle_locations.mm +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/mac/bundle_locations.h" - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/strings/sys_string_conversions.h" - -namespace base { -namespace mac { - -// NSBundle isn't threadsafe, all functions in this file must be called on the -// main thread. -static NSBundle* g_override_framework_bundle = nil; -static NSBundle* g_override_outer_bundle = nil; - -NSBundle* MainBundle() { - return [NSBundle mainBundle]; -} - -FilePath MainBundlePath() { - NSBundle* bundle = MainBundle(); - return NSStringToFilePath([bundle bundlePath]); -} - -NSBundle* OuterBundle() { - if (g_override_outer_bundle) - return g_override_outer_bundle; - return [NSBundle mainBundle]; -} - -FilePath OuterBundlePath() { - NSBundle* bundle = OuterBundle(); - return NSStringToFilePath([bundle bundlePath]); -} - -NSBundle* FrameworkBundle() { - if (g_override_framework_bundle) - return g_override_framework_bundle; - return [NSBundle mainBundle]; -} - -FilePath FrameworkBundlePath() { - NSBundle* bundle = FrameworkBundle(); - return NSStringToFilePath([bundle bundlePath]); -} - -static void AssignOverrideBundle(NSBundle* new_bundle, - NSBundle** override_bundle) { - if (new_bundle != *override_bundle) { - [*override_bundle release]; - *override_bundle = [new_bundle retain]; - } -} - -static void AssignOverridePath(const FilePath& file_path, - NSBundle** override_bundle) { - NSString* path = base::SysUTF8ToNSString(file_path.value()); - NSBundle* new_bundle = [NSBundle bundleWithPath:path]; - DCHECK(new_bundle) << "Failed to load the bundle at " << file_path.value(); - AssignOverrideBundle(new_bundle, override_bundle); -} - -void SetOverrideOuterBundle(NSBundle* bundle) { - AssignOverrideBundle(bundle, &g_override_outer_bundle); -} - -void SetOverrideFrameworkBundle(NSBundle* bundle) { - AssignOverrideBundle(bundle, &g_override_framework_bundle); -} - -void SetOverrideOuterBundlePath(const FilePath& file_path) { - AssignOverridePath(file_path, &g_override_outer_bundle); -} - -void SetOverrideFrameworkBundlePath(const FilePath& file_path) { - AssignOverridePath(file_path, &g_override_framework_bundle); -} - -} // namespace mac -} // namespace base diff --git a/base/mac/call_with_eh_frame.cc b/base/mac/call_with_eh_frame.cc deleted file mode 100644 index d1d5165dac..0000000000 --- a/base/mac/call_with_eh_frame.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 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. - -#include "base/mac/call_with_eh_frame.h" - -#include <stdint.h> -#include <unwind.h> - -#include "build/build_config.h" - -namespace base { -namespace mac { - -// On CrOS we build 32bits (which is not supported on Chrome Mac BTW), so -// we use the IOS code. -//#if defined(OS_IOS) -// No iOS assembly implementation exists, so just call the block directly. -void CallWithEHFrame(void (^block)(void)) { - block(); -} - /* -#else // OS_MACOSX -extern "C" _Unwind_Reason_Code __gxx_personality_v0(int, - _Unwind_Action, - uint64_t, - struct _Unwind_Exception*, - struct _Unwind_Context*); - -_Unwind_Reason_Code CxxPersonalityRoutine( - int version, - _Unwind_Action actions, - uint64_t exception_class, - struct _Unwind_Exception* exception_object, - struct _Unwind_Context* context) { - // Unwinding is a two-phase process: phase one searches for an exception - // handler, and phase two performs cleanup. For phase one, this custom - // personality will terminate the search. For phase two, this should delegate - // back to the standard personality routine. - - if ((actions & _UA_SEARCH_PHASE) != 0) { - // Tell libunwind that this is the end of the stack. When it encounters the - // CallWithEHFrame, it will stop searching for an exception handler. The - // result is that no exception handler has been found higher on the stack, - // and any that are lower on the stack (e.g. in CFRunLoopRunSpecific), will - // now be skipped. Since this is reporting the end of the stack, and no - // exception handler will have been found, std::terminate() will be called. - return _URC_END_OF_STACK; - } - - return __gxx_personality_v0(version, actions, exception_class, - exception_object, context); -} -#endif // defined(OS_IOS) - */ -} // namespace mac -} // namespace base diff --git a/base/mac/call_with_eh_frame.h b/base/mac/call_with_eh_frame.h deleted file mode 100644 index 1f7d5e0dec..0000000000 --- a/base/mac/call_with_eh_frame.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 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. - -#ifndef BASE_MAC_CALL_WITH_EH_FRAME_H_ -#define BASE_MAC_CALL_WITH_EH_FRAME_H_ - -#include "base/base_export.h" - -namespace base { -namespace mac { - -// Invokes the specified block in a stack frame with a special exception -// handler. This function creates an exception handling stack frame that -// specifies a custom C++ exception personality routine, which terminates the -// search for an exception handler at this frame. -// -// The purpose of this function is to prevent a try/catch statement in system -// libraries, acting as a global exception handler, from handling exceptions -// in such a way that disrupts the generation of useful stack traces. -void BASE_EXPORT CallWithEHFrame(void (^block)(void)); - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_CALL_WITH_EH_FRAME_H_ diff --git a/base/mac/cocoa_protocols.h b/base/mac/cocoa_protocols.h deleted file mode 100644 index a28795c3a4..0000000000 --- a/base/mac/cocoa_protocols.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_COCOA_PROTOCOLS_H_ -#define BASE_MAC_COCOA_PROTOCOLS_H_ - -#import <Cocoa/Cocoa.h> - -// New Mac OS X SDKs introduce new protocols used for delegates. These -// protocol defintions aren't not present in earlier releases of the Mac OS X -// SDK. In order to support building against the new SDK, which requires -// delegates to conform to these protocols, and earlier SDKs, which do not -// define these protocols at all, this file will provide empty protocol -// definitions when used with earlier SDK versions. - -#define DEFINE_EMPTY_PROTOCOL(p) \ -@protocol p \ -@end - -#if !defined(MAC_OS_X_VERSION_10_7) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 - -DEFINE_EMPTY_PROTOCOL(NSDraggingDestination) -DEFINE_EMPTY_PROTOCOL(ICCameraDeviceDownloadDelegate) - -#endif // MAC_OS_X_VERSION_10_7 - -#undef DEFINE_EMPTY_PROTOCOL - -#endif // BASE_MAC_COCOA_PROTOCOLS_H_ diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h deleted file mode 100644 index 69b61280c3..0000000000 --- a/base/mac/foundation_util.h +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_FOUNDATION_UTIL_H_ -#define BASE_MAC_FOUNDATION_UTIL_H_ - -#include <CoreFoundation/CoreFoundation.h> - -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "build/build_config.h" - -#if defined(__OBJC__) -#import <Foundation/Foundation.h> -@class NSFont; -@class UIFont; -#else // __OBJC__ -#include <CoreFoundation/CoreFoundation.h> -class NSBundle; -class NSFont; -class NSString; -class UIFont; -#endif // __OBJC__ - -#if defined(OS_IOS) -#include <CoreText/CoreText.h> -#else -#include <ApplicationServices/ApplicationServices.h> -#endif - -// Adapted from NSObjCRuntime.h NS_ENUM definition (used in Foundation starting -// with the OS X 10.8 SDK and the iOS 6.0 SDK). -#if __has_extension(cxx_strong_enums) && \ - (defined(OS_IOS) || (defined(MAC_OS_X_VERSION_10_8) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8)) -#define CR_FORWARD_ENUM(_type, _name) enum _name : _type _name -#else -#define CR_FORWARD_ENUM(_type, _name) _type _name -#endif - -// Adapted from NSPathUtilities.h and NSObjCRuntime.h. -#if __LP64__ || NS_BUILD_32_LIKE_64 -typedef CR_FORWARD_ENUM(unsigned long, NSSearchPathDirectory); -typedef unsigned long NSSearchPathDomainMask; -#else -typedef CR_FORWARD_ENUM(unsigned int, NSSearchPathDirectory); -typedef unsigned int NSSearchPathDomainMask; -#endif - -typedef struct OpaqueSecTrustRef* SecACLRef; -typedef struct OpaqueSecTrustedApplicationRef* SecTrustedApplicationRef; - -#if defined(OS_IOS) -typedef struct CF_BRIDGED_TYPE(id) __SecPolicy* SecPolicyRef; -#else -typedef struct OpaqueSecPolicyRef* SecPolicyRef; -#endif - -namespace base { - -class FilePath; - -namespace mac { - -// Returns true if the application is running from a bundle -BASE_EXPORT bool AmIBundled(); -BASE_EXPORT void SetOverrideAmIBundled(bool value); - -#if defined(UNIT_TEST) -// This is required because instantiating some tests requires checking the -// directory structure, which sets the AmIBundled cache state. Individual tests -// may or may not be bundled, and this would trip them up if the cache weren't -// cleared. This should not be called from individual tests, just from test -// instantiation code that gets a path from PathService. -BASE_EXPORT void ClearAmIBundledCache(); -#endif - -// Returns true if this process is marked as a "Background only process". -BASE_EXPORT bool IsBackgroundOnlyProcess(); - -// Returns the path to a resource within the framework bundle. -BASE_EXPORT FilePath PathForFrameworkBundleResource(CFStringRef resourceName); - -// Returns the creator code associated with the CFBundleRef at bundle. -OSType CreatorCodeForCFBundleRef(CFBundleRef bundle); - -// Returns the creator code associated with this application, by calling -// CreatorCodeForCFBundleRef for the application's main bundle. If this -// information cannot be determined, returns kUnknownType ('????'). This -// does not respect the override app bundle because it's based on CFBundle -// instead of NSBundle, and because callers probably don't want the override -// app bundle's creator code anyway. -BASE_EXPORT OSType CreatorCodeForApplication(); - -// Searches for directories for the given key in only the given |domain_mask|. -// If found, fills result (which must always be non-NULL) with the -// first found directory and returns true. Otherwise, returns false. -BASE_EXPORT bool GetSearchPathDirectory(NSSearchPathDirectory directory, - NSSearchPathDomainMask domain_mask, - FilePath* result); - -// Searches for directories for the given key in only the local domain. -// If found, fills result (which must always be non-NULL) with the -// first found directory and returns true. Otherwise, returns false. -BASE_EXPORT bool GetLocalDirectory(NSSearchPathDirectory directory, - FilePath* result); - -// Searches for directories for the given key in only the user domain. -// If found, fills result (which must always be non-NULL) with the -// first found directory and returns true. Otherwise, returns false. -BASE_EXPORT bool GetUserDirectory(NSSearchPathDirectory directory, - FilePath* result); - -// Returns the ~/Library directory. -BASE_EXPORT FilePath GetUserLibraryPath(); - -// Takes a path to an (executable) binary and tries to provide the path to an -// application bundle containing it. It takes the outermost bundle that it can -// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). -// |exec_name| - path to the binary -// returns - path to the application bundle, or empty on error -BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name); - -#define TYPE_NAME_FOR_CF_TYPE_DECL(TypeCF) \ -BASE_EXPORT std::string TypeNameForCFType(TypeCF##Ref); - -TYPE_NAME_FOR_CF_TYPE_DECL(CFArray); -TYPE_NAME_FOR_CF_TYPE_DECL(CFBag); -TYPE_NAME_FOR_CF_TYPE_DECL(CFBoolean); -TYPE_NAME_FOR_CF_TYPE_DECL(CFData); -TYPE_NAME_FOR_CF_TYPE_DECL(CFDate); -TYPE_NAME_FOR_CF_TYPE_DECL(CFDictionary); -TYPE_NAME_FOR_CF_TYPE_DECL(CFNull); -TYPE_NAME_FOR_CF_TYPE_DECL(CFNumber); -TYPE_NAME_FOR_CF_TYPE_DECL(CFSet); -TYPE_NAME_FOR_CF_TYPE_DECL(CFString); -TYPE_NAME_FOR_CF_TYPE_DECL(CFURL); -TYPE_NAME_FOR_CF_TYPE_DECL(CFUUID); - -TYPE_NAME_FOR_CF_TYPE_DECL(CGColor); - -TYPE_NAME_FOR_CF_TYPE_DECL(CTFont); -TYPE_NAME_FOR_CF_TYPE_DECL(CTRun); - -TYPE_NAME_FOR_CF_TYPE_DECL(SecPolicy); - -#undef TYPE_NAME_FOR_CF_TYPE_DECL - -// Retain/release calls for memory management in C++. -BASE_EXPORT void NSObjectRetain(void* obj); -BASE_EXPORT void NSObjectRelease(void* obj); - -// CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation -// object (one derived from CFTypeRef) to the Foundation memory management -// system. In a traditional managed-memory environment, cf_object is -// autoreleased and returned as an NSObject. In a garbage-collected -// environment, cf_object is marked as eligible for garbage collection. -// -// This function should only be used to convert a concrete CFTypeRef type to -// its equivalent "toll-free bridged" NSObject subclass, for example, -// converting a CFStringRef to NSString. -// -// By calling this function, callers relinquish any ownership claim to -// cf_object. In a managed-memory environment, the object's ownership will be -// managed by the innermost NSAutoreleasePool, so after this function returns, -// callers should not assume that cf_object is valid any longer than the -// returned NSObject. -// -// Returns an id, typed here for C++'s sake as a void*. -BASE_EXPORT void* CFTypeRefToNSObjectAutorelease(CFTypeRef cf_object); - -// Returns the base bundle ID, which can be set by SetBaseBundleID but -// defaults to a reasonable string. This never returns NULL. BaseBundleID -// returns a pointer to static storage that must not be freed. -BASE_EXPORT const char* BaseBundleID(); - -// Sets the base bundle ID to override the default. The implementation will -// make its own copy of new_base_bundle_id. -BASE_EXPORT void SetBaseBundleID(const char* new_base_bundle_id); - -} // namespace mac -} // namespace base - -#if !defined(__OBJC__) -#define OBJC_CPP_CLASS_DECL(x) class x; -#else // __OBJC__ -#define OBJC_CPP_CLASS_DECL(x) -#endif // __OBJC__ - -// Convert toll-free bridged CFTypes to NSTypes and vice-versa. This does not -// autorelease |cf_val|. This is useful for the case where there is a CFType in -// a call that expects an NSType and the compiler is complaining about const -// casting problems. -// The calls are used like this: -// NSString *foo = CFToNSCast(CFSTR("Hello")); -// CFStringRef foo2 = NSToCFCast(@"Hello"); -// The macro magic below is to enforce safe casting. It could possibly have -// been done using template function specialization, but template function -// specialization doesn't always work intuitively, -// (http://www.gotw.ca/publications/mill17.htm) so the trusty combination -// of macros and function overloading is used instead. - -#define CF_TO_NS_CAST_DECL(TypeCF, TypeNS) \ -OBJC_CPP_CLASS_DECL(TypeNS) \ -\ -namespace base { \ -namespace mac { \ -BASE_EXPORT TypeNS* CFToNSCast(TypeCF##Ref cf_val); \ -BASE_EXPORT TypeCF##Ref NSToCFCast(TypeNS* ns_val); \ -} \ -} - -#define CF_TO_NS_MUTABLE_CAST_DECL(name) \ -CF_TO_NS_CAST_DECL(CF##name, NS##name) \ -OBJC_CPP_CLASS_DECL(NSMutable##name) \ -\ -namespace base { \ -namespace mac { \ -BASE_EXPORT NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val); \ -BASE_EXPORT CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val); \ -} \ -} - -// List of toll-free bridged types taken from: -// http://www.cocoadev.com/index.pl?TollFreeBridged - -CF_TO_NS_MUTABLE_CAST_DECL(Array); -CF_TO_NS_MUTABLE_CAST_DECL(AttributedString); -CF_TO_NS_CAST_DECL(CFCalendar, NSCalendar); -CF_TO_NS_MUTABLE_CAST_DECL(CharacterSet); -CF_TO_NS_MUTABLE_CAST_DECL(Data); -CF_TO_NS_CAST_DECL(CFDate, NSDate); -CF_TO_NS_MUTABLE_CAST_DECL(Dictionary); -CF_TO_NS_CAST_DECL(CFError, NSError); -CF_TO_NS_CAST_DECL(CFLocale, NSLocale); -CF_TO_NS_CAST_DECL(CFNumber, NSNumber); -CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer); -CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone); -CF_TO_NS_MUTABLE_CAST_DECL(Set); -CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream); -CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream); -CF_TO_NS_MUTABLE_CAST_DECL(String); -CF_TO_NS_CAST_DECL(CFURL, NSURL); - -#if defined(OS_IOS) -CF_TO_NS_CAST_DECL(CTFont, UIFont); -#else -CF_TO_NS_CAST_DECL(CTFont, NSFont); -#endif - -#undef CF_TO_NS_CAST_DECL -#undef CF_TO_NS_MUTABLE_CAST_DECL -#undef OBJC_CPP_CLASS_DECL - -namespace base { -namespace mac { - -// CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more -// specific CoreFoundation type. The compatibility of the passed -// object is found by comparing its opaque type against the -// requested type identifier. If the supplied object is not -// compatible with the requested return type, CFCast<>() returns -// NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer -// to either variant results in NULL being returned without -// triggering any DCHECK. -// -// Example usage: -// CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( -// CFArrayGetValueAtIndex(array, index)); -// -// CFTypeRef hello = CFSTR("hello world"); -// CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>(hello); - -template<typename T> -T CFCast(const CFTypeRef& cf_val); - -template<typename T> -T CFCastStrict(const CFTypeRef& cf_val); - -#define CF_CAST_DECL(TypeCF) \ -template<> BASE_EXPORT TypeCF##Ref \ -CFCast<TypeCF##Ref>(const CFTypeRef& cf_val);\ -\ -template<> BASE_EXPORT TypeCF##Ref \ -CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val); - -CF_CAST_DECL(CFArray); -CF_CAST_DECL(CFBag); -CF_CAST_DECL(CFBoolean); -CF_CAST_DECL(CFData); -CF_CAST_DECL(CFDate); -CF_CAST_DECL(CFDictionary); -CF_CAST_DECL(CFNull); -CF_CAST_DECL(CFNumber); -CF_CAST_DECL(CFSet); -CF_CAST_DECL(CFString); -CF_CAST_DECL(CFURL); -CF_CAST_DECL(CFUUID); - -CF_CAST_DECL(CGColor); - -CF_CAST_DECL(CTFont); -CF_CAST_DECL(CTFontDescriptor); -CF_CAST_DECL(CTRun); - -CF_CAST_DECL(SecACL); -CF_CAST_DECL(SecPolicy); -CF_CAST_DECL(SecTrustedApplication); - -#undef CF_CAST_DECL - -#if defined(__OBJC__) - -// ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more -// specific (NSObject-derived) type. The compatibility of the passed -// object is found by checking if it's a kind of the requested type -// identifier. If the supplied object is not compatible with the -// requested return type, ObjCCast<>() returns nil and -// ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either -// variant results in nil being returned without triggering any DCHECK. -// -// The strict variant is useful when retrieving a value from a -// collection which only has values of a specific type, e.g. an -// NSArray of NSStrings. The non-strict variant is useful when -// retrieving values from data that you can't fully control. For -// example, a plist read from disk may be beyond your exclusive -// control, so you'd only want to check that the values you retrieve -// from it are of the expected types, but not crash if they're not. -// -// Example usage: -// NSString* version = base::mac::ObjCCast<NSString>( -// [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); -// -// NSString* str = base::mac::ObjCCastStrict<NSString>( -// [ns_arr_of_ns_strs objectAtIndex:0]); -template<typename T> -T* ObjCCast(id objc_val) { - if ([objc_val isKindOfClass:[T class]]) { - return reinterpret_cast<T*>(objc_val); - } - return nil; -} - -template<typename T> -T* ObjCCastStrict(id objc_val) { - T* rv = ObjCCast<T>(objc_val); - DCHECK(objc_val == nil || rv); - return rv; -} - -#endif // defined(__OBJC__) - -// Helper function for GetValueFromDictionary to create the error message -// that appears when a type mismatch is encountered. -BASE_EXPORT std::string GetValueFromDictionaryErrorMessage( - CFStringRef key, const std::string& expected_type, CFTypeRef value); - -// Utility function to pull out a value from a dictionary, check its type, and -// return it. Returns NULL if the key is not present or of the wrong type. -template<typename T> -T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) { - CFTypeRef value = CFDictionaryGetValue(dict, key); - T value_specific = CFCast<T>(value); - - if (value && !value_specific) { - std::string expected_type = TypeNameForCFType(value_specific); - DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key, - expected_type, - value); - } - - return value_specific; -} - -// Converts |path| to an autoreleased NSString. Returns nil if |path| is empty. -BASE_EXPORT NSString* FilePathToNSString(const FilePath& path); - -// Converts |str| to a FilePath. Returns an empty path if |str| is nil. -BASE_EXPORT FilePath NSStringToFilePath(NSString* str); - -#if defined(__OBJC__) -// Converts |range| to an NSRange, returning the new range in |range_out|. -// Returns true if conversion was successful, false if the values of |range| -// could not be converted to NSUIntegers. -BASE_EXPORT bool CFRangeToNSRange(CFRange range, - NSRange* range_out) WARN_UNUSED_RESULT; -#endif // defined(__OBJC__) - -} // namespace mac -} // namespace base - -// Stream operations for CFTypes. They can be used with NSTypes as well -// by using the NSToCFCast methods above. -// e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); -// Operator << can not be overloaded for ObjectiveC types as the compiler -// can not distinguish between overloads for id with overloads for void*. -BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, - const CFErrorRef err); -BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, - const CFStringRef str); - -#endif // BASE_MAC_FOUNDATION_UTIL_H_ diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm deleted file mode 100644 index eb8284ee58..0000000000 --- a/base/mac/foundation_util.mm +++ /dev/null @@ -1,481 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/mac/foundation_util.h" - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/mac/bundle_locations.h" -#include "base/mac/mac_logging.h" -#include "base/macros.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/sys_string_conversions.h" -#include "build/build_config.h" - -#if !defined(OS_IOS) -#import <AppKit/AppKit.h> -#endif - -#if !defined(OS_IOS) -extern "C" { -CFTypeID SecACLGetTypeID(); -CFTypeID SecTrustedApplicationGetTypeID(); -Boolean _CFIsObjC(CFTypeID typeID, CFTypeRef obj); -} // extern "C" -#endif - -namespace base { -namespace mac { - -namespace { - -bool g_cached_am_i_bundled_called = false; -bool g_cached_am_i_bundled_value = false; -bool g_override_am_i_bundled = false; -bool g_override_am_i_bundled_value = false; - -bool UncachedAmIBundled() { -#if defined(OS_IOS) - // All apps are bundled on iOS. - return true; -#else - if (g_override_am_i_bundled) - return g_override_am_i_bundled_value; - - // Yes, this is cheap. - return [[base::mac::OuterBundle() bundlePath] hasSuffix:@".app"]; -#endif -} - -} // namespace - -bool AmIBundled() { - // If the return value is not cached, this function will return different - // values depending on when it's called. This confuses some client code, see - // http://crbug.com/63183 . - if (!g_cached_am_i_bundled_called) { - g_cached_am_i_bundled_called = true; - g_cached_am_i_bundled_value = UncachedAmIBundled(); - } - DCHECK_EQ(g_cached_am_i_bundled_value, UncachedAmIBundled()) - << "The return value of AmIBundled() changed. This will confuse tests. " - << "Call SetAmIBundled() override manually if your test binary " - << "delay-loads the framework."; - return g_cached_am_i_bundled_value; -} - -void SetOverrideAmIBundled(bool value) { -#if defined(OS_IOS) - // It doesn't make sense not to be bundled on iOS. - if (!value) - NOTREACHED(); -#endif - g_override_am_i_bundled = true; - g_override_am_i_bundled_value = value; -} - -BASE_EXPORT void ClearAmIBundledCache() { - g_cached_am_i_bundled_called = false; -} - -bool IsBackgroundOnlyProcess() { - // This function really does want to examine NSBundle's idea of the main - // bundle dictionary. It needs to look at the actual running .app's - // Info.plist to access its LSUIElement property. - NSDictionary* info_dictionary = [base::mac::MainBundle() infoDictionary]; - return [[info_dictionary objectForKey:@"LSUIElement"] boolValue] != NO; -} - -FilePath PathForFrameworkBundleResource(CFStringRef resourceName) { - NSBundle* bundle = base::mac::FrameworkBundle(); - NSString* resourcePath = [bundle pathForResource:(NSString*)resourceName - ofType:nil]; - return NSStringToFilePath(resourcePath); -} - -OSType CreatorCodeForCFBundleRef(CFBundleRef bundle) { - OSType creator = kUnknownType; - CFBundleGetPackageInfo(bundle, NULL, &creator); - return creator; -} - -OSType CreatorCodeForApplication() { - CFBundleRef bundle = CFBundleGetMainBundle(); - if (!bundle) - return kUnknownType; - - return CreatorCodeForCFBundleRef(bundle); -} - -bool GetSearchPathDirectory(NSSearchPathDirectory directory, - NSSearchPathDomainMask domain_mask, - FilePath* result) { - DCHECK(result); - NSArray* dirs = - NSSearchPathForDirectoriesInDomains(directory, domain_mask, YES); - if ([dirs count] < 1) { - return false; - } - *result = NSStringToFilePath([dirs objectAtIndex:0]); - return true; -} - -bool GetLocalDirectory(NSSearchPathDirectory directory, FilePath* result) { - return GetSearchPathDirectory(directory, NSLocalDomainMask, result); -} - -bool GetUserDirectory(NSSearchPathDirectory directory, FilePath* result) { - return GetSearchPathDirectory(directory, NSUserDomainMask, result); -} - -FilePath GetUserLibraryPath() { - FilePath user_library_path; - if (!GetUserDirectory(NSLibraryDirectory, &user_library_path)) { - DLOG(WARNING) << "Could not get user library path"; - } - return user_library_path; -} - -// Takes a path to an (executable) binary and tries to provide the path to an -// application bundle containing it. It takes the outermost bundle that it can -// find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). -// |exec_name| - path to the binary -// returns - path to the application bundle, or empty on error -FilePath GetAppBundlePath(const FilePath& exec_name) { - const char kExt[] = ".app"; - const size_t kExtLength = arraysize(kExt) - 1; - - // Split the path into components. - std::vector<std::string> components; - exec_name.GetComponents(&components); - - // It's an error if we don't get any components. - if (components.empty()) - return FilePath(); - - // Don't prepend '/' to the first component. - std::vector<std::string>::const_iterator it = components.begin(); - std::string bundle_name = *it; - DCHECK_GT(it->length(), 0U); - // If the first component ends in ".app", we're already done. - if (it->length() > kExtLength && - !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength)) - return FilePath(bundle_name); - - // The first component may be "/" or "//", etc. Only append '/' if it doesn't - // already end in '/'. - if (bundle_name.back() != '/') - bundle_name += '/'; - - // Go through the remaining components. - for (++it; it != components.end(); ++it) { - DCHECK_GT(it->length(), 0U); - - bundle_name += *it; - - // If the current component ends in ".app", we're done. - if (it->length() > kExtLength && - !it->compare(it->length() - kExtLength, kExtLength, kExt, kExtLength)) - return FilePath(bundle_name); - - // Separate this component from the next one. - bundle_name += '/'; - } - - return FilePath(); -} - -#define TYPE_NAME_FOR_CF_TYPE_DEFN(TypeCF) \ -std::string TypeNameForCFType(TypeCF##Ref) { \ - return #TypeCF; \ -} - -TYPE_NAME_FOR_CF_TYPE_DEFN(CFArray); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFBag); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFBoolean); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFData); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFDate); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFDictionary); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFNull); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFNumber); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFSet); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFString); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFURL); -TYPE_NAME_FOR_CF_TYPE_DEFN(CFUUID); - -TYPE_NAME_FOR_CF_TYPE_DEFN(CGColor); - -TYPE_NAME_FOR_CF_TYPE_DEFN(CTFont); -TYPE_NAME_FOR_CF_TYPE_DEFN(CTRun); - -#if !defined(OS_IOS) -TYPE_NAME_FOR_CF_TYPE_DEFN(SecPolicy); -#endif - -#undef TYPE_NAME_FOR_CF_TYPE_DEFN - -void NSObjectRetain(void* obj) { - id<NSObject> nsobj = static_cast<id<NSObject> >(obj); - [nsobj retain]; -} - -void NSObjectRelease(void* obj) { - id<NSObject> nsobj = static_cast<id<NSObject> >(obj); - [nsobj release]; -} - -void* CFTypeRefToNSObjectAutorelease(CFTypeRef cf_object) { - // When GC is on, NSMakeCollectable marks cf_object for GC and autorelease - // is a no-op. - // - // In the traditional GC-less environment, NSMakeCollectable is a no-op, - // and cf_object is autoreleased, balancing out the caller's ownership claim. - // - // NSMakeCollectable returns nil when used on a NULL object. - return [NSMakeCollectable(cf_object) autorelease]; -} - -static const char* base_bundle_id; - -const char* BaseBundleID() { - if (base_bundle_id) { - return base_bundle_id; - } - -#if defined(GOOGLE_CHROME_BUILD) - return "com.google.Chrome"; -#else - return "org.chromium.Chromium"; -#endif -} - -void SetBaseBundleID(const char* new_base_bundle_id) { - if (new_base_bundle_id != base_bundle_id) { - free((void*)base_bundle_id); - base_bundle_id = new_base_bundle_id ? strdup(new_base_bundle_id) : NULL; - } -} - -// Definitions for the corresponding CF_TO_NS_CAST_DECL macros in -// foundation_util.h. -#define CF_TO_NS_CAST_DEFN(TypeCF, TypeNS) \ -\ -TypeNS* CFToNSCast(TypeCF##Ref cf_val) { \ - DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \ - TypeNS* ns_val = \ - const_cast<TypeNS*>(reinterpret_cast<const TypeNS*>(cf_val)); \ - return ns_val; \ -} \ -\ -TypeCF##Ref NSToCFCast(TypeNS* ns_val) { \ - TypeCF##Ref cf_val = reinterpret_cast<TypeCF##Ref>(ns_val); \ - DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \ - return cf_val; \ -} - -#define CF_TO_NS_MUTABLE_CAST_DEFN(name) \ -CF_TO_NS_CAST_DEFN(CF##name, NS##name) \ -\ -NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val) { \ - DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \ - NSMutable##name* ns_val = reinterpret_cast<NSMutable##name*>(cf_val); \ - return ns_val; \ -} \ -\ -CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val) { \ - CFMutable##name##Ref cf_val = \ - reinterpret_cast<CFMutable##name##Ref>(ns_val); \ - DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \ - return cf_val; \ -} - -CF_TO_NS_MUTABLE_CAST_DEFN(Array); -CF_TO_NS_MUTABLE_CAST_DEFN(AttributedString); -CF_TO_NS_CAST_DEFN(CFCalendar, NSCalendar); -CF_TO_NS_MUTABLE_CAST_DEFN(CharacterSet); -CF_TO_NS_MUTABLE_CAST_DEFN(Data); -CF_TO_NS_CAST_DEFN(CFDate, NSDate); -CF_TO_NS_MUTABLE_CAST_DEFN(Dictionary); -CF_TO_NS_CAST_DEFN(CFError, NSError); -CF_TO_NS_CAST_DEFN(CFLocale, NSLocale); -CF_TO_NS_CAST_DEFN(CFNumber, NSNumber); -CF_TO_NS_CAST_DEFN(CFRunLoopTimer, NSTimer); -CF_TO_NS_CAST_DEFN(CFTimeZone, NSTimeZone); -CF_TO_NS_MUTABLE_CAST_DEFN(Set); -CF_TO_NS_CAST_DEFN(CFReadStream, NSInputStream); -CF_TO_NS_CAST_DEFN(CFWriteStream, NSOutputStream); -CF_TO_NS_MUTABLE_CAST_DEFN(String); -CF_TO_NS_CAST_DEFN(CFURL, NSURL); - -#if defined(OS_IOS) -CF_TO_NS_CAST_DEFN(CTFont, UIFont); -#else -// The NSFont/CTFont toll-free bridging is broken when it comes to type -// checking, so do some special-casing. -// http://www.openradar.me/15341349 rdar://15341349 -NSFont* CFToNSCast(CTFontRef cf_val) { - NSFont* ns_val = - const_cast<NSFont*>(reinterpret_cast<const NSFont*>(cf_val)); - DCHECK(!cf_val || - CTFontGetTypeID() == CFGetTypeID(cf_val) || - (_CFIsObjC(CTFontGetTypeID(), cf_val) && - [ns_val isKindOfClass:[NSFont class]])); - return ns_val; -} - -CTFontRef NSToCFCast(NSFont* ns_val) { - CTFontRef cf_val = reinterpret_cast<CTFontRef>(ns_val); - DCHECK(!cf_val || - CTFontGetTypeID() == CFGetTypeID(cf_val) || - [ns_val isKindOfClass:[NSFont class]]); - return cf_val; -} -#endif - -#undef CF_TO_NS_CAST_DEFN -#undef CF_TO_NS_MUTABLE_CAST_DEFN - -#define CF_CAST_DEFN(TypeCF) \ -template<> TypeCF##Ref \ -CFCast<TypeCF##Ref>(const CFTypeRef& cf_val) { \ - if (cf_val == NULL) { \ - return NULL; \ - } \ - if (CFGetTypeID(cf_val) == TypeCF##GetTypeID()) { \ - return (TypeCF##Ref)(cf_val); \ - } \ - return NULL; \ -} \ -\ -template<> TypeCF##Ref \ -CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val) { \ - TypeCF##Ref rv = CFCast<TypeCF##Ref>(cf_val); \ - DCHECK(cf_val == NULL || rv); \ - return rv; \ -} - -CF_CAST_DEFN(CFArray); -CF_CAST_DEFN(CFBag); -CF_CAST_DEFN(CFBoolean); -CF_CAST_DEFN(CFData); -CF_CAST_DEFN(CFDate); -CF_CAST_DEFN(CFDictionary); -CF_CAST_DEFN(CFNull); -CF_CAST_DEFN(CFNumber); -CF_CAST_DEFN(CFSet); -CF_CAST_DEFN(CFString); -CF_CAST_DEFN(CFURL); -CF_CAST_DEFN(CFUUID); - -CF_CAST_DEFN(CGColor); - -CF_CAST_DEFN(CTFontDescriptor); -CF_CAST_DEFN(CTRun); - -#if defined(OS_IOS) -CF_CAST_DEFN(CTFont); -#else -// The NSFont/CTFont toll-free bridging is broken when it comes to type -// checking, so do some special-casing. -// http://www.openradar.me/15341349 rdar://15341349 -template<> CTFontRef -CFCast<CTFontRef>(const CFTypeRef& cf_val) { - if (cf_val == NULL) { - return NULL; - } - if (CFGetTypeID(cf_val) == CTFontGetTypeID()) { - return (CTFontRef)(cf_val); - } - - if (!_CFIsObjC(CTFontGetTypeID(), cf_val)) - return NULL; - - id<NSObject> ns_val = reinterpret_cast<id>(const_cast<void*>(cf_val)); - if ([ns_val isKindOfClass:[NSFont class]]) { - return (CTFontRef)(cf_val); - } - return NULL; -} - -template<> CTFontRef -CFCastStrict<CTFontRef>(const CFTypeRef& cf_val) { - CTFontRef rv = CFCast<CTFontRef>(cf_val); - DCHECK(cf_val == NULL || rv); - return rv; -} -#endif - -#if !defined(OS_IOS) -CF_CAST_DEFN(SecACL); -CF_CAST_DEFN(SecPolicy); -CF_CAST_DEFN(SecTrustedApplication); -#endif - -#undef CF_CAST_DEFN - -std::string GetValueFromDictionaryErrorMessage( - CFStringRef key, const std::string& expected_type, CFTypeRef value) { - ScopedCFTypeRef<CFStringRef> actual_type_ref( - CFCopyTypeIDDescription(CFGetTypeID(value))); - return "Expected value for key " + - base::SysCFStringRefToUTF8(key) + - " to be " + - expected_type + - " but it was " + - base::SysCFStringRefToUTF8(actual_type_ref) + - " instead"; -} - -NSString* FilePathToNSString(const FilePath& path) { - if (path.empty()) - return nil; - return [NSString stringWithUTF8String:path.value().c_str()]; -} - -FilePath NSStringToFilePath(NSString* str) { - if (![str length]) - return FilePath(); - return FilePath([str fileSystemRepresentation]); -} - -bool CFRangeToNSRange(CFRange range, NSRange* range_out) { - if (base::IsValueInRangeForNumericType<decltype(range_out->location)>( - range.location) && - base::IsValueInRangeForNumericType<decltype(range_out->length)>( - range.length) && - base::IsValueInRangeForNumericType<decltype(range_out->location)>( - range.location + range.length)) { - *range_out = NSMakeRange(range.location, range.length); - return true; - } - return false; -} - -} // namespace mac -} // namespace base - -std::ostream& operator<<(std::ostream& o, const CFStringRef string) { - return o << base::SysCFStringRefToUTF8(string); -} - -std::ostream& operator<<(std::ostream& o, const CFErrorRef err) { - base::ScopedCFTypeRef<CFStringRef> desc(CFErrorCopyDescription(err)); - base::ScopedCFTypeRef<CFDictionaryRef> user_info(CFErrorCopyUserInfo(err)); - CFStringRef errorDesc = NULL; - if (user_info.get()) { - errorDesc = reinterpret_cast<CFStringRef>( - CFDictionaryGetValue(user_info.get(), kCFErrorDescriptionKey)); - } - o << "Code: " << CFErrorGetCode(err) - << " Domain: " << CFErrorGetDomain(err) - << " Desc: " << desc.get(); - if(errorDesc) { - o << "(" << errorDesc << ")"; - } - return o; -} diff --git a/base/mac/mac_logging.h b/base/mac/mac_logging.h deleted file mode 100644 index 30e43ead29..0000000000 --- a/base/mac/mac_logging.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_MAC_LOGGING_H_ -#define BASE_MAC_MAC_LOGGING_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_IOS) -#include <MacTypes.h> -#else -#include <libkern/OSTypes.h> -#endif - -// Use the OSSTATUS_LOG family to log messages related to errors in Mac OS X -// system routines that report status via an OSStatus or OSErr value. It is -// similar to the PLOG family which operates on errno, but because there is no -// global (or thread-local) OSStatus or OSErr value, the specific error must -// be supplied as an argument to the OSSTATUS_LOG macro. The message logged -// will contain the symbolic constant name corresponding to the status value, -// along with the value itself. -// -// OSErr is just an older 16-bit form of the newer 32-bit OSStatus. Despite -// the name, OSSTATUS_LOG can be used equally well for OSStatus and OSErr. - -namespace logging { - -// Returns a UTF8 description from an OS X Status error. -BASE_EXPORT std::string DescriptionFromOSStatus(OSStatus err); - -class BASE_EXPORT OSStatusLogMessage : public logging::LogMessage { - public: - OSStatusLogMessage(const char* file_path, - int line, - LogSeverity severity, - OSStatus status); - ~OSStatusLogMessage(); - - private: - OSStatus status_; - - DISALLOW_COPY_AND_ASSIGN(OSStatusLogMessage); -}; - -} // namespace logging - -#if defined(NDEBUG) -#define MAC_DVLOG_IS_ON(verbose_level) 0 -#else -#define MAC_DVLOG_IS_ON(verbose_level) VLOG_IS_ON(verbose_level) -#endif - -#define OSSTATUS_LOG_STREAM(severity, status) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(OSStatusLogMessage, status).stream() -#define OSSTATUS_VLOG_STREAM(verbose_level, status) \ - logging::OSStatusLogMessage(__FILE__, __LINE__, \ - -verbose_level, status).stream() - -#define OSSTATUS_LOG(severity, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(severity, status), LOG_IS_ON(severity)) -#define OSSTATUS_LOG_IF(severity, condition, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(severity, status), \ - LOG_IS_ON(severity) && (condition)) - -#define OSSTATUS_VLOG(verbose_level, status) \ - LAZY_STREAM(OSSTATUS_VLOG_STREAM(verbose_level, status), \ - VLOG_IS_ON(verbose_level)) -#define OSSTATUS_VLOG_IF(verbose_level, condition, status) \ - LAZY_STREAM(OSSTATUS_VLOG_STREAM(verbose_level, status), \ - VLOG_IS_ON(verbose_level) && (condition)) - -#define OSSTATUS_CHECK(condition, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(FATAL, status), !(condition)) \ - << "Check failed: " # condition << ". " - -#define OSSTATUS_DLOG(severity, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(severity, status), DLOG_IS_ON(severity)) -#define OSSTATUS_DLOG_IF(severity, condition, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(severity, status), \ - DLOG_IS_ON(severity) && (condition)) - -#define OSSTATUS_DVLOG(verbose_level, status) \ - LAZY_STREAM(OSSTATUS_VLOG_STREAM(verbose_level, status), \ - MAC_DVLOG_IS_ON(verbose_level)) -#define OSSTATUS_DVLOG_IF(verbose_level, condition, status) \ - LAZY_STREAM(OSSTATUS_VLOG_STREAM(verbose_level, status), \ - MAC_DVLOG_IS_ON(verbose_level) && (condition)) - -#define OSSTATUS_DCHECK(condition, status) \ - LAZY_STREAM(OSSTATUS_LOG_STREAM(FATAL, status), \ - DCHECK_IS_ON() && !(condition)) \ - << "Check failed: " #condition << ". " - -#endif // BASE_MAC_MAC_LOGGING_H_ diff --git a/base/mac/mac_logging.mm b/base/mac/mac_logging.mm deleted file mode 100644 index f0d3c07da8..0000000000 --- a/base/mac/mac_logging.mm +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/mac/mac_logging.h" - -#import <Foundation/Foundation.h> - -#include <iomanip> - -#include "build/build_config.h" - -#if !defined(OS_IOS) -#include <CoreServices/CoreServices.h> -#endif - -namespace logging { - -std::string DescriptionFromOSStatus(OSStatus err) { - NSError* error = - [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil]; - return error.description.UTF8String; -} - -OSStatusLogMessage::OSStatusLogMessage(const char* file_path, - int line, - LogSeverity severity, - OSStatus status) - : LogMessage(file_path, line, severity), - status_(status) { -} - -OSStatusLogMessage::~OSStatusLogMessage() { -#if defined(OS_IOS) - // TODO(crbug.com/546375): Consider using NSError with NSOSStatusErrorDomain - // to try to get a description of the failure. - stream() << ": " << status_; -#else - stream() << ": " - << DescriptionFromOSStatus(status_) - << " (" - << status_ - << ")"; -#endif -} - -} // namespace logging diff --git a/base/mac/mac_util.h b/base/mac/mac_util.h deleted file mode 100644 index 67d1880849..0000000000 --- a/base/mac/mac_util.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_MAC_UTIL_H_ -#define BASE_MAC_MAC_UTIL_H_ - -#include <stdint.h> -#include <string> - -#import <CoreGraphics/CoreGraphics.h> - -#include "base/base_export.h" - -namespace base { - -class FilePath; - -namespace mac { - -// Full screen modes, in increasing order of priority. More permissive modes -// take predecence. -enum FullScreenMode { - kFullScreenModeHideAll = 0, - kFullScreenModeHideDock = 1, - kFullScreenModeAutoHideAll = 2, - kNumFullScreenModes = 3, - - // kFullScreenModeNormal is not a valid FullScreenMode, but it is useful to - // other classes, so we include it here. - kFullScreenModeNormal = 10, -}; - -// Returns an sRGB color space. The return value is a static value; do not -// release it! -BASE_EXPORT CGColorSpaceRef GetSRGBColorSpace(); - -// Returns the generic RGB color space. The return value is a static value; do -// not release it! -BASE_EXPORT CGColorSpaceRef GetGenericRGBColorSpace(); - -// Returns the color space being used by the main display. The return value -// is a static value; do not release it! -BASE_EXPORT CGColorSpaceRef GetSystemColorSpace(); - -// Add a full screen request for the given |mode|. Must be paired with a -// ReleaseFullScreen() call for the same |mode|. This does not by itself create -// a fullscreen window; rather, it manages per-application state related to -// hiding the dock and menubar. Must be called on the main thread. -BASE_EXPORT void RequestFullScreen(FullScreenMode mode); - -// Release a request for full screen mode. Must be matched with a -// RequestFullScreen() call for the same |mode|. As with RequestFullScreen(), -// this does not affect windows directly, but rather manages per-application -// state. For example, if there are no other outstanding -// |kFullScreenModeAutoHideAll| requests, this will reshow the menu bar. Must -// be called on main thread. -BASE_EXPORT void ReleaseFullScreen(FullScreenMode mode); - -// Convenience method to switch the current fullscreen mode. This has the same -// net effect as a ReleaseFullScreen(from_mode) call followed immediately by a -// RequestFullScreen(to_mode). Must be called on the main thread. -BASE_EXPORT void SwitchFullScreenModes(FullScreenMode from_mode, - FullScreenMode to_mode); - -// Excludes the file given by |file_path| from being backed up by Time Machine. -BASE_EXPORT bool SetFileBackupExclusion(const FilePath& file_path); - -// Checks if the current application is set as a Login Item, so it will launch -// on Login. If a non-NULL pointer to is_hidden is passed, the Login Item also -// is queried for the 'hide on launch' flag. -BASE_EXPORT bool CheckLoginItemStatus(bool* is_hidden); - -// Adds current application to the set of Login Items with specified "hide" -// flag. This has the same effect as adding/removing the application in -// SystemPreferences->Accounts->LoginItems or marking Application in the Dock -// as "Options->Open on Login". -// Does nothing if the application is already set up as Login Item with -// specified hide flag. -BASE_EXPORT void AddToLoginItems(bool hide_on_startup); - -// Removes the current application from the list Of Login Items. -BASE_EXPORT void RemoveFromLoginItems(); - -// Returns true if the current process was automatically launched as a -// 'Login Item' or via Lion's Resume. Used to suppress opening windows. -BASE_EXPORT bool WasLaunchedAsLoginOrResumeItem(); - -// Returns true if the current process was automatically launched as a -// 'Login Item' or via Resume, and the 'Reopen windows when logging back in' -// checkbox was selected by the user. This indicates that the previous -// session should be restored. -BASE_EXPORT bool WasLaunchedAsLoginItemRestoreState(); - -// Returns true if the current process was automatically launched as a -// 'Login Item' with 'hide on startup' flag. Used to suppress opening windows. -BASE_EXPORT bool WasLaunchedAsHiddenLoginItem(); - -// Remove the quarantine xattr from the given file. Returns false if there was -// an error, or true otherwise. -BASE_EXPORT bool RemoveQuarantineAttribute(const FilePath& file_path); - -namespace internal { - -// Returns the system's Mac OS X minor version. This is the |y| value -// in 10.y or 10.y.z. -BASE_EXPORT int MacOSXMinorVersion(); - -} // namespace internal - -// Run-time OS version checks. Use these instead of -// base::SysInfo::OperatingSystemVersionNumbers. Prefer the "AtLeast" and -// "AtMost" variants to those that check for a specific version, unless you -// know for sure that you need to check for a specific version. - -#define DEFINE_IS_OS_FUNCS(V, TEST_DEPLOYMENT_TARGET) \ - inline bool IsOS10_##V() { \ - TEST_DEPLOYMENT_TARGET(>, V, false) \ - return internal::MacOSXMinorVersion() == V; \ - } \ - inline bool IsAtLeastOS10_##V() { \ - TEST_DEPLOYMENT_TARGET(>=, V, true) \ - return internal::MacOSXMinorVersion() >= V; \ - } \ - inline bool IsAtMostOS10_##V() { \ - TEST_DEPLOYMENT_TARGET(>, V, false) \ - return internal::MacOSXMinorVersion() <= V; \ - } - -#define TEST_DEPLOYMENT_TARGET(OP, V, RET) \ - if (MAC_OS_X_VERSION_MIN_REQUIRED OP MAC_OS_X_VERSION_10_##V) \ - return RET; -#define IGNORE_DEPLOYMENT_TARGET(OP, V, RET) - -DEFINE_IS_OS_FUNCS(9, TEST_DEPLOYMENT_TARGET) -DEFINE_IS_OS_FUNCS(10, TEST_DEPLOYMENT_TARGET) - -#ifdef MAC_OS_X_VERSION_10_11 -DEFINE_IS_OS_FUNCS(11, TEST_DEPLOYMENT_TARGET) -#else -DEFINE_IS_OS_FUNCS(11, IGNORE_DEPLOYMENT_TARGET) -#endif - -#ifdef MAC_OS_X_VERSION_10_12 -DEFINE_IS_OS_FUNCS(12, TEST_DEPLOYMENT_TARGET) -#else -DEFINE_IS_OS_FUNCS(12, IGNORE_DEPLOYMENT_TARGET) -#endif - -#undef IGNORE_DEPLOYMENT_TARGET -#undef TEST_DEPLOYMENT_TARGET -#undef DEFINE_IS_OS_FUNCS - -// This should be infrequently used. It only makes sense to use this to avoid -// codepaths that are very likely to break on future (unreleased, untested, -// unborn) OS releases, or to log when the OS is newer than any known version. -inline bool IsOSLaterThan10_12_DontCallThis() { - return !IsAtMostOS10_12(); -} - -// Retrieve the system's model identifier string from the IOKit registry: -// for example, "MacPro4,1", "MacBookPro6,1". Returns empty string upon -// failure. -BASE_EXPORT std::string GetModelIdentifier(); - -// Parse a model identifier string; for example, into ("MacBookPro", 6, 1). -// If any error occurs, none of the input pointers are touched. -BASE_EXPORT bool ParseModelIdentifier(const std::string& ident, - std::string* type, - int32_t* major, - int32_t* minor); - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_MAC_UTIL_H_ diff --git a/base/mac/mach_logging.cc b/base/mac/mach_logging.cc deleted file mode 100644 index 7b939b3dd9..0000000000 --- a/base/mac/mach_logging.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2014 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. - -#include "base/mac/mach_logging.h" - -#include <iomanip> -#include <string> - -#include "base/strings/stringprintf.h" -#include "build/build_config.h" - -#if !defined(OS_IOS) -#include <servers/bootstrap.h> -#endif // !OS_IOS - -namespace { - -std::string FormatMachErrorNumber(mach_error_t mach_err) { - // For the os/kern subsystem, give the error number in decimal as in - // <mach/kern_return.h>. Otherwise, give it in hexadecimal to make it easier - // to visualize the various bits. See <mach/error.h>. - if (mach_err >= 0 && mach_err < KERN_RETURN_MAX) { - return base::StringPrintf(" (%d)", mach_err); - } - return base::StringPrintf(" (0x%08x)", mach_err); -} - -} // namespace - -namespace logging { - -MachLogMessage::MachLogMessage(const char* file_path, - int line, - LogSeverity severity, - mach_error_t mach_err) - : LogMessage(file_path, line, severity), - mach_err_(mach_err) { -} - -MachLogMessage::~MachLogMessage() { - stream() << ": " - << mach_error_string(mach_err_) - << FormatMachErrorNumber(mach_err_); -} - -#if !defined(OS_IOS) - -BootstrapLogMessage::BootstrapLogMessage(const char* file_path, - int line, - LogSeverity severity, - kern_return_t bootstrap_err) - : LogMessage(file_path, line, severity), - bootstrap_err_(bootstrap_err) { -} - -BootstrapLogMessage::~BootstrapLogMessage() { - stream() << ": " - << bootstrap_strerror(bootstrap_err_); - - switch (bootstrap_err_) { - case BOOTSTRAP_SUCCESS: - case BOOTSTRAP_NOT_PRIVILEGED: - case BOOTSTRAP_NAME_IN_USE: - case BOOTSTRAP_UNKNOWN_SERVICE: - case BOOTSTRAP_SERVICE_ACTIVE: - case BOOTSTRAP_BAD_COUNT: - case BOOTSTRAP_NO_MEMORY: - case BOOTSTRAP_NO_CHILDREN: { - // Show known bootstrap errors in decimal because that's how they're - // defined in <servers/bootstrap.h>. - stream() << " (" << bootstrap_err_ << ")"; - break; - } - - default: { - // bootstrap_strerror passes unknown errors to mach_error_string, so - // format them as they would be if they were handled by - // MachErrorMessage. - stream() << FormatMachErrorNumber(bootstrap_err_); - break; - } - } -} - -#endif // !OS_IOS - -} // namespace logging diff --git a/base/mac/mach_logging.h b/base/mac/mach_logging.h deleted file mode 100644 index 59ab762c3c..0000000000 --- a/base/mac/mach_logging.h +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2014 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. - -#ifndef BASE_MAC_MACH_LOGGING_H_ -#define BASE_MAC_MACH_LOGGING_H_ - -#include <mach/mach.h> - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "build/build_config.h" - -// Use the MACH_LOG family of macros along with a mach_error_t (kern_return_t) -// containing a Mach error. The error value will be decoded so that logged -// messages explain the error. -// -// Use the BOOTSTRAP_LOG family of macros specifically for errors that occur -// while interoperating with the bootstrap subsystem. These errors will first -// be looked up as bootstrap error messages. If no match is found, they will -// be treated as generic Mach errors, as in MACH_LOG. -// -// Examples: -// -// kern_return_t kr = mach_timebase_info(&info); -// if (kr != KERN_SUCCESS) { -// MACH_LOG(ERROR, kr) << "mach_timebase_info"; -// } -// -// kr = vm_deallocate(task, address, size); -// MACH_DCHECK(kr == KERN_SUCCESS, kr) << "vm_deallocate"; - -namespace logging { - -class BASE_EXPORT MachLogMessage : public logging::LogMessage { - public: - MachLogMessage(const char* file_path, - int line, - LogSeverity severity, - mach_error_t mach_err); - ~MachLogMessage(); - - private: - mach_error_t mach_err_; - - DISALLOW_COPY_AND_ASSIGN(MachLogMessage); -}; - -} // namespace logging - -#if defined(NDEBUG) -#define MACH_DVLOG_IS_ON(verbose_level) 0 -#else -#define MACH_DVLOG_IS_ON(verbose_level) VLOG_IS_ON(verbose_level) -#endif - -#define MACH_LOG_STREAM(severity, mach_err) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(MachLogMessage, mach_err).stream() -#define MACH_VLOG_STREAM(verbose_level, mach_err) \ - logging::MachLogMessage(__FILE__, __LINE__, \ - -verbose_level, mach_err).stream() - -#define MACH_LOG(severity, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), LOG_IS_ON(severity)) -#define MACH_LOG_IF(severity, condition, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), \ - LOG_IS_ON(severity) && (condition)) - -#define MACH_VLOG(verbose_level, mach_err) \ - LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \ - VLOG_IS_ON(verbose_level)) -#define MACH_VLOG_IF(verbose_level, condition, mach_err) \ - LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \ - VLOG_IS_ON(verbose_level) && (condition)) - -#define MACH_CHECK(condition, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(FATAL, mach_err), !(condition)) \ - << "Check failed: " # condition << ". " - -#define MACH_DLOG(severity, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), DLOG_IS_ON(severity)) -#define MACH_DLOG_IF(severity, condition, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), \ - DLOG_IS_ON(severity) && (condition)) - -#define MACH_DVLOG(verbose_level, mach_err) \ - LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \ - MACH_DVLOG_IS_ON(verbose_level)) -#define MACH_DVLOG_IF(verbose_level, condition, mach_err) \ - LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \ - MACH_DVLOG_IS_ON(verbose_level) && (condition)) - -#define MACH_DCHECK(condition, mach_err) \ - LAZY_STREAM(MACH_LOG_STREAM(FATAL, mach_err), \ - DCHECK_IS_ON() && !(condition)) \ - << "Check failed: " #condition << ". " - -#if !defined(OS_IOS) - -namespace logging { - -class BASE_EXPORT BootstrapLogMessage : public logging::LogMessage { - public: - BootstrapLogMessage(const char* file_path, - int line, - LogSeverity severity, - kern_return_t bootstrap_err); - ~BootstrapLogMessage(); - - private: - kern_return_t bootstrap_err_; - - DISALLOW_COPY_AND_ASSIGN(BootstrapLogMessage); -}; - -} // namespace logging - -#define BOOTSTRAP_DVLOG_IS_ON MACH_DVLOG_IS_ON - -#define BOOTSTRAP_LOG_STREAM(severity, bootstrap_err) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(BootstrapLogMessage, \ - bootstrap_err).stream() -#define BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err) \ - logging::BootstrapLogMessage(__FILE__, __LINE__, \ - -verbose_level, bootstrap_err).stream() - -#define BOOTSTRAP_LOG(severity, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, \ - bootstrap_err), LOG_IS_ON(severity)) -#define BOOTSTRAP_LOG_IF(severity, condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \ - LOG_IS_ON(severity) && (condition)) - -#define BOOTSTRAP_VLOG(verbose_level, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \ - VLOG_IS_ON(verbose_level)) -#define BOOTSTRAP_VLOG_IF(verbose_level, condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \ - VLOG_IS_ON(verbose_level) && (condition)) - -#define BOOTSTRAP_CHECK(condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(FATAL, bootstrap_err), !(condition)) \ - << "Check failed: " # condition << ". " - -#define BOOTSTRAP_DLOG(severity, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \ - DLOG_IS_ON(severity)) -#define BOOTSTRAP_DLOG_IF(severity, condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \ - DLOG_IS_ON(severity) && (condition)) - -#define BOOTSTRAP_DVLOG(verbose_level, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \ - BOOTSTRAP_DVLOG_IS_ON(verbose_level)) -#define BOOTSTRAP_DVLOG_IF(verbose_level, condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \ - BOOTSTRAP_DVLOG_IS_ON(verbose_level) && (condition)) - -#define BOOTSTRAP_DCHECK(condition, bootstrap_err) \ - LAZY_STREAM(BOOTSTRAP_LOG_STREAM(FATAL, bootstrap_err), \ - DCHECK_IS_ON() && !(condition)) \ - << "Check failed: " #condition << ". " - -#endif // !OS_IOS - -#endif // BASE_MAC_MACH_LOGGING_H_ diff --git a/base/mac/mach_port_broker.h b/base/mac/mach_port_broker.h deleted file mode 100644 index 4554b6aec6..0000000000 --- a/base/mac/mach_port_broker.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2016 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. - -#ifndef BASE_MAC_MACH_PORT_BROKER_H_ -#define BASE_MAC_MACH_PORT_BROKER_H_ - -#include <mach/mach.h> - -#include <map> -#include <memory> -#include <string> - -#include "base/base_export.h" -#include "base/mac/dispatch_source_mach.h" -#include "base/mac/scoped_mach_port.h" -#include "base/macros.h" -#include "base/process/port_provider_mac.h" -#include "base/process/process_handle.h" -#include "base/synchronization/lock.h" - -namespace base { - -// On OS X, the task port of a process is required to collect metrics about the -// process, and to insert Mach ports into the process. Running |task_for_pid()| -// is only allowed for privileged code. However, a process has port rights to -// all its subprocesses, so let the child processes send their Mach port to the -// parent over IPC. -// -// Mach ports can only be sent over Mach IPC, not over the |socketpair()| that -// the regular IPC system uses. Hence, the child processes opens a Mach -// connection shortly after launching and ipc their mach data to the parent -// process. A single |MachPortBroker| with a given name is expected to exist in -// the parent process. -// -// Since this data arrives over a separate channel, it is not available -// immediately after a child process has been started. -class BASE_EXPORT MachPortBroker : public base::PortProvider { - public: - // For use in child processes. This will send the task port of the current - // process over Mach IPC to the port registered by name (via this class) in - // the parent process. Returns true if the message was sent successfully - // and false if otherwise. - static bool ChildSendTaskPortToParent(const std::string& name); - - // Returns the Mach port name to use when sending or receiving messages. - // Does the Right Thing in the browser and in child processes. - static std::string GetMachPortName(const std::string& name, bool is_child); - - MachPortBroker(const std::string& name); - ~MachPortBroker() override; - - // Performs any initialization work. - bool Init(); - - // Adds a placeholder to the map for the given pid with MACH_PORT_NULL. - // Callers are expected to later update the port with FinalizePid(). Callers - // MUST acquire the lock given by GetLock() before calling this method (and - // release the lock afterwards). - void AddPlaceholderForPid(base::ProcessHandle pid); - - // Removes |pid| from the task port map. Callers MUST acquire the lock given - // by GetLock() before calling this method (and release the lock afterwards). - void InvalidatePid(base::ProcessHandle pid); - - // The lock that protects this MachPortBroker object. Callers MUST acquire - // and release this lock around calls to AddPlaceholderForPid(), - // InvalidatePid(), and FinalizePid(); - base::Lock& GetLock() { return lock_; } - - // Implement |base::PortProvider|. - mach_port_t TaskForPid(base::ProcessHandle process) const override; - - private: - friend class MachPortBrokerTest; - - // Message handler that is invoked on |dispatch_source_| when an - // incoming message needs to be received. - void HandleRequest(); - - // Updates the mapping for |pid| to include the given |mach_info|. Does - // nothing if PlaceholderForPid() has not already been called for the given - // |pid|. Callers MUST acquire the lock given by GetLock() before calling - // this method (and release the lock afterwards). - void FinalizePid(base::ProcessHandle pid, mach_port_t task_port); - - // Name used to identify a particular port broker. - const std::string name_; - - // The Mach port on which the server listens. - base::mac::ScopedMachReceiveRight server_port_; - - // The dispatch source and queue on which Mach messages will be received. - std::unique_ptr<base::DispatchSourceMach> dispatch_source_; - - // Stores mach info for every process in the broker. - typedef std::map<base::ProcessHandle, mach_port_t> MachMap; - MachMap mach_map_; - - // Mutex that guards |mach_map_|. - mutable base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(MachPortBroker); -}; - -} // namespace base - -#endif // BASE_MAC_MACH_PORT_BROKER_H_ diff --git a/base/mac/mach_port_broker.mm b/base/mac/mach_port_broker.mm deleted file mode 100644 index 6d9fec5ab6..0000000000 --- a/base/mac/mach_port_broker.mm +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2016 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. - -#include "base/mac/mach_port_broker.h" - -#include <bsm/libbsm.h> -#include <servers/bootstrap.h> - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/mach_logging.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" - -namespace base { - -namespace { - -// Mach message structure used in the child as a sending message. -struct MachPortBroker_ChildSendMsg { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_port_descriptor_t child_task_port; -}; - -// Complement to the ChildSendMsg, this is used in the parent for receiving -// a message. Contains a message trailer with audit information. -struct MachPortBroker_ParentRecvMsg : public MachPortBroker_ChildSendMsg { - mach_msg_audit_trailer_t trailer; -}; - -} // namespace - -// static -bool MachPortBroker::ChildSendTaskPortToParent(const std::string& name) { - // Look up the named MachPortBroker port that's been registered with the - // bootstrap server. - mach_port_t parent_port; - kern_return_t kr = bootstrap_look_up(bootstrap_port, - const_cast<char*>(GetMachPortName(name, true).c_str()), &parent_port); - if (kr != KERN_SUCCESS) { - BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up"; - return false; - } - base::mac::ScopedMachSendRight scoped_right(parent_port); - - // Create the check in message. This will copy a send right on this process' - // (the child's) task port and send it to the parent. - MachPortBroker_ChildSendMsg msg; - bzero(&msg, sizeof(msg)); - msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) | - MACH_MSGH_BITS_COMPLEX; - msg.header.msgh_remote_port = parent_port; - msg.header.msgh_size = sizeof(msg); - msg.body.msgh_descriptor_count = 1; - msg.child_task_port.name = mach_task_self(); - msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND; - msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR; - - kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg), - 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); - if (kr != KERN_SUCCESS) { - MACH_LOG(ERROR, kr) << "mach_msg"; - return false; - } - - return true; -} - -// static -std::string MachPortBroker::GetMachPortName(const std::string& name, - bool is_child) { - // In child processes, use the parent's pid. - const pid_t pid = is_child ? getppid() : getpid(); - return base::StringPrintf( - "%s.%s.%d", base::mac::BaseBundleID(), name.c_str(), pid); -} - -mach_port_t MachPortBroker::TaskForPid(base::ProcessHandle pid) const { - base::AutoLock lock(lock_); - MachPortBroker::MachMap::const_iterator it = mach_map_.find(pid); - if (it == mach_map_.end()) - return MACH_PORT_NULL; - return it->second; -} - -MachPortBroker::MachPortBroker(const std::string& name) : name_(name) {} - -MachPortBroker::~MachPortBroker() {} - -bool MachPortBroker::Init() { - DCHECK(server_port_.get() == MACH_PORT_NULL); - - // Check in with launchd and publish the service name. - mach_port_t port; - kern_return_t kr = bootstrap_check_in( - bootstrap_port, GetMachPortName(name_, false).c_str(), &port); - if (kr != KERN_SUCCESS) { - BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in"; - return false; - } - server_port_.reset(port); - - // Start the dispatch source. - std::string queue_name = - base::StringPrintf("%s.MachPortBroker", base::mac::BaseBundleID()); - dispatch_source_.reset(new base::DispatchSourceMach( - queue_name.c_str(), server_port_.get(), ^{ HandleRequest(); })); - dispatch_source_->Resume(); - - return true; -} - -void MachPortBroker::AddPlaceholderForPid(base::ProcessHandle pid) { - lock_.AssertAcquired(); - DCHECK_EQ(0u, mach_map_.count(pid)); - mach_map_[pid] = MACH_PORT_NULL; -} - -void MachPortBroker::InvalidatePid(base::ProcessHandle pid) { - lock_.AssertAcquired(); - - MachMap::iterator mach_it = mach_map_.find(pid); - if (mach_it != mach_map_.end()) { - kern_return_t kr = mach_port_deallocate(mach_task_self(), mach_it->second); - MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; - mach_map_.erase(mach_it); - } -} - -void MachPortBroker::HandleRequest() { - MachPortBroker_ParentRecvMsg msg; - bzero(&msg, sizeof(msg)); - msg.header.msgh_size = sizeof(msg); - msg.header.msgh_local_port = server_port_.get(); - - const mach_msg_option_t options = MACH_RCV_MSG | - MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | - MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); - - kern_return_t kr = mach_msg(&msg.header, - options, - 0, - sizeof(msg), - server_port_.get(), - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - if (kr != KERN_SUCCESS) { - MACH_LOG(ERROR, kr) << "mach_msg"; - return; - } - - // Use the kernel audit information to make sure this message is from - // a task that this process spawned. The kernel audit token contains the - // unspoofable pid of the task that sent the message. - pid_t child_pid = audit_token_to_pid(msg.trailer.msgh_audit); - mach_port_t child_task_port = msg.child_task_port.name; - - // Take the lock and update the broker information. - { - base::AutoLock lock(lock_); - FinalizePid(child_pid, child_task_port); - } - NotifyObservers(child_pid); -} - -void MachPortBroker::FinalizePid(base::ProcessHandle pid, - mach_port_t task_port) { - lock_.AssertAcquired(); - - MachMap::iterator it = mach_map_.find(pid); - if (it == mach_map_.end()) { - // Do nothing for unknown pids. - LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; - return; - } - - DCHECK(it->second == MACH_PORT_NULL); - if (it->second == MACH_PORT_NULL) - it->second = task_port; -} - -} // namespace base diff --git a/base/mac/mach_port_broker_unittest.cc b/base/mac/mach_port_broker_unittest.cc deleted file mode 100644 index cb4b82ca47..0000000000 --- a/base/mac/mach_port_broker_unittest.cc +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2016 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. - -#include "base/mac/mach_port_broker.h" - -#include "base/command_line.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_timeouts.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/multiprocess_func_list.h" - -namespace base { - -namespace { -const char kBootstrapPortName[] = "thisisatest"; -} - -class MachPortBrokerTest : public testing::Test, - public base::PortProvider::Observer { - public: - MachPortBrokerTest() - : broker_(kBootstrapPortName), - event_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - received_process_(kNullProcessHandle) { - broker_.AddObserver(this); - } - ~MachPortBrokerTest() override { - broker_.RemoveObserver(this); - } - - // Helper function to acquire/release locks and call |PlaceholderForPid()|. - void AddPlaceholderForPid(base::ProcessHandle pid) { - base::AutoLock lock(broker_.GetLock()); - broker_.AddPlaceholderForPid(pid); - } - - // Helper function to acquire/release locks and call |FinalizePid()|. - void FinalizePid(base::ProcessHandle pid, - mach_port_t task_port) { - base::AutoLock lock(broker_.GetLock()); - broker_.FinalizePid(pid, task_port); - } - - void WaitForTaskPort() { - event_.Wait(); - } - - // base::PortProvider::Observer: - void OnReceivedTaskPort(ProcessHandle process) override { - received_process_ = process; - event_.Signal(); - } - - protected: - MachPortBroker broker_; - WaitableEvent event_; - ProcessHandle received_process_; -}; - -TEST_F(MachPortBrokerTest, Locks) { - // Acquire and release the locks. Nothing bad should happen. - base::AutoLock lock(broker_.GetLock()); -} - -TEST_F(MachPortBrokerTest, AddPlaceholderAndFinalize) { - // Add a placeholder for PID 1. - AddPlaceholderForPid(1); - EXPECT_EQ(0u, broker_.TaskForPid(1)); - - // Finalize PID 1. - FinalizePid(1, 100u); - EXPECT_EQ(100u, broker_.TaskForPid(1)); - - // Should be no entry for PID 2. - EXPECT_EQ(0u, broker_.TaskForPid(2)); -} - -TEST_F(MachPortBrokerTest, FinalizeUnknownPid) { - // Finalizing an entry for an unknown pid should not add it to the map. - FinalizePid(1u, 100u); - EXPECT_EQ(0u, broker_.TaskForPid(1u)); -} - -MULTIPROCESS_TEST_MAIN(MachPortBrokerTestChild) { - CHECK(base::MachPortBroker::ChildSendTaskPortToParent(kBootstrapPortName)); - return 0; -} - -TEST_F(MachPortBrokerTest, ReceivePortFromChild) { - ASSERT_TRUE(broker_.Init()); - CommandLine command_line( - base::GetMultiProcessTestChildBaseCommandLine()); - broker_.GetLock().Acquire(); - base::SpawnChildResult spawn_result = base::SpawnMultiProcessTestChild( - "MachPortBrokerTestChild", command_line, LaunchOptions()); - broker_.AddPlaceholderForPid(spawn_result.process.Handle()); - broker_.GetLock().Release(); - - WaitForTaskPort(); - EXPECT_EQ(spawn_result.process.Handle(), received_process_); - - int rv = -1; - ASSERT_TRUE(spawn_result.process.WaitForExitWithTimeout( - TestTimeouts::action_timeout(), &rv)); - EXPECT_EQ(0, rv); - - EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), - broker_.TaskForPid(spawn_result.process.Handle())); -} - -TEST_F(MachPortBrokerTest, ReceivePortFromChildWithoutAdding) { - ASSERT_TRUE(broker_.Init()); - CommandLine command_line( - base::GetMultiProcessTestChildBaseCommandLine()); - broker_.GetLock().Acquire(); - base::SpawnChildResult spawn_result = base::SpawnMultiProcessTestChild( - "MachPortBrokerTestChild", command_line, LaunchOptions()); - - broker_.GetLock().Release(); - - int rv = -1; - ASSERT_TRUE(spawn_result.process.WaitForExitWithTimeout( - TestTimeouts::action_timeout(), &rv)); - EXPECT_EQ(0, rv); - - EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL), - broker_.TaskForPid(spawn_result.process.Handle())); -} - -} // namespace base diff --git a/base/mac/mach_port_util.cc b/base/mac/mach_port_util.cc deleted file mode 100644 index 0eee21085d..0000000000 --- a/base/mac/mach_port_util.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2016 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. - -#include "base/mac/mach_port_util.h" - -#include "base/logging.h" - -namespace base { - -namespace { - -// Struct for sending a complex Mach message. -struct MachSendComplexMessage { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_port_descriptor_t data; -}; - -// Struct for receiving a complex message. -struct MachReceiveComplexMessage { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_port_descriptor_t data; - mach_msg_trailer_t trailer; -}; - -} // namespace - -kern_return_t SendMachPort(mach_port_t endpoint, - mach_port_t port_to_send, - int disposition) { - MachSendComplexMessage send_msg; - send_msg.header.msgh_bits = - MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0) | MACH_MSGH_BITS_COMPLEX; - send_msg.header.msgh_size = sizeof(send_msg); - send_msg.header.msgh_remote_port = endpoint; - send_msg.header.msgh_local_port = MACH_PORT_NULL; - send_msg.header.msgh_reserved = 0; - send_msg.header.msgh_id = 0; - send_msg.body.msgh_descriptor_count = 1; - send_msg.data.name = port_to_send; - send_msg.data.disposition = disposition; - send_msg.data.type = MACH_MSG_PORT_DESCRIPTOR; - - kern_return_t kr = - mach_msg(&send_msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, - send_msg.header.msgh_size, - 0, // receive limit - MACH_PORT_NULL, // receive name - 0, // timeout - MACH_PORT_NULL); // notification port - - if (kr != KERN_SUCCESS) - mach_port_deallocate(mach_task_self(), endpoint); - - return kr; -} - -base::mac::ScopedMachSendRight ReceiveMachPort(mach_port_t port_to_listen_on) { - MachReceiveComplexMessage recv_msg; - mach_msg_header_t* recv_hdr = &recv_msg.header; - recv_hdr->msgh_local_port = port_to_listen_on; - recv_hdr->msgh_size = sizeof(recv_msg); - - kern_return_t kr = - mach_msg(recv_hdr, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, - recv_hdr->msgh_size, port_to_listen_on, 0, MACH_PORT_NULL); - if (kr != KERN_SUCCESS) - return base::mac::ScopedMachSendRight(MACH_PORT_NULL); - if (recv_msg.header.msgh_id != 0) - return base::mac::ScopedMachSendRight(MACH_PORT_NULL); - return base::mac::ScopedMachSendRight(recv_msg.data.name); -} - -mach_port_name_t CreateIntermediateMachPort( - mach_port_t task_port, - base::mac::ScopedMachSendRight port_to_insert, - MachCreateError* error_code) { - DCHECK_NE(mach_task_self(), task_port); - DCHECK_NE(static_cast<mach_port_name_t>(MACH_PORT_NULL), task_port); - - // Make a port with receive rights in the destination task. - mach_port_name_t endpoint; - kern_return_t kr = - mach_port_allocate(task_port, MACH_PORT_RIGHT_RECEIVE, &endpoint); - if (kr != KERN_SUCCESS) { - if (error_code) - *error_code = MachCreateError::ERROR_MAKE_RECEIVE_PORT; - return MACH_PORT_NULL; - } - - // Change its message queue limit so that it accepts one message. - mach_port_limits limits = {}; - limits.mpl_qlimit = 1; - kr = mach_port_set_attributes(task_port, endpoint, MACH_PORT_LIMITS_INFO, - reinterpret_cast<mach_port_info_t>(&limits), - MACH_PORT_LIMITS_INFO_COUNT); - if (kr != KERN_SUCCESS) { - if (error_code) - *error_code = MachCreateError::ERROR_SET_ATTRIBUTES; - mach_port_deallocate(task_port, endpoint); - return MACH_PORT_NULL; - } - - // Get a send right. - mach_port_t send_once_right; - mach_msg_type_name_t send_right_type; - kr = - mach_port_extract_right(task_port, endpoint, MACH_MSG_TYPE_MAKE_SEND_ONCE, - &send_once_right, &send_right_type); - if (kr != KERN_SUCCESS) { - if (error_code) - *error_code = MachCreateError::ERROR_EXTRACT_DEST_RIGHT; - mach_port_deallocate(task_port, endpoint); - return MACH_PORT_NULL; - } - DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND_ONCE), - send_right_type); - - // This call takes ownership of |send_once_right|. - kr = base::SendMachPort( - send_once_right, port_to_insert.get(), MACH_MSG_TYPE_COPY_SEND); - if (kr != KERN_SUCCESS) { - if (error_code) - *error_code = MachCreateError::ERROR_SEND_MACH_PORT; - mach_port_deallocate(task_port, endpoint); - return MACH_PORT_NULL; - } - - // Endpoint is intentionally leaked into the destination task. An IPC must be - // sent to the destination task so that it can clean up this port. - return endpoint; -} - -} // namespace base diff --git a/base/mac/mach_port_util.h b/base/mac/mach_port_util.h deleted file mode 100644 index f7a7f325f1..0000000000 --- a/base/mac/mach_port_util.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 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. - -#ifndef BASE_MAC_MACH_PORT_UTIL_H_ -#define BASE_MAC_MACH_PORT_UTIL_H_ - -#include <mach/mach.h> - -#include "base/base_export.h" -#include "base/mac/scoped_mach_port.h" - -namespace base { - -enum class MachCreateError { - ERROR_MAKE_RECEIVE_PORT, - ERROR_SET_ATTRIBUTES, - ERROR_EXTRACT_DEST_RIGHT, - ERROR_SEND_MACH_PORT, -}; - -// Sends a Mach port to |dest_port|. Assumes that |dest_port| is a send once -// right. Takes ownership of |dest_port|. -BASE_EXPORT kern_return_t SendMachPort(mach_port_t dest_port, - mach_port_t port_to_send, - int disposition); - -// Receives a Mach port from |port_to_listen_on|, which should have exactly one -// queued message. Returns |MACH_PORT_NULL| on any error. -BASE_EXPORT base::mac::ScopedMachSendRight ReceiveMachPort( - mach_port_t port_to_listen_on); - -// Creates an intermediate Mach port in |task_port| and sends |port_to_insert| -// as a mach_msg to the intermediate Mach port. -// |task_port| is the task port of another process. -// |port_to_insert| must be a send right in the current task's name space. -// Returns the intermediate port on success, and MACH_PORT_NULL on failure. -// On failure, |error_code| is set if not null. -// This method takes ownership of |port_to_insert|. On success, ownership is -// passed to the intermediate Mach port. -BASE_EXPORT mach_port_name_t CreateIntermediateMachPort( - mach_port_t task_port, - base::mac::ScopedMachSendRight port_to_insert, - MachCreateError* error_code); - -} // namespace base - -#endif // BASE_MAC_MACH_PORT_UTIL_H_ diff --git a/base/mac/scoped_aedesc.h b/base/mac/scoped_aedesc.h deleted file mode 100644 index 73270920dd..0000000000 --- a/base/mac/scoped_aedesc.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2010 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. - -#ifndef BASE_MAC_SCOPED_AEDESC_H_ -#define BASE_MAC_SCOPED_AEDESC_H_ - -#import <CoreServices/CoreServices.h> - -#include "base/macros.h" - -namespace base { -namespace mac { - -// The ScopedAEDesc is used to scope AppleEvent descriptors. On creation, -// it will store a NULL descriptor. On destruction, it will dispose of the -// descriptor. -// -// This class is parameterized for additional type safety checks. You can use -// the generic AEDesc type by not providing a template parameter: -// ScopedAEDesc<> desc; -template <typename AEDescType = AEDesc> -class ScopedAEDesc { - public: - ScopedAEDesc() { - AECreateDesc(typeNull, NULL, 0, &desc_); - } - - ~ScopedAEDesc() { - AEDisposeDesc(&desc_); - } - - // Used for in parameters. - operator const AEDescType*() { - return &desc_; - } - - // Used for out parameters. - AEDescType* OutPointer() { - return &desc_; - } - - private: - AEDescType desc_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAEDesc); -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_AEDESC_H_ diff --git a/base/mac/scoped_authorizationref.h b/base/mac/scoped_authorizationref.h deleted file mode 100644 index b83f8dfb35..0000000000 --- a/base/mac/scoped_authorizationref.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_AUTHORIZATIONREF_H_ -#define BASE_MAC_SCOPED_AUTHORIZATIONREF_H_ - -#include <Security/Authorization.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" - -// ScopedAuthorizationRef maintains ownership of an AuthorizationRef. It is -// patterned after the unique_ptr interface. - -namespace base { -namespace mac { - -class ScopedAuthorizationRef { - public: - explicit ScopedAuthorizationRef(AuthorizationRef authorization = NULL) - : authorization_(authorization) { - } - - ~ScopedAuthorizationRef() { - if (authorization_) { - AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights); - } - } - - void reset(AuthorizationRef authorization = NULL) { - if (authorization_ != authorization) { - if (authorization_) { - AuthorizationFree(authorization_, kAuthorizationFlagDestroyRights); - } - authorization_ = authorization; - } - } - - bool operator==(AuthorizationRef that) const { - return authorization_ == that; - } - - bool operator!=(AuthorizationRef that) const { - return authorization_ != that; - } - - operator AuthorizationRef() const { - return authorization_; - } - - AuthorizationRef* get_pointer() { return &authorization_; } - - AuthorizationRef get() const { - return authorization_; - } - - void swap(ScopedAuthorizationRef& that) { - AuthorizationRef temp = that.authorization_; - that.authorization_ = authorization_; - authorization_ = temp; - } - - // ScopedAuthorizationRef::release() is like std::unique_ptr<>::release. It is - // NOT a wrapper for AuthorizationFree(). To force a ScopedAuthorizationRef - // object to call AuthorizationFree(), use ScopedAuthorizationRef::reset(). - AuthorizationRef release() WARN_UNUSED_RESULT { - AuthorizationRef temp = authorization_; - authorization_ = NULL; - return temp; - } - - private: - AuthorizationRef authorization_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAuthorizationRef); -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_AUTHORIZATIONREF_H_ diff --git a/base/mac/scoped_block.h b/base/mac/scoped_block.h deleted file mode 100644 index 10ab4b4e88..0000000000 --- a/base/mac/scoped_block.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef BASE_MAC_SCOPED_BLOCK_H_ -#define BASE_MAC_SCOPED_BLOCK_H_ - -#include <Block.h> - -#include "base/mac/scoped_typeref.h" - -#if defined(__has_feature) && __has_feature(objc_arc) -#define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) (__bridge TYPE)(VALUE) -#else -#define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) VALUE -#endif - -namespace base { -namespace mac { - -namespace internal { - -template <typename B> -struct ScopedBlockTraits { - static B InvalidValue() { return nullptr; } - static B Retain(B block) { - return BASE_MAC_BRIDGE_CAST( - B, Block_copy(BASE_MAC_BRIDGE_CAST(const void*, block))); - } - static void Release(B block) { - Block_release(BASE_MAC_BRIDGE_CAST(const void*, block)); - } -}; - -} // namespace internal - -// ScopedBlock<> is patterned after ScopedCFTypeRef<>, but uses Block_copy() and -// Block_release() instead of CFRetain() and CFRelease(). -template <typename B> -class ScopedBlock : public ScopedTypeRef<B, internal::ScopedBlockTraits<B>> { - public: - using Traits = internal::ScopedBlockTraits<B>; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit ScopedBlock( - B block = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : ScopedTypeRef<B, Traits>(block, policy) {} -#else - explicit ScopedBlock(B block = Traits::InvalidValue()) - : ScopedTypeRef<B, Traits>(block, base::scoped_policy::RETAIN) {} -#endif - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(B block = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - ScopedTypeRef<B, Traits>::reset(block, policy); - } -#else - void reset(B block = Traits::InvalidValue()) { - ScopedTypeRef<B, Traits>::reset(block, base::scoped_policy::RETAIN); - } -#endif -}; - -} // namespace mac -} // namespace base - -#undef BASE_MAC_BRIDGE_CAST - -#endif // BASE_MAC_SCOPED_BLOCK_H_ diff --git a/base/mac/scoped_cffiledescriptorref.h b/base/mac/scoped_cffiledescriptorref.h deleted file mode 100644 index 923a159c76..0000000000 --- a/base/mac/scoped_cffiledescriptorref.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 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. - -#ifndef BASE_MAC_SCOPED_CFFILEDESCRIPTORREF_H_ -#define BASE_MAC_SCOPED_CFFILEDESCRIPTORREF_H_ - -#include <CoreFoundation/CoreFoundation.h> - -#include "base/scoped_generic.h" - -namespace base { -namespace mac { - -namespace internal { - -struct ScopedCFFileDescriptorRefTraits { - static CFFileDescriptorRef InvalidValue() { return nullptr; } - static void Free(CFFileDescriptorRef ref) { - CFFileDescriptorInvalidate(ref); - CFRelease(ref); - } -}; - -} // namespace internal - -// ScopedCFFileDescriptorRef is designed after ScopedCFTypeRef<>. On -// destruction, it will invalidate the file descriptor. -// ScopedCFFileDescriptorRef (unlike ScopedCFTypeRef<>) does not support RETAIN -// semantics, copying, or assignment, as doing so would increase the chances -// that a file descriptor is invalidated while still in use. -using ScopedCFFileDescriptorRef = - ScopedGeneric<CFFileDescriptorRef, - internal::ScopedCFFileDescriptorRefTraits>; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_CFFILEDESCRIPTORREF_H_ diff --git a/base/mac/scoped_cftyperef.h b/base/mac/scoped_cftyperef.h deleted file mode 100644 index ccbc5cfbe6..0000000000 --- a/base/mac/scoped_cftyperef.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_CFTYPEREF_H_ -#define BASE_MAC_SCOPED_CFTYPEREF_H_ - -#include <CoreFoundation/CoreFoundation.h> - -#include "base/mac/scoped_typeref.h" - -namespace base { - -// ScopedCFTypeRef<> is patterned after std::unique_ptr<>, but maintains -// ownership of a CoreFoundation object: any object that can be represented -// as a CFTypeRef. Style deviations here are solely for compatibility with -// std::unique_ptr<>'s interface, with which everyone is already familiar. -// -// By default, ScopedCFTypeRef<> takes ownership of an object (in the -// constructor or in reset()) by taking over the caller's existing ownership -// claim. The caller must own the object it gives to ScopedCFTypeRef<>, and -// relinquishes an ownership claim to that object. ScopedCFTypeRef<> does not -// call CFRetain(). This behavior is parameterized by the |OwnershipPolicy| -// enum. If the value |RETAIN| is passed (in the constructor or in reset()), -// then ScopedCFTypeRef<> will call CFRetain() on the object, and the initial -// ownership is not changed. - -namespace internal { - -template<typename CFT> -struct ScopedCFTypeRefTraits { - static CFT InvalidValue() { return nullptr; } - static CFT Retain(CFT object) { - CFRetain(object); - return object; - } - static void Release(CFT object) { - CFRelease(object); - } -}; - -} // namespace internal - -template<typename CFT> -using ScopedCFTypeRef = - ScopedTypeRef<CFT, internal::ScopedCFTypeRefTraits<CFT>>; - -} // namespace base - -#endif // BASE_MAC_SCOPED_CFTYPEREF_H_ diff --git a/base/mac/scoped_dispatch_object.h b/base/mac/scoped_dispatch_object.h deleted file mode 100644 index 5f5d517d9b..0000000000 --- a/base/mac/scoped_dispatch_object.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 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. - -#ifndef BASE_MAC_SCOPED_DISPATCH_OBJECT_H_ -#define BASE_MAC_SCOPED_DISPATCH_OBJECT_H_ - -#include <dispatch/dispatch.h> - -#include "base/mac/scoped_typeref.h" - -namespace base { - -namespace internal { - -template <typename T> -struct ScopedDispatchObjectTraits { - static T InvalidValue() { return nullptr; } - static T Retain(T object) { - dispatch_retain(object); - return object; - } - static void Release(T object) { - dispatch_release(object); - } -}; - -} // namepsace internal - -template <typename T> -using ScopedDispatchObject = - ScopedTypeRef<T, internal::ScopedDispatchObjectTraits<T>>; - -} // namespace base - -#endif // BASE_MAC_SCOPED_DISPATCH_OBJECT_H_ diff --git a/base/mac/scoped_ioobject.h b/base/mac/scoped_ioobject.h deleted file mode 100644 index c948cb5542..0000000000 --- a/base/mac/scoped_ioobject.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_IOOBJECT_H_ -#define BASE_MAC_SCOPED_IOOBJECT_H_ - -#include <IOKit/IOKitLib.h> - -#include "base/mac/scoped_typeref.h" - -namespace base { -namespace mac { - -namespace internal { - -template <typename IOT> -struct ScopedIOObjectTraits { - static IOT InvalidValue() { return IO_OBJECT_NULL; } - static IOT Retain(IOT iot) { - IOObjectRetain(iot); - return iot; - } - static void Release(IOT iot) { IOObjectRelease(iot); } -}; - -} // namespce internal - -// Just like ScopedCFTypeRef but for io_object_t and subclasses. -template <typename IOT> -using ScopedIOObject = ScopedTypeRef<IOT, internal::ScopedIOObjectTraits<IOT>>; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_IOOBJECT_H_ diff --git a/base/mac/scoped_ioplugininterface.h b/base/mac/scoped_ioplugininterface.h deleted file mode 100644 index 872da8eaa5..0000000000 --- a/base/mac/scoped_ioplugininterface.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_IOPLUGININTERFACE_H_ -#define BASE_MAC_SCOPED_IOPLUGININTERFACE_H_ - -#include <IOKit/IOKitLib.h> - -#include "base/mac/scoped_typeref.h" - -namespace base { -namespace mac { - -namespace internal { - -template <typename T> -struct ScopedIOPluginInterfaceTraits { - static T InvalidValue() { return nullptr; } - static T Retain(T t) { - (*t)->AddRef(t); - return t; - } - static void Release(T t) { (*t)->Release(t); } -}; - -} // namespace internal - -// Just like ScopedCFTypeRef but for IOCFPlugInInterface and friends -// (IOUSBInterfaceStruct and IOUSBDeviceStruct320 in particular). -template <typename T> -using ScopedIOPluginInterface = - ScopedTypeRef<T**, internal::ScopedIOPluginInterfaceTraits<T**>>; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_IOPLUGININTERFACE_H_ diff --git a/base/mac/scoped_launch_data.h b/base/mac/scoped_launch_data.h deleted file mode 100644 index f4db3306d4..0000000000 --- a/base/mac/scoped_launch_data.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_LAUNCH_DATA_H_ -#define BASE_MAC_SCOPED_LAUNCH_DATA_H_ - -#include <launch.h> - -#include "base/scoped_generic.h" - -namespace base { -namespace mac { - -namespace internal { - -struct ScopedLaunchDataTraits { - static launch_data_t InvalidValue() { return nullptr; } - static void Free(launch_data_t ldt) { launch_data_free(ldt); } -}; - -} // namespace internal - -// Just like std::unique_ptr<> but for launch_data_t. -using ScopedLaunchData = - ScopedGeneric<launch_data_t, internal::ScopedLaunchDataTraits>; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_LAUNCH_DATA_H_ diff --git a/base/mac/scoped_mach_port.cc b/base/mac/scoped_mach_port.cc deleted file mode 100644 index 13307f2c9d..0000000000 --- a/base/mac/scoped_mach_port.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/mac/scoped_mach_port.h" - -#include "base/mac/mach_logging.h" - -namespace base { -namespace mac { -namespace internal { - -// static -void SendRightTraits::Free(mach_port_t port) { - kern_return_t kr = mach_port_deallocate(mach_task_self(), port); - MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) - << "ScopedMachSendRight mach_port_deallocate"; -} - -// static -void ReceiveRightTraits::Free(mach_port_t port) { - kern_return_t kr = - mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1); - MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) - << "ScopedMachReceiveRight mach_port_mod_refs"; -} - -// static -void PortSetTraits::Free(mach_port_t port) { - kern_return_t kr = - mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, -1); - MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) - << "ScopedMachPortSet mach_port_mod_refs"; -} - -} // namespace internal -} // namespace mac -} // namespace base diff --git a/base/mac/scoped_mach_port.h b/base/mac/scoped_mach_port.h deleted file mode 100644 index 67fed6bcfd..0000000000 --- a/base/mac/scoped_mach_port.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_MACH_PORT_H_ -#define BASE_MAC_SCOPED_MACH_PORT_H_ - -#include <mach/mach.h> - -#include "base/base_export.h" -#include "base/scoped_generic.h" - -namespace base { -namespace mac { - -namespace internal { - -struct BASE_EXPORT SendRightTraits { - static mach_port_t InvalidValue() { - return MACH_PORT_NULL; - } - - BASE_EXPORT static void Free(mach_port_t port); -}; - -struct BASE_EXPORT ReceiveRightTraits { - static mach_port_t InvalidValue() { - return MACH_PORT_NULL; - } - - BASE_EXPORT static void Free(mach_port_t port); -}; - -struct PortSetTraits { - static mach_port_t InvalidValue() { - return MACH_PORT_NULL; - } - - BASE_EXPORT static void Free(mach_port_t port); -}; - -} // namespace internal - -// A scoper for handling a Mach port that names a send right. Send rights are -// reference counted, and this takes ownership of the right on construction -// and then removes a reference to the right on destruction. If the reference -// is the last one on the right, the right is deallocated. -using ScopedMachSendRight = - ScopedGeneric<mach_port_t, internal::SendRightTraits>; - -// A scoper for handling a Mach port's receive right. There is only one -// receive right per port. This takes ownership of the receive right on -// construction and then destroys the right on destruction, turning all -// outstanding send rights into dead names. -using ScopedMachReceiveRight = - ScopedGeneric<mach_port_t, internal::ReceiveRightTraits>; - -// A scoper for handling a Mach port set. A port set can have only one -// reference. This takes ownership of that single reference on construction and -// destroys the port set on destruction. Destroying a port set does not destroy -// the receive rights that are members of the port set. -using ScopedMachPortSet = ScopedGeneric<mach_port_t, internal::PortSetTraits>; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_MACH_PORT_H_ diff --git a/base/mac/scoped_mach_vm.cc b/base/mac/scoped_mach_vm.cc deleted file mode 100644 index d52c77f639..0000000000 --- a/base/mac/scoped_mach_vm.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 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. - -#include "base/mac/scoped_mach_vm.h" - -namespace base { -namespace mac { - -void ScopedMachVM::reset(vm_address_t address, vm_size_t size) { - DCHECK_EQ(address % PAGE_SIZE, 0u); - DCHECK_EQ(size % PAGE_SIZE, 0u); - - if (size_) { - if (address_ < address) { - vm_deallocate(mach_task_self(), - address_, - std::min(size_, address - address_)); - } - if (address_ + size_ > address + size) { - vm_address_t deallocate_start = std::max(address_, address + size); - vm_deallocate(mach_task_self(), - deallocate_start, - address_ + size_ - deallocate_start); - } - } - - address_ = address; - size_ = size; -} - -} // namespace mac -} // namespace base diff --git a/base/mac/scoped_mach_vm.h b/base/mac/scoped_mach_vm.h deleted file mode 100644 index 58a13f6649..0000000000 --- a/base/mac/scoped_mach_vm.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 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. - -#ifndef BASE_MAC_SCOPED_MACH_VM_H_ -#define BASE_MAC_SCOPED_MACH_VM_H_ - -#include <mach/mach.h> -#include <stddef.h> - -#include <algorithm> - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" - -// Use ScopedMachVM to supervise ownership of pages in the current process -// through the Mach VM subsystem. Pages allocated with vm_allocate can be -// released when exiting a scope with ScopedMachVM. -// -// The Mach VM subsystem operates on a page-by-page basis, and a single VM -// allocation managed by a ScopedMachVM object may span multiple pages. As far -// as Mach is concerned, allocated pages may be deallocated individually. This -// is in contrast to higher-level allocators such as malloc, where the base -// address of an allocation implies the size of an allocated block. -// Consequently, it is not sufficient to just pass the base address of an -// allocation to ScopedMachVM, it also needs to know the size of the -// allocation. To avoid any confusion, both the base address and size must -// be page-aligned. -// -// When dealing with Mach VM, base addresses will naturally be page-aligned, -// but user-specified sizes may not be. If there's a concern that a size is -// not page-aligned, use the mach_vm_round_page macro to correct it. -// -// Example: -// -// vm_address_t address = 0; -// vm_size_t size = 12345; // This requested size is not page-aligned. -// kern_return_t kr = -// vm_allocate(mach_task_self(), &address, size, VM_FLAGS_ANYWHERE); -// if (kr != KERN_SUCCESS) { -// return false; -// } -// ScopedMachVM vm_owner(address, mach_vm_round_page(size)); - -namespace base { -namespace mac { - -class BASE_EXPORT ScopedMachVM { - public: - explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0) - : address_(address), size_(size) { - DCHECK_EQ(address % PAGE_SIZE, 0u); - DCHECK_EQ(size % PAGE_SIZE, 0u); - } - - ~ScopedMachVM() { - if (size_) { - vm_deallocate(mach_task_self(), address_, size_); - } - } - - void reset(vm_address_t address = 0, vm_size_t size = 0); - - vm_address_t address() const { - return address_; - } - - vm_size_t size() const { - return size_; - } - - void swap(ScopedMachVM& that) { - std::swap(address_, that.address_); - std::swap(size_, that.size_); - } - - void release() { - address_ = 0; - size_ = 0; - } - - private: - vm_address_t address_; - vm_size_t size_; - - DISALLOW_COPY_AND_ASSIGN(ScopedMachVM); -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_MACH_VM_H_ diff --git a/base/mac/scoped_nsautorelease_pool.h b/base/mac/scoped_nsautorelease_pool.h deleted file mode 100644 index 4d15e6da4c..0000000000 --- a/base/mac/scoped_nsautorelease_pool.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef BASE_MAC_SCOPED_NSAUTORELEASE_POOL_H_ -#define BASE_MAC_SCOPED_NSAUTORELEASE_POOL_H_ - -#include "base/base_export.h" -#include "base/macros.h" - -#if defined(__OBJC__) -@class NSAutoreleasePool; -#else // __OBJC__ -class NSAutoreleasePool; -#endif // __OBJC__ - -namespace base { -namespace mac { - -// ScopedNSAutoreleasePool allocates an NSAutoreleasePool when instantiated and -// sends it a -drain message when destroyed. This allows an autorelease pool to -// be maintained in ordinary C++ code without bringing in any direct Objective-C -// dependency. - -class BASE_EXPORT ScopedNSAutoreleasePool { - public: - ScopedNSAutoreleasePool(); - ~ScopedNSAutoreleasePool(); - - // Clear out the pool in case its position on the stack causes it to be - // alive for long periods of time (such as the entire length of the app). - // Only use then when you're certain the items currently in the pool are - // no longer needed. - void Recycle(); - private: - NSAutoreleasePool* autorelease_pool_; - - private: - DISALLOW_COPY_AND_ASSIGN(ScopedNSAutoreleasePool); -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_SCOPED_NSAUTORELEASE_POOL_H_ diff --git a/base/mac/scoped_nsautorelease_pool.mm b/base/mac/scoped_nsautorelease_pool.mm deleted file mode 100644 index e542ca86b2..0000000000 --- a/base/mac/scoped_nsautorelease_pool.mm +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2010 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. - -#include "base/mac/scoped_nsautorelease_pool.h" - -#import <Foundation/Foundation.h> - -#include "base/logging.h" - -namespace base { -namespace mac { - -ScopedNSAutoreleasePool::ScopedNSAutoreleasePool() - : autorelease_pool_([[NSAutoreleasePool alloc] init]) { - DCHECK(autorelease_pool_); -} - -ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() { - [autorelease_pool_ drain]; -} - -// Cycle the internal pool, allowing everything there to get cleaned up and -// start anew. -void ScopedNSAutoreleasePool::Recycle() { - [autorelease_pool_ drain]; - autorelease_pool_ = [[NSAutoreleasePool alloc] init]; - DCHECK(autorelease_pool_); -} - -} // namespace mac -} // namespace base diff --git a/base/mac/scoped_nsobject.h b/base/mac/scoped_nsobject.h deleted file mode 100644 index ecd8e78f9d..0000000000 --- a/base/mac/scoped_nsobject.h +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_MAC_SCOPED_NSOBJECT_H_ -#define BASE_MAC_SCOPED_NSOBJECT_H_ - -#include <type_traits> - -// Include NSObject.h directly because Foundation.h pulls in many dependencies. -// (Approx 100k lines of code versus 1.5k for NSObject.h). scoped_nsobject gets -// singled out because it is most typically included from other header files. -#import <Foundation/NSObject.h> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/mac/scoped_typeref.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -@class NSAutoreleasePool; -#endif - -namespace base { - -// scoped_nsobject<> is patterned after std::unique_ptr<>, but maintains -// ownership of an NSObject subclass object. Style deviations here are solely -// for compatibility with std::unique_ptr<>'s interface, with which everyone is -// already familiar. -// -// scoped_nsobject<> takes ownership of an object (in the constructor or in -// reset()) by taking over the caller's existing ownership claim. The caller -// must own the object it gives to scoped_nsobject<>, and relinquishes an -// ownership claim to that object. scoped_nsobject<> does not call -retain, -// callers have to call this manually if appropriate. -// -// scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used -// with protocols. -// -// scoped_nsobject<> is not to be used for NSAutoreleasePools. For -// NSAutoreleasePools use ScopedNSAutoreleasePool from -// scoped_nsautorelease_pool.h instead. -// We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile -// time with a template specialization (see below). -// -// If Automatic Reference Counting (aka ARC) is enabled then the ownership -// policy is not controllable by the user as ARC make it really difficult to -// transfer ownership (the reference passed to scoped_nsobject constructor is -// sunk by ARC and __attribute((ns_consumed)) appears to not work correctly -// with Objective-C++ see https://llvm.org/bugs/show_bug.cgi?id=27887). Due to -// that, the policy is always to |RETAIN| when using ARC. - -namespace internal { - -BASE_EXPORT id ScopedNSProtocolTraitsRetain(__unsafe_unretained id obj) - __attribute((ns_returns_not_retained)); -BASE_EXPORT id ScopedNSProtocolTraitsAutoRelease(__unsafe_unretained id obj) - __attribute((ns_returns_not_retained)); -BASE_EXPORT void ScopedNSProtocolTraitsRelease(__unsafe_unretained id obj); - -// Traits for ScopedTypeRef<>. As this class may be compiled from file with -// Automatic Reference Counting enable or not all methods have annotation to -// enforce the same code generation in both case (in particular, the Retain -// method uses ns_returns_not_retained to prevent ARC to insert a -release -// call on the returned value and thus defeating the -retain). -template <typename NST> -struct ScopedNSProtocolTraits { - static NST InvalidValue() __attribute((ns_returns_not_retained)) { - return nil; - } - static NST Retain(__unsafe_unretained NST nst) - __attribute((ns_returns_not_retained)) { - return ScopedNSProtocolTraitsRetain(nst); - } - static void Release(__unsafe_unretained NST nst) { - ScopedNSProtocolTraitsRelease(nst); - } -}; - -} // namespace internal - -template <typename NST> -class scoped_nsprotocol - : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> { - public: - using Traits = internal::ScopedNSProtocolTraits<NST>; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit scoped_nsprotocol( - NST object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : ScopedTypeRef<NST, Traits>(object, policy) {} -#else - explicit scoped_nsprotocol(NST object = Traits::InvalidValue()) - : ScopedTypeRef<NST, Traits>(object, base::scoped_policy::RETAIN) {} -#endif - - scoped_nsprotocol(const scoped_nsprotocol<NST>& that) - : ScopedTypeRef<NST, Traits>(that) {} - - template <typename NSR> - explicit scoped_nsprotocol(const scoped_nsprotocol<NSR>& that_as_subclass) - : ScopedTypeRef<NST, Traits>(that_as_subclass) {} - - scoped_nsprotocol(scoped_nsprotocol<NST>&& that) - : ScopedTypeRef<NST, Traits>(std::move(that)) {} - - scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) { - ScopedTypeRef<NST, Traits>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(NST object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - ScopedTypeRef<NST, Traits>::reset(object, policy); - } -#else - void reset(NST object = Traits::InvalidValue()) { - ScopedTypeRef<NST, Traits>::reset(object, base::scoped_policy::RETAIN); - } -#endif - - // Shift reference to the autorelease pool to be released later. - NST autorelease() __attribute((ns_returns_not_retained)) { - return internal::ScopedNSProtocolTraitsAutoRelease(this->release()); - } -}; - -// Free functions -template <class C> -void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) { - p1.swap(p2); -} - -template <class C> -bool operator==(C p1, const scoped_nsprotocol<C>& p2) { - return p1 == p2.get(); -} - -template <class C> -bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { - return p1 != p2.get(); -} - -template <typename NST> -class scoped_nsobject : public scoped_nsprotocol<NST*> { - public: - using Traits = typename scoped_nsprotocol<NST*>::Traits; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit scoped_nsobject( - NST* object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : scoped_nsprotocol<NST*>(object, policy) {} -#else - explicit scoped_nsobject(NST* object = Traits::InvalidValue()) - : scoped_nsprotocol<NST*>(object) {} -#endif - - scoped_nsobject(const scoped_nsobject<NST>& that) - : scoped_nsprotocol<NST*>(that) {} - - template <typename NSR> - explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass) - : scoped_nsprotocol<NST*>(that_as_subclass) {} - - scoped_nsobject(scoped_nsobject<NST>&& that) - : scoped_nsprotocol<NST*>(std::move(that)) {} - - scoped_nsobject& operator=(const scoped_nsobject<NST>& that) { - scoped_nsprotocol<NST*>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(NST* object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - scoped_nsprotocol<NST*>::reset(object, policy); - } -#else - void reset(NST* object = Traits::InvalidValue()) { - scoped_nsprotocol<NST*>::reset(object); - } -#endif - -#if !defined(__has_feature) || !__has_feature(objc_arc) - static_assert(std::is_same<NST, NSAutoreleasePool>::value == false, - "Use ScopedNSAutoreleasePool instead"); -#endif -}; - -// Specialization to make scoped_nsobject<id> work. -template<> -class scoped_nsobject<id> : public scoped_nsprotocol<id> { - public: - using Traits = typename scoped_nsprotocol<id>::Traits; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit scoped_nsobject( - id object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : scoped_nsprotocol<id>(object, policy) {} -#else - explicit scoped_nsobject(id object = Traits::InvalidValue()) - : scoped_nsprotocol<id>(object) {} -#endif - - scoped_nsobject(const scoped_nsobject<id>& that) - : scoped_nsprotocol<id>(that) {} - - template <typename NSR> - explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass) - : scoped_nsprotocol<id>(that_as_subclass) {} - - scoped_nsobject(scoped_nsobject<id>&& that) - : scoped_nsprotocol<id>(std::move(that)) {} - - scoped_nsobject& operator=(const scoped_nsobject<id>& that) { - scoped_nsprotocol<id>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(id object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - scoped_nsprotocol<id>::reset(object, policy); - } -#else - void reset(id object = Traits::InvalidValue()) { - scoped_nsprotocol<id>::reset(object); - } -#endif -}; - -} // namespace base - -#endif // BASE_MAC_SCOPED_NSOBJECT_H_ diff --git a/base/mac/scoped_typeref.h b/base/mac/scoped_typeref.h deleted file mode 100644 index b8d8a14262..0000000000 --- a/base/mac/scoped_typeref.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2014 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. - -#ifndef BASE_MAC_SCOPED_TYPEREF_H_ -#define BASE_MAC_SCOPED_TYPEREF_H_ - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/memory/scoped_policy.h" - -namespace base { - -// ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains ownership -// of a reference to any type that is maintained by Retain and Release methods. -// -// The Traits structure must provide the Retain and Release methods for type T. -// A default ScopedTypeRefTraits is used but not defined, and should be defined -// for each type to use this interface. For example, an appropriate definition -// of ScopedTypeRefTraits for CGLContextObj would be: -// -// template<> -// struct ScopedTypeRefTraits<CGLContextObj> { -// static CGLContextObj InvalidValue() { return nullptr; } -// static CGLContextObj Retain(CGLContextObj object) { -// CGLContextRetain(object); -// return object; -// } -// static void Release(CGLContextObj object) { CGLContextRelease(object); } -// }; -// -// For the many types that have pass-by-pointer create functions, the function -// InitializeInto() is provided to allow direct initialization and assumption -// of ownership of the object. For example, continuing to use the above -// CGLContextObj specialization: -// -// base::ScopedTypeRef<CGLContextObj> context; -// CGLCreateContext(pixel_format, share_group, context.InitializeInto()); -// -// For initialization with an existing object, the caller may specify whether -// the ScopedTypeRef<> being initialized is assuming the caller's existing -// ownership of the object (and should not call Retain in initialization) or if -// it should not assume this ownership and must create its own (by calling -// Retain in initialization). This behavior is based on the |policy| parameter, -// with |ASSUME| for the former and |RETAIN| for the latter. The default policy -// is to |ASSUME|. - -template<typename T> -struct ScopedTypeRefTraits; - -template<typename T, typename Traits = ScopedTypeRefTraits<T>> -class ScopedTypeRef { - public: - typedef T element_type; - - explicit ScopedTypeRef( - __unsafe_unretained T object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : object_(object) { - if (object_ && policy == base::scoped_policy::RETAIN) - object_ = Traits::Retain(object_); - } - - ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) - : object_(that.object_) { - if (object_) - object_ = Traits::Retain(object_); - } - - // This allows passing an object to a function that takes its superclass. - template <typename R, typename RTraits> - explicit ScopedTypeRef(const ScopedTypeRef<R, RTraits>& that_as_subclass) - : object_(that_as_subclass.get()) { - if (object_) - object_ = Traits::Retain(object_); - } - - ScopedTypeRef(ScopedTypeRef<T, Traits>&& that) : object_(that.object_) { - that.object_ = Traits::InvalidValue(); - } - - ~ScopedTypeRef() { - if (object_) - Traits::Release(object_); - } - - ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) { - reset(that.get(), base::scoped_policy::RETAIN); - return *this; - } - - // This is to be used only to take ownership of objects that are created - // by pass-by-pointer create functions. To enforce this, require that the - // object be reset to NULL before this may be used. - T* InitializeInto() WARN_UNUSED_RESULT { - DCHECK(!object_); - return &object_; - } - - void reset(__unsafe_unretained T object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - if (object && policy == base::scoped_policy::RETAIN) - object = Traits::Retain(object); - if (object_) - Traits::Release(object_); - object_ = object; - } - - bool operator==(__unsafe_unretained T that) const { return object_ == that; } - - bool operator!=(__unsafe_unretained T that) const { return object_ != that; } - - operator T() const __attribute((ns_returns_not_retained)) { return object_; } - - T get() const __attribute((ns_returns_not_retained)) { return object_; } - - void swap(ScopedTypeRef& that) { - __unsafe_unretained T temp = that.object_; - that.object_ = object_; - object_ = temp; - } - - // ScopedTypeRef<>::release() is like std::unique_ptr<>::release. It is NOT - // a wrapper for Release(). To force a ScopedTypeRef<> object to call - // Release(), use ScopedTypeRef<>::reset(). - T release() __attribute((ns_returns_not_retained)) WARN_UNUSED_RESULT { - __unsafe_unretained T temp = object_; - object_ = Traits::InvalidValue(); - return temp; - } - - private: - __unsafe_unretained T object_; -}; - -} // namespace base - -#endif // BASE_MAC_SCOPED_TYPEREF_H_ diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h deleted file mode 100644 index 0404d7d8fd..0000000000 --- a/base/mac/sdk_forward_declarations.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2012 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. - -// This file contains forward declarations for items in later SDKs than the -// default one with which Chromium is built (currently 10.10). -// If you call any function from this header, be sure to check at runtime for -// respondsToSelector: before calling these functions (else your code will crash -// on older OS X versions that chrome still supports). - -#ifndef BASE_MAC_SDK_FORWARD_DECLARATIONS_H_ -#define BASE_MAC_SDK_FORWARD_DECLARATIONS_H_ - -#import <AppKit/AppKit.h> -#import <CoreBluetooth/CoreBluetooth.h> -#import <CoreWLAN/CoreWLAN.h> -#import <IOBluetooth/IOBluetooth.h> -#import <ImageCaptureCore/ImageCaptureCore.h> -#import <QuartzCore/QuartzCore.h> -#include <stdint.h> - -#include "base/base_export.h" - -// ---------------------------------------------------------------------------- -// Define typedefs, enums, and protocols not available in the version of the -// OSX SDK being compiled against. -// ---------------------------------------------------------------------------- - -#if !defined(MAC_OS_X_VERSION_10_11) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11 - -enum { - NSPressureBehaviorUnknown = -1, - NSPressureBehaviorPrimaryDefault = 0, - NSPressureBehaviorPrimaryClick = 1, - NSPressureBehaviorPrimaryGeneric = 2, - NSPressureBehaviorPrimaryAccelerator = 3, - NSPressureBehaviorPrimaryDeepClick = 5, - NSPressureBehaviorPrimaryDeepDrag = 6 -}; -typedef NSInteger NSPressureBehavior; - -@interface NSPressureConfiguration : NSObject -- (instancetype)initWithPressureBehavior:(NSPressureBehavior)pressureBehavior; -@end - -enum { - NSSpringLoadingHighlightNone = 0, - NSSpringLoadingHighlightStandard, - NSSpringLoadingHighlightEmphasized -}; -typedef NSUInteger NSSpringLoadingHighlight; - -#endif // MAC_OS_X_VERSION_10_11 - -#if !defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 - -// The protocol was formalized by the 10.12 SDK, but it was informally used -// before. -@protocol CAAnimationDelegate -- (void)animationDidStart:(CAAnimation*)animation; -- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished; -@end - -@protocol CALayerDelegate -@end - -#endif // MAC_OS_X_VERSION_10_12 - -// ---------------------------------------------------------------------------- -// Define NSStrings only available in newer versions of the OSX SDK to force -// them to be statically linked. -// ---------------------------------------------------------------------------- - -extern "C" { -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 -BASE_EXPORT extern NSString* const CIDetectorTypeQRCode; -BASE_EXPORT extern NSString* const NSUserActivityTypeBrowsingWeb; -BASE_EXPORT extern NSString* const NSAppearanceNameVibrantDark; -BASE_EXPORT extern NSString* const NSAppearanceNameVibrantLight; -#endif // MAC_OS_X_VERSION_10_10 -} // extern "C" - -// ---------------------------------------------------------------------------- -// If compiling against an older version of the OSX SDK, declare classes and -// functions that are available in newer versions of the OSX SDK. If compiling -// against a newer version of the OSX SDK, redeclare those same classes and -// functions to suppress -Wpartial-availability warnings. -// ---------------------------------------------------------------------------- - -// Once Chrome no longer supports OSX 10.9, everything within this preprocessor -// block can be removed. -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 - -/* -@interface NSUserActivity (YosemiteSDK) -@property(readonly, copy) NSString* activityType; -@property(copy) NSDictionary* userInfo; -@property(copy) NSURL* webpageURL; -- (instancetype)initWithActivityType:(NSString*)activityType; -- (void)becomeCurrent; -- (void)invalidate; -@end -*/ - -@interface CBUUID (YosemiteSDK) -- (NSString*)UUIDString; -@end - -@interface NSViewController (YosemiteSDK) -- (void)viewDidLoad; -@end - -@interface NSWindow (YosemiteSDK) -- (void)setTitlebarAppearsTransparent:(BOOL)flag; -@end - -@interface NSProcessInfo (YosemiteSDK) -@property(readonly) NSOperatingSystemVersion operatingSystemVersion; -@end - -@interface NSLayoutConstraint (YosemiteSDK) -@property(getter=isActive) BOOL active; -+ (void)activateConstraints:(NSArray*)constraints; -@end - -@interface NSVisualEffectView (YosemiteSDK) -- (void)setState:(NSVisualEffectState)state; -@end - -@class NSVisualEffectView; - -@interface CIQRCodeFeature (YosemiteSDK) -@property(readonly) CGRect bounds; -@property(readonly) CGPoint topLeft; -@property(readonly) CGPoint topRight; -@property(readonly) CGPoint bottomLeft; -@property(readonly) CGPoint bottomRight; -@property(readonly, copy) NSString* messageString; -@end - -@class CIQRCodeFeature; - -@interface NSView (YosemiteSDK) -- (BOOL)isAccessibilitySelectorAllowed:(SEL)selector; -@end - -#endif // MAC_OS_X_VERSION_10_10 - -// Once Chrome no longer supports OSX 10.10.2, everything within this -// preprocessor block can be removed. -#if !defined(MAC_OS_X_VERSION_10_10_3) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10_3 - -@interface NSEvent (Yosemite_3_SDK) -@property(readonly) NSInteger stage; -@end - -@interface NSView (Yosemite_3_SDK) -- (void)setPressureConfiguration:(NSPressureConfiguration*)aConfiguration; -@end - -#endif // MAC_OS_X_VERSION_10_10 - -// ---------------------------------------------------------------------------- -// Define NSStrings only available in newer versions of the OSX SDK to force -// them to be statically linked. -// ---------------------------------------------------------------------------- - -extern "C" { -#if !defined(MAC_OS_X_VERSION_10_11) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 -BASE_EXPORT extern NSString* const CIDetectorTypeText; -#endif // MAC_OS_X_VERSION_10_11 -} // extern "C" - -// Once Chrome no longer supports OSX 10.10, everything within this -// preprocessor block can be removed. -#if !defined(MAC_OS_X_VERSION_10_11) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 - -@class NSLayoutDimension; -@class NSLayoutXAxisAnchor; -@class NSLayoutYAxisAnchor; - -@interface NSObject (ElCapitanSDK) -- (NSLayoutConstraint*)constraintEqualToConstant:(CGFloat)c; -@end - -@interface NSView (ElCapitanSDK) -@property(readonly, strong) NSLayoutXAxisAnchor* leftAnchor; -@property(readonly, strong) NSLayoutXAxisAnchor* rightAnchor; -@property(readonly, strong) NSLayoutYAxisAnchor* bottomAnchor; -@property(readonly, strong) NSLayoutDimension* widthAnchor; -@end - -@interface NSWindow (ElCapitanSDK) -- (void)performWindowDragWithEvent:(NSEvent*)event; -@end - -@interface CIRectangleFeature (ElCapitanSDK) -@property(readonly) CGRect bounds; -@end - -@class CIRectangleFeature; - -#endif // MAC_OS_X_VERSION_10_11 - -// Once Chrome no longer supports OSX 10.11, everything within this -// preprocessor block can be removed. -#if !defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 - -@interface NSWindow (SierraSDK) -@property(class) BOOL allowsAutomaticWindowTabbing; -@end - -#endif // MAC_OS_X_VERSION_10_12 - -// Once Chrome no longer supports OSX 10.12.0, everything within this -// preprocessor block can be removed. -#if !defined(MAC_OS_X_VERSION_10_12_1) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12_1 - -@interface NSButton (SierraPointOneSDK) -@property(copy) NSColor* bezelColor; -@property BOOL imageHugsTitle; -+ (instancetype)buttonWithTitle:(NSString*)title - target:(id)target - action:(SEL)action; -+ (instancetype)buttonWithImage:(NSImage*)image - target:(id)target - action:(SEL)action; -+ (instancetype)buttonWithTitle:(NSString*)title - image:(NSImage*)image - target:(id)target - action:(SEL)action; -@end - -@interface NSSegmentedControl (SierraPointOneSDK) -+ (instancetype)segmentedControlWithImages:(NSArray*)images - trackingMode:(NSSegmentSwitchTracking)trackingMode - target:(id)target - action:(SEL)action; -@end - -#endif // MAC_OS_X_VERSION_10_12_1 - -// ---------------------------------------------------------------------------- -// The symbol for kCWSSIDDidChangeNotification is available in the -// CoreWLAN.framework for OSX versions 10.6 through 10.10. The symbol is not -// declared in the OSX 10.9+ SDK, so when compiling against an OSX 10.9+ SDK, -// declare the symbol. -// ---------------------------------------------------------------------------- -BASE_EXPORT extern "C" NSString* const kCWSSIDDidChangeNotification; - -#endif // BASE_MAC_SDK_FORWARD_DECLARATIONS_H_ diff --git a/base/mac/sdk_forward_declarations.mm b/base/mac/sdk_forward_declarations.mm deleted file mode 100644 index c624daedd8..0000000000 --- a/base/mac/sdk_forward_declarations.mm +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 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. - -#include "base/mac/sdk_forward_declarations.h" - -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 -NSString* const CIDetectorTypeQRCode = @"CIDetectorTypeQRCode"; - -NSString* const NSUserActivityTypeBrowsingWeb = - @"NSUserActivityTypeBrowsingWeb"; - -NSString* const NSAppearanceNameVibrantDark = @"NSAppearanceNameVibrantDark"; -#endif // MAC_OS_X_VERSION_10_10 - -#if !defined(MAC_OS_X_VERSION_10_11) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 -NSString* const CIDetectorTypeText = @"CIDetectorTypeText"; -#endif // MAC_OS_X_VERSION_10_11 diff --git a/base/memory/shared_memory_handle_mac.cc b/base/memory/shared_memory_handle_mac.cc deleted file mode 100644 index 9dfd3c1aea..0000000000 --- a/base/memory/shared_memory_handle_mac.cc +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2015 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. - -#include "base/memory/shared_memory_handle.h" - -#include <mach/mach_vm.h> -#include <stddef.h> -#include <sys/mman.h> -#include <unistd.h> - -#include "base/mac/mac_util.h" -#include "base/mac/mach_logging.h" -#include "base/posix/eintr_wrapper.h" - -namespace base { - -SharedMemoryHandle::SharedMemoryHandle() - : type_(MACH), memory_object_(MACH_PORT_NULL) {} - -SharedMemoryHandle::SharedMemoryHandle( - const base::FileDescriptor& file_descriptor) - : type_(POSIX), file_descriptor_(file_descriptor) {} - -SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) { - type_ = MACH; - mach_port_t named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), - &size, - 0, // Address. - MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, - &named_right, - MACH_PORT_NULL); // Parent handle. - if (kr != KERN_SUCCESS) { - memory_object_ = MACH_PORT_NULL; - return; - } - - memory_object_ = named_right; - size_ = size; - pid_ = GetCurrentProcId(); - ownership_passes_to_ipc_ = false; -} - -SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object, - mach_vm_size_t size, - base::ProcessId pid) - : type_(MACH), - memory_object_(memory_object), - size_(size), - pid_(pid), - ownership_passes_to_ipc_(false) {} - -SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) { - CopyRelevantData(handle); -} - -SharedMemoryHandle& SharedMemoryHandle::operator=( - const SharedMemoryHandle& handle) { - if (this == &handle) - return *this; - - type_ = handle.type_; - CopyRelevantData(handle); - return *this; -} - -SharedMemoryHandle SharedMemoryHandle::Duplicate() const { - switch (type_) { - case POSIX: { - if (!IsValid()) - return SharedMemoryHandle(); - int duped_fd = HANDLE_EINTR(dup(file_descriptor_.fd)); - if (duped_fd < 0) - return SharedMemoryHandle(); - return SharedMemoryHandle(FileDescriptor(duped_fd, true)); - } - case MACH: { - if (!IsValid()) - return SharedMemoryHandle(MACH_PORT_NULL, 0, 0); - - // Increment the ref count. - kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_, - MACH_PORT_RIGHT_SEND, 1); - DCHECK_EQ(kr, KERN_SUCCESS); - SharedMemoryHandle handle(*this); - handle.SetOwnershipPassesToIPC(true); - return handle; - } - } -} - -bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { - if (!IsValid() && !handle.IsValid()) - return true; - - if (type_ != handle.type_) - return false; - - switch (type_) { - case POSIX: - return file_descriptor_.fd == handle.file_descriptor_.fd; - case MACH: - return memory_object_ == handle.memory_object_ && size_ == handle.size_ && - pid_ == handle.pid_; - } -} - -bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { - return !(*this == handle); -} - -bool SharedMemoryHandle::IsValid() const { - switch (type_) { - case POSIX: - return file_descriptor_.fd >= 0; - case MACH: - return memory_object_ != MACH_PORT_NULL; - } -} - -mach_port_t SharedMemoryHandle::GetMemoryObject() const { - DCHECK_EQ(type_, MACH); - return memory_object_; -} - -bool SharedMemoryHandle::GetSize(size_t* size) const { - if (!IsValid()) { - *size = 0; - return true; - } - - switch (type_) { - case SharedMemoryHandle::POSIX: - struct stat st; - if (fstat(file_descriptor_.fd, &st) != 0) - return false; - if (st.st_size < 0) - return false; - *size = st.st_size; - return true; - case SharedMemoryHandle::MACH: - *size = size_; - return true; - } -} - -bool SharedMemoryHandle::MapAt(off_t offset, - size_t bytes, - void** memory, - bool read_only) { - DCHECK(IsValid()); - switch (type_) { - case SharedMemoryHandle::POSIX: - *memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE), - MAP_SHARED, file_descriptor_.fd, offset); - return *memory != MAP_FAILED; - case SharedMemoryHandle::MACH: - DCHECK_EQ(pid_, GetCurrentProcId()); - kern_return_t kr = mach_vm_map( - mach_task_self(), - reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter - bytes, - 0, // Alignment mask - VM_FLAGS_ANYWHERE, - memory_object_, - offset, - FALSE, // Copy - VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection - VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection - VM_INHERIT_NONE); - return kr == KERN_SUCCESS; - } -} - -void SharedMemoryHandle::Close() const { - if (!IsValid()) - return; - - switch (type_) { - case POSIX: - if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0) - DPLOG(ERROR) << "Error closing fd"; - break; - case MACH: - kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_); - if (kr != KERN_SUCCESS) - MACH_DLOG(ERROR, kr) << "Error deallocating mach port"; - break; - } -} - -void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { - DCHECK_EQ(type_, MACH); - ownership_passes_to_ipc_ = ownership_passes; -} - -bool SharedMemoryHandle::OwnershipPassesToIPC() const { - DCHECK_EQ(type_, MACH); - return ownership_passes_to_ipc_; -} - -void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) { - type_ = handle.type_; - switch (type_) { - case POSIX: - file_descriptor_ = handle.file_descriptor_; - break; - case MACH: - memory_object_ = handle.memory_object_; - size_ = handle.size_; - pid_ = handle.pid_; - ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_; - break; - } -} - -} // namespace base diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc deleted file mode 100644 index c76d1626d6..0000000000 --- a/base/memory/shared_memory_mac.cc +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/memory/shared_memory.h" - -#include <errno.h> -#include <mach/mach_vm.h> -#include <stddef.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_mach_vm.h" -#include "base/memory/shared_memory_helper.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram_macros.h" -#include "base/posix/eintr_wrapper.h" -#include "base/posix/safe_strerror.h" -#include "base/process/process_metrics.h" -#include "base/scoped_generic.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "build/build_config.h" - -#if defined(OS_MACOSX) -#include "base/mac/foundation_util.h" -#endif // OS_MACOSX - -namespace base { - -namespace { - -// Returns whether the operation succeeded. -// |new_handle| is an output variable, populated on success. The caller takes -// ownership of the underlying memory object. -// |handle| is the handle to copy. -// If |handle| is already mapped, |mapped_addr| is its mapped location. -// Otherwise, |mapped_addr| should be |nullptr|. -bool MakeMachSharedMemoryHandleReadOnly(SharedMemoryHandle* new_handle, - SharedMemoryHandle handle, - void* mapped_addr) { - if (!handle.IsValid()) - return false; - - size_t size; - CHECK(handle.GetSize(&size)); - - // Map if necessary. - void* temp_addr = mapped_addr; - base::mac::ScopedMachVM scoper; - if (!temp_addr) { - // Intentionally lower current prot and max prot to |VM_PROT_READ|. - kern_return_t kr = mach_vm_map( - mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&temp_addr), - size, 0, VM_FLAGS_ANYWHERE, handle.GetMemoryObject(), 0, FALSE, - VM_PROT_READ, VM_PROT_READ, VM_INHERIT_NONE); - if (kr != KERN_SUCCESS) - return false; - scoper.reset(reinterpret_cast<vm_address_t>(temp_addr), - mach_vm_round_page(size)); - } - - // Make new memory object. - mach_port_t named_right; - kern_return_t kr = mach_make_memory_entry_64( - mach_task_self(), reinterpret_cast<memory_object_size_t*>(&size), - reinterpret_cast<memory_object_offset_t>(temp_addr), VM_PROT_READ, - &named_right, MACH_PORT_NULL); - if (kr != KERN_SUCCESS) - return false; - - *new_handle = SharedMemoryHandle(named_right, size, base::GetCurrentProcId()); - return true; -} - - -} // namespace - -SharedMemory::SharedMemory() - : mapped_memory_mechanism_(SharedMemoryHandle::MACH), - readonly_mapped_file_(-1), - mapped_size_(0), - memory_(NULL), - read_only_(false), - requested_size_(0) {} - -SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : shm_(handle), - mapped_memory_mechanism_(SharedMemoryHandle::POSIX), - readonly_mapped_file_(-1), - mapped_size_(0), - memory_(NULL), - read_only_(read_only), - requested_size_(0) {} - -SharedMemory::~SharedMemory() { - Unmap(); - Close(); -} - -// static -bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle.IsValid(); -} - -// static -SharedMemoryHandle SharedMemory::NULLHandle() { - return SharedMemoryHandle(); -} - -// static -void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - handle.Close(); -} - -// static -size_t SharedMemory::GetHandleLimit() { - return GetMaxFds(); -} - -// static -SharedMemoryHandle SharedMemory::DuplicateHandle( - const SharedMemoryHandle& handle) { - return handle.Duplicate(); -} - -// static -int SharedMemory::GetFdFromSharedMemoryHandle( - const SharedMemoryHandle& handle) { - return handle.file_descriptor_.fd; -} - -bool SharedMemory::CreateAndMapAnonymous(size_t size) { - return CreateAnonymous(size) && Map(size); -} - -// static -bool SharedMemory::GetSizeFromSharedMemoryHandle( - const SharedMemoryHandle& handle, - size_t* size) { - return handle.GetSize(size); -} - -// Chromium mostly only uses the unique/private shmem as specified by -// "name == L"". The exception is in the StatsTable. -bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { - DCHECK(!shm_.IsValid()); - if (options.size == 0) return false; - - if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - - if (options.type == SharedMemoryHandle::MACH) { - shm_ = SharedMemoryHandle(options.size); - requested_size_ = options.size; - return shm_.IsValid(); - } - - // This function theoretically can block on the disk. Both profiling of real - // users and local instrumentation shows that this is a real problem. - // https://code.google.com/p/chromium/issues/detail?id=466437 - base::ThreadRestrictions::ScopedAllowIO allow_io; - - ScopedFILE fp; - ScopedFD readonly_fd; - - FilePath path; - bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); - if (!result) - return false; - - if (!fp) { - PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; - return false; - } - - // Get current size. - struct stat stat; - if (fstat(fileno(fp.get()), &stat) != 0) - return false; - const size_t current_size = stat.st_size; - if (current_size != options.size) { - if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) - return false; - } - requested_size_ = options.size; - - int mapped_file = -1; - result = PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, - &readonly_mapped_file_); - - shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false)); - return result; -} - -bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) - return false; - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) - return false; - if (memory_) - return false; - - bool success = shm_.MapAt(offset, bytes, &memory_, read_only_); - if (success) { - mapped_size_ = bytes; - DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & - (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); - mapped_memory_mechanism_ = shm_.type_; - } else { - memory_ = NULL; - } - - return success; -} - -bool SharedMemory::Unmap() { - if (memory_ == NULL) - return false; - - switch (mapped_memory_mechanism_) { - case SharedMemoryHandle::POSIX: - munmap(memory_, mapped_size_); - break; - case SharedMemoryHandle::MACH: - mach_vm_deallocate(mach_task_self(), - reinterpret_cast<mach_vm_address_t>(memory_), - mapped_size_); - break; - } - - memory_ = NULL; - mapped_size_ = 0; - return true; -} - -SharedMemoryHandle SharedMemory::handle() const { - switch (shm_.type_) { - case SharedMemoryHandle::POSIX: - return SharedMemoryHandle( - FileDescriptor(shm_.file_descriptor_.fd, false)); - case SharedMemoryHandle::MACH: - return shm_; - } -} - -SharedMemoryHandle SharedMemory::TakeHandle() { - SharedMemoryHandle dup = DuplicateHandle(handle()); - Close(); - return dup; -} - -void SharedMemory::Close() { - shm_.Close(); - shm_ = SharedMemoryHandle(); - if (shm_.type_ == SharedMemoryHandle::POSIX) { - if (readonly_mapped_file_ > 0) { - if (IGNORE_EINTR(close(readonly_mapped_file_)) < 0) - PLOG(ERROR) << "close"; - readonly_mapped_file_ = -1; - } - } -} - -bool SharedMemory::Share(SharedMemoryHandle* new_handle, ShareMode share_mode) { - if (shm_.type_ == SharedMemoryHandle::MACH) { - DCHECK(shm_.IsValid()); - - bool success = false; - switch (share_mode) { - case SHARE_CURRENT_MODE: - *new_handle = shm_.Duplicate(); - success = true; - break; - case SHARE_READONLY: - success = MakeMachSharedMemoryHandleReadOnly(new_handle, shm_, memory_); - break; - } - - if (success) - new_handle->SetOwnershipPassesToIPC(true); - - return success; - } - - int handle_to_dup = -1; - switch (share_mode) { - case SHARE_CURRENT_MODE: - handle_to_dup = shm_.file_descriptor_.fd; - break; - case SHARE_READONLY: - // We could imagine re-opening the file from /dev/fd, but that can't make - // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10 - CHECK_GE(readonly_mapped_file_, 0); - handle_to_dup = readonly_mapped_file_; - break; - } - - const int new_fd = HANDLE_EINTR(dup(handle_to_dup)); - if (new_fd < 0) { - DPLOG(ERROR) << "dup() failed."; - return false; - } - - new_handle->file_descriptor_.fd = new_fd; - new_handle->type_ = SharedMemoryHandle::POSIX; - - return true; -} - -bool SharedMemory::ShareToProcessCommon(ProcessHandle process, - SharedMemoryHandle* new_handle, - bool close_self, - ShareMode share_mode) { - ALLOW_UNUSED_PARAM(process); - bool success = Share(new_handle, share_mode); - if (close_self) { - Unmap(); - Close(); - } - return success; -} - -} // namespace base diff --git a/base/memory/shared_memory_mac_unittest.cc b/base/memory/shared_memory_mac_unittest.cc deleted file mode 100644 index 4ccee89deb..0000000000 --- a/base/memory/shared_memory_mac_unittest.cc +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright 2015 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. - -#include <mach/mach.h> -#include <mach/mach_vm.h> -#include <servers/bootstrap.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/command_line.h" -#include "base/mac/mac_util.h" -#include "base/mac/mach_logging.h" -#include "base/mac/scoped_mach_port.h" -#include "base/macros.h" -#include "base/memory/shared_memory.h" -#include "base/process/process_handle.h" -#include "base/rand_util.h" -#include "base/strings/stringprintf.h" -#include "base/sys_info.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_timeouts.h" -#include "testing/multiprocess_func_list.h" - -namespace base { - -namespace { - -// Gets the current and maximum protection levels of the memory region. -// Returns whether the operation was successful. -// |current| and |max| are output variables only populated on success. -bool GetProtections(void* address, size_t size, int* current, int* max) { - vm_region_info_t region_info; - mach_vm_address_t mem_address = reinterpret_cast<mach_vm_address_t>(address); - mach_vm_size_t mem_size = size; - vm_region_basic_info_64 basic_info; - - region_info = reinterpret_cast<vm_region_recurse_info_t>(&basic_info); - vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64; - memory_object_name_t memory_object; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - - kern_return_t kr = - mach_vm_region(mach_task_self(), &mem_address, &mem_size, flavor, - region_info, &count, &memory_object); - if (kr != KERN_SUCCESS) { - MACH_LOG(ERROR, kr) << "Failed to get region info."; - return false; - } - - *current = basic_info.protection; - *max = basic_info.max_protection; - return true; -} - -// Creates a new SharedMemory with the given |size|, filled with 'a'. -std::unique_ptr<SharedMemory> CreateSharedMemory(int size) { - SharedMemoryHandle shm(size); - if (!shm.IsValid()) { - LOG(ERROR) << "Failed to make SharedMemoryHandle"; - return nullptr; - } - std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); - shared_memory->Map(size); - memset(shared_memory->memory(), 'a', size); - return shared_memory; -} - -static const std::string g_service_switch_name = "service_name"; - -// Structs used to pass a mach port from client to server. -struct MachSendPortMessage { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_port_descriptor_t data; -}; -struct MachReceivePortMessage { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_port_descriptor_t data; - mach_msg_trailer_t trailer; -}; - -// Makes the current process into a Mach Server with the given |service_name|. -mach_port_t BecomeMachServer(const char* service_name) { - mach_port_t port; - kern_return_t kr = bootstrap_check_in(bootstrap_port, service_name, &port); - MACH_CHECK(kr == KERN_SUCCESS, kr) << "BecomeMachServer"; - return port; -} - -// Returns the mach port for the Mach Server with the given |service_name|. -mach_port_t LookupServer(const char* service_name) { - mach_port_t server_port; - kern_return_t kr = - bootstrap_look_up(bootstrap_port, service_name, &server_port); - MACH_CHECK(kr == KERN_SUCCESS, kr) << "LookupServer"; - return server_port; -} - -mach_port_t MakeReceivingPort() { - mach_port_t client_port; - kern_return_t kr = - mach_port_allocate(mach_task_self(), // our task is acquiring - MACH_PORT_RIGHT_RECEIVE, // a new receive right - &client_port); // with this name - MACH_CHECK(kr == KERN_SUCCESS, kr) << "MakeReceivingPort"; - return client_port; -} - -// Blocks until a mach message is sent to |server_port|. This mach message -// must contain a mach port. Returns that mach port. -mach_port_t ReceiveMachPort(mach_port_t port_to_listen_on) { - MachReceivePortMessage recv_msg; - mach_msg_header_t* recv_hdr = &(recv_msg.header); - recv_hdr->msgh_local_port = port_to_listen_on; - recv_hdr->msgh_size = sizeof(recv_msg); - kern_return_t kr = - mach_msg(recv_hdr, // message buffer - MACH_RCV_MSG, // option indicating service - 0, // send size - recv_hdr->msgh_size, // size of header + body - port_to_listen_on, // receive name - MACH_MSG_TIMEOUT_NONE, // no timeout, wait forever - MACH_PORT_NULL); // no notification port - MACH_CHECK(kr == KERN_SUCCESS, kr) << "ReceiveMachPort"; - mach_port_t other_task_port = recv_msg.data.name; - return other_task_port; -} - -// Passes a copy of the send right of |port_to_send| to |receiving_port|. -void SendMachPort(mach_port_t receiving_port, - mach_port_t port_to_send, - int disposition) { - MachSendPortMessage send_msg; - mach_msg_header_t* send_hdr; - send_hdr = &(send_msg.header); - send_hdr->msgh_bits = - MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX; - send_hdr->msgh_size = sizeof(send_msg); - send_hdr->msgh_remote_port = receiving_port; - send_hdr->msgh_local_port = MACH_PORT_NULL; - send_hdr->msgh_reserved = 0; - send_hdr->msgh_id = 0; - send_msg.body.msgh_descriptor_count = 1; - send_msg.data.name = port_to_send; - send_msg.data.disposition = disposition; - send_msg.data.type = MACH_MSG_PORT_DESCRIPTOR; - int kr = mach_msg(send_hdr, // message buffer - MACH_SEND_MSG, // option indicating send - send_hdr->msgh_size, // size of header + body - 0, // receive limit - MACH_PORT_NULL, // receive name - MACH_MSG_TIMEOUT_NONE, // no timeout, wait forever - MACH_PORT_NULL); // no notification port - MACH_CHECK(kr == KERN_SUCCESS, kr) << "SendMachPort"; -} - -std::string CreateRandomServiceName() { - return StringPrintf("SharedMemoryMacMultiProcessTest.%llu", RandUint64()); -} - -// Sets up the mach communication ports with the server. Returns a port to which -// the server will send mach objects. -mach_port_t CommonChildProcessSetUp() { - CommandLine cmd_line = *CommandLine::ForCurrentProcess(); - std::string service_name = - cmd_line.GetSwitchValueASCII(g_service_switch_name); - mac::ScopedMachSendRight server_port(LookupServer(service_name.c_str())); - mach_port_t client_port = MakeReceivingPort(); - - // Send the port that this process is listening on to the server. - SendMachPort(server_port.get(), client_port, MACH_MSG_TYPE_MAKE_SEND); - return client_port; -} - -// The number of active names in the current task's port name space. -mach_msg_type_number_t GetActiveNameCount() { - mach_port_name_array_t name_array; - mach_msg_type_number_t names_count; - mach_port_type_array_t type_array; - mach_msg_type_number_t types_count; - kern_return_t kr = mach_port_names(mach_task_self(), &name_array, - &names_count, &type_array, &types_count); - MACH_CHECK(kr == KERN_SUCCESS, kr) << "GetActiveNameCount"; - return names_count; -} - -} // namespace - -class SharedMemoryMacMultiProcessTest : public MultiProcessTest { - public: - SharedMemoryMacMultiProcessTest() {} - - CommandLine MakeCmdLine(const std::string& procname) override { - CommandLine command_line = MultiProcessTest::MakeCmdLine(procname); - // Pass the service name to the child process. - command_line.AppendSwitchASCII(g_service_switch_name, service_name_); - return command_line; - } - - void SetUpChild(const std::string& name) { - // Make a random service name so that this test doesn't conflict with other - // similar tests. - service_name_ = CreateRandomServiceName(); - server_port_.reset(BecomeMachServer(service_name_.c_str())); - spawn_child_ = SpawnChild(name); - client_port_.reset(ReceiveMachPort(server_port_.get())); - } - - static const int s_memory_size = 99999; - - protected: - std::string service_name_; - - // A port on which the main process listens for mach messages from the child - // process. - mac::ScopedMachReceiveRight server_port_; - - // A port on which the child process listens for mach messages from the main - // process. - mac::ScopedMachSendRight client_port_; - - base::SpawnChildResult spawn_child_; - DISALLOW_COPY_AND_ASSIGN(SharedMemoryMacMultiProcessTest); -}; - -// Tests that content written to shared memory in the server process can be read -// by the child process. -TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) { - SetUpChild("MachBasedSharedMemoryClient"); - - std::unique_ptr<SharedMemory> shared_memory( - CreateSharedMemory(s_memory_size)); - - // Send the underlying memory object to the client process. - SendMachPort(client_port_.get(), shared_memory->handle().GetMemoryObject(), - MACH_MSG_TYPE_COPY_SEND); - int rv = -1; - ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( - TestTimeouts::action_timeout(), &rv)); - EXPECT_EQ(0, rv); -} - -MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) { - mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); - // The next mach port should be for a memory object. - mach_port_t memory_object = ReceiveMachPort(client_port.get()); - SharedMemoryHandle shm(memory_object, - SharedMemoryMacMultiProcessTest::s_memory_size, - GetCurrentProcId()); - SharedMemory shared_memory(shm, false); - shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size); - const char* start = static_cast<const char*>(shared_memory.memory()); - for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) { - DCHECK_EQ(start[i], 'a'); - } - return 0; -} - -// Tests that mapping shared memory with an offset works correctly. -TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) { - SetUpChild("MachBasedSharedMemoryWithOffsetClient"); - - SharedMemoryHandle shm(s_memory_size); - ASSERT_TRUE(shm.IsValid()); - SharedMemory shared_memory(shm, false); - shared_memory.Map(s_memory_size); - - size_t page_size = SysInfo::VMAllocationGranularity(); - char* start = static_cast<char*>(shared_memory.memory()); - memset(start, 'a', page_size); - memset(start + page_size, 'b', page_size); - memset(start + 2 * page_size, 'c', page_size); - - // Send the underlying memory object to the client process. - SendMachPort( - client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND); - int rv = -1; - ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( - TestTimeouts::action_timeout(), &rv)); - EXPECT_EQ(0, rv); -} - -MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryWithOffsetClient) { - mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); - // The next mach port should be for a memory object. - mach_port_t memory_object = ReceiveMachPort(client_port.get()); - SharedMemoryHandle shm(memory_object, - SharedMemoryMacMultiProcessTest::s_memory_size, - GetCurrentProcId()); - SharedMemory shared_memory(shm, false); - size_t page_size = SysInfo::VMAllocationGranularity(); - shared_memory.MapAt(page_size, 2 * page_size); - const char* start = static_cast<const char*>(shared_memory.memory()); - for (size_t i = 0; i < page_size; ++i) { - DCHECK_EQ(start[i], 'b'); - } - for (size_t i = page_size; i < 2 * page_size; ++i) { - DCHECK_EQ(start[i], 'c'); - } - return 0; -} - -// Tests that duplication and closing has the right effect on Mach reference -// counts. -TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) { - mach_msg_type_number_t active_name_count = GetActiveNameCount(); - - // Making a new SharedMemoryHandle increments the name count. - SharedMemoryHandle shm(s_memory_size); - ASSERT_TRUE(shm.IsValid()); - EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); - - // Duplicating the SharedMemoryHandle increments the ref count, but doesn't - // make a new name. - shm.Duplicate(); - EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); - - // Closing the SharedMemoryHandle decrements the ref count. The first time has - // no effect. - shm.Close(); - EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); - - // Closing the SharedMemoryHandle decrements the ref count. The second time - // destroys the port. - shm.Close(); - EXPECT_EQ(active_name_count, GetActiveNameCount()); -} - -// Tests that Mach shared memory can be mapped and unmapped. -TEST_F(SharedMemoryMacMultiProcessTest, MachUnmapMap) { - mach_msg_type_number_t active_name_count = GetActiveNameCount(); - - std::unique_ptr<SharedMemory> shared_memory = - CreateSharedMemory(s_memory_size); - ASSERT_TRUE(shared_memory->Unmap()); - ASSERT_TRUE(shared_memory->Map(s_memory_size)); - shared_memory.reset(); - EXPECT_EQ(active_name_count, GetActiveNameCount()); -} - -// Tests that passing a SharedMemoryHandle to a SharedMemory object also passes -// ownership, and that destroying the SharedMemory closes the SharedMemoryHandle -// as well. -TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) { - mach_msg_type_number_t active_name_count = GetActiveNameCount(); - - // Making a new SharedMemoryHandle increments the name count. - SharedMemoryHandle shm(s_memory_size); - ASSERT_TRUE(shm.IsValid()); - EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); - - // Name count doesn't change when mapping the memory. - std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); - shared_memory->Map(s_memory_size); - EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); - - // Destroying the SharedMemory object frees the resource. - shared_memory.reset(); - EXPECT_EQ(active_name_count, GetActiveNameCount()); -} - -// Tests that the read-only flag works. -TEST_F(SharedMemoryMacMultiProcessTest, MachReadOnly) { - std::unique_ptr<SharedMemory> shared_memory( - CreateSharedMemory(s_memory_size)); - - SharedMemoryHandle shm2 = shared_memory->handle().Duplicate(); - ASSERT_TRUE(shm2.IsValid()); - SharedMemory shared_memory2(shm2, true); - shared_memory2.Map(s_memory_size); - ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), ""); -} - -// Tests that the method ShareToProcess() works. -TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcess) { - mach_msg_type_number_t active_name_count = GetActiveNameCount(); - - { - std::unique_ptr<SharedMemory> shared_memory( - CreateSharedMemory(s_memory_size)); - - SharedMemoryHandle shm2; - ASSERT_TRUE(shared_memory->ShareToProcess(GetCurrentProcId(), &shm2)); - ASSERT_TRUE(shm2.IsValid()); - SharedMemory shared_memory2(shm2, true); - shared_memory2.Map(s_memory_size); - - ASSERT_EQ(0, memcmp(shared_memory->memory(), shared_memory2.memory(), - s_memory_size)); - } - - EXPECT_EQ(active_name_count, GetActiveNameCount()); -} - -// Tests that the method ShareReadOnlyToProcess() creates a memory object that -// is read only. -TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonly) { - std::unique_ptr<SharedMemory> shared_memory( - CreateSharedMemory(s_memory_size)); - - // Check the protection levels. - int current_prot, max_prot; - ASSERT_TRUE(GetProtections(shared_memory->memory(), - shared_memory->mapped_size(), ¤t_prot, - &max_prot)); - ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot); - ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot); - - // Make a new memory object. - SharedMemoryHandle shm2; - ASSERT_TRUE(shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2)); - ASSERT_TRUE(shm2.IsValid()); - - // Mapping with |readonly| set to |false| should fail. - SharedMemory shared_memory2(shm2, false); - shared_memory2.Map(s_memory_size); - ASSERT_EQ(nullptr, shared_memory2.memory()); - - // Now trying mapping with |readonly| set to |true|. - SharedMemory shared_memory3(shm2.Duplicate(), true); - shared_memory3.Map(s_memory_size); - ASSERT_NE(nullptr, shared_memory3.memory()); - - // Check the protection levels. - ASSERT_TRUE(GetProtections(shared_memory3.memory(), - shared_memory3.mapped_size(), ¤t_prot, - &max_prot)); - ASSERT_EQ(VM_PROT_READ, current_prot); - ASSERT_EQ(VM_PROT_READ, max_prot); - - // The memory should still be readonly, since the underlying memory object - // is readonly. - ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), ""); -} - -// Tests that the method ShareReadOnlyToProcess() doesn't leak. -TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonlyLeak) { - mach_msg_type_number_t active_name_count = GetActiveNameCount(); - - { - std::unique_ptr<SharedMemory> shared_memory( - CreateSharedMemory(s_memory_size)); - - SharedMemoryHandle shm2; - ASSERT_TRUE( - shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2)); - ASSERT_TRUE(shm2.IsValid()); - - // Intentionally map with |readonly| set to |false|. - SharedMemory shared_memory2(shm2, false); - shared_memory2.Map(s_memory_size); - } - - EXPECT_EQ(active_name_count, GetActiveNameCount()); -} - -} // namespace base diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h deleted file mode 100644 index f0766eb860..0000000000 --- a/base/message_loop/message_pump_mac.h +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) 2012 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. - -// The basis for all native run loops on the Mac is the CFRunLoop. It can be -// used directly, it can be used as the driving force behind the similar -// Foundation NSRunLoop, and it can be used to implement higher-level event -// loops such as the NSApplication event loop. -// -// This file introduces a basic CFRunLoop-based implementation of the -// MessagePump interface called CFRunLoopBase. CFRunLoopBase contains all -// of the machinery necessary to dispatch events to a delegate, but does not -// implement the specific run loop. Concrete subclasses must provide their -// own DoRun and Quit implementations. -// -// A concrete subclass that just runs a CFRunLoop loop is provided in -// MessagePumpCFRunLoop. For an NSRunLoop, the similar MessagePumpNSRunLoop -// is provided. -// -// For the application's event loop, an implementation based on AppKit's -// NSApplication event system is provided in MessagePumpNSApplication. -// -// Typically, MessagePumpNSApplication only makes sense on a Cocoa -// application's main thread. If a CFRunLoop-based message pump is needed on -// any other thread, one of the other concrete subclasses is preferable. -// MessagePumpMac::Create is defined, which returns a new NSApplication-based -// or NSRunLoop-based MessagePump subclass depending on which thread it is -// called on. - -#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_MAC_H_ -#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_MAC_H_ - -#include "base/message_loop/message_pump.h" - - -#include <CoreFoundation/CoreFoundation.h> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/timer_slack.h" -#include "build/build_config.h" - -#if defined(__OBJC__) -#if defined(OS_IOS) -#import <Foundation/Foundation.h> -#else -#import <AppKit/AppKit.h> - -// Clients must subclass NSApplication and implement this protocol if they use -// MessagePumpMac. -@protocol CrAppProtocol -// Must return true if -[NSApplication sendEvent:] is currently on the stack. -// See the comment for |CreateAutoreleasePool()| in the cc file for why this is -// necessary. -- (BOOL)isHandlingSendEvent; -@end -#endif // !defined(OS_IOS) -#endif // defined(__OBJC__) - -namespace base { - -class RunLoop; -class TimeTicks; - -// AutoreleasePoolType is a proxy type for autorelease pools. Its definition -// depends on the translation unit (TU) in which this header appears. In pure -// C++ TUs, it is defined as a forward C++ class declaration (that is never -// defined), because autorelease pools are an Objective-C concept. In Automatic -// Reference Counting (ARC) Objective-C TUs, it is similarly defined as a -// forward C++ class declaration, because clang will not allow the type -// "NSAutoreleasePool" in such TUs. Finally, in Manual Retain Release (MRR) -// Objective-C TUs, it is a type alias for NSAutoreleasePool. In all cases, a -// method that takes or returns an NSAutoreleasePool* can use -// AutoreleasePoolType* instead. -#if !defined(__OBJC__) || __has_feature(objc_arc) -class AutoreleasePoolType; -#else // !defined(__OBJC__) || __has_feature(objc_arc) -typedef NSAutoreleasePool AutoreleasePoolType; -#endif // !defined(__OBJC__) || __has_feature(objc_arc) - -class BASE_EXPORT MessagePumpCFRunLoopBase : public MessagePump { - // Needs access to CreateAutoreleasePool. - friend class MessagePumpScopedAutoreleasePool; - friend class TestMessagePumpCFRunLoopBase; - - public: - MessagePumpCFRunLoopBase(); - ~MessagePumpCFRunLoopBase() override; - - // Subclasses should implement the work they need to do in MessagePump::Run - // in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly. - // This arrangement is used because MessagePumpCFRunLoopBase needs to set - // up and tear down things before and after the "meat" of DoRun. - void Run(Delegate* delegate) override; - virtual void DoRun(Delegate* delegate) = 0; - - void ScheduleWork() override; - void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; - void SetTimerSlack(TimerSlack timer_slack) override; - - protected: - // Accessors for private data members to be used by subclasses. - CFRunLoopRef run_loop() const { return run_loop_; } - int nesting_level() const { return nesting_level_; } - int run_nesting_level() const { return run_nesting_level_; } - - // Sets this pump's delegate. Signals the appropriate sources if - // |delegateless_work_| is true. |delegate| can be NULL. - void SetDelegate(Delegate* delegate); - - // Return an autorelease pool to wrap around any work being performed. - // In some cases, CreateAutoreleasePool may return nil intentionally to - // preventing an autorelease pool from being created, allowing any - // objects autoreleased by work to fall into the current autorelease pool. - virtual AutoreleasePoolType* CreateAutoreleasePool(); - - private: - // Marking timers as invalid at the right time helps significantly reduce - // power use (see the comment in RunDelayedWorkTimer()), however there is no - // public API for doing so. CFRuntime.h states that CFRuntimeBase, upon which - // the above timer invalidation functions are based, can change from release - // to release and should not be accessed directly (this struct last changed at - // least in 2008 in CF-476). - // - // This function uses private API to modify a test timer's valid state and - // uses public API to confirm that the private API changed the right bit. - static bool CanInvalidateCFRunLoopTimers(); - - // Sets a Core Foundation object's "invalid" bit to |valid|. Based on code - // from CFRunLoop.c. - static void ChromeCFRunLoopTimerSetValid(CFRunLoopTimerRef timer, bool valid); - - // Timer callback scheduled by ScheduleDelayedWork. This does not do any - // work, but it signals work_source_ so that delayed work can be performed - // within the appropriate priority constraints. - static void RunDelayedWorkTimer(CFRunLoopTimerRef timer, void* info); - - // Perform highest-priority work. This is associated with work_source_ - // signalled by ScheduleWork or RunDelayedWorkTimer. The static method calls - // the instance method; the instance method returns true if it resignalled - // work_source_ to be called again from the loop. - static void RunWorkSource(void* info); - bool RunWork(); - - // Perform idle-priority work. This is normally called by PreWaitObserver, - // but is also associated with idle_work_source_. When this function - // actually does perform idle work, it will resignal that source. The - // static method calls the instance method; the instance method returns - // true if idle work was done. - static void RunIdleWorkSource(void* info); - bool RunIdleWork(); - - // Perform work that may have been deferred because it was not runnable - // within a nested run loop. This is associated with - // nesting_deferred_work_source_ and is signalled by - // MaybeScheduleNestingDeferredWork when returning from a nested loop, - // so that an outer loop will be able to perform the necessary tasks if it - // permits nestable tasks. - static void RunNestingDeferredWorkSource(void* info); - bool RunNestingDeferredWork(); - - // Schedules possible nesting-deferred work to be processed before the run - // loop goes to sleep, exits, or begins processing sources at the top of its - // loop. If this function detects that a nested loop had run since the - // previous attempt to schedule nesting-deferred work, it will schedule a - // call to RunNestingDeferredWorkSource. - void MaybeScheduleNestingDeferredWork(); - - // Observer callback responsible for performing idle-priority work, before - // the run loop goes to sleep. Associated with idle_work_observer_. - static void PreWaitObserver(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void* info); - - // Observer callback called before the run loop processes any sources. - // Associated with pre_source_observer_. - static void PreSourceObserver(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void* info); - - // Observer callback called when the run loop starts and stops, at the - // beginning and end of calls to CFRunLoopRun. This is used to maintain - // nesting_level_. Associated with enter_exit_observer_. - static void EnterExitObserver(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void* info); - - // Called by EnterExitObserver after performing maintenance on nesting_level_. - // This allows subclasses an opportunity to perform additional processing on - // the basis of run loops starting and stopping. - virtual void EnterExitRunLoop(CFRunLoopActivity activity); - - // The thread's run loop. - CFRunLoopRef run_loop_; - - // The timer, sources, and observers are described above alongside their - // callbacks. - CFRunLoopTimerRef delayed_work_timer_; - CFRunLoopSourceRef work_source_; - CFRunLoopSourceRef idle_work_source_; - CFRunLoopSourceRef nesting_deferred_work_source_; - CFRunLoopObserverRef pre_wait_observer_; - CFRunLoopObserverRef pre_source_observer_; - CFRunLoopObserverRef enter_exit_observer_; - - // (weak) Delegate passed as an argument to the innermost Run call. - Delegate* delegate_; - - // The time that delayed_work_timer_ is scheduled to fire. This is tracked - // independently of CFRunLoopTimerGetNextFireDate(delayed_work_timer_) - // to be able to reset the timer properly after waking from system sleep. - // See PowerStateNotification. - CFAbsoluteTime delayed_work_fire_time_; - - base::TimerSlack timer_slack_; - - // The recursion depth of the currently-executing CFRunLoopRun loop on the - // run loop's thread. 0 if no run loops are running inside of whatever scope - // the object was created in. - int nesting_level_; - - // The recursion depth (calculated in the same way as nesting_level_) of the - // innermost executing CFRunLoopRun loop started by a call to Run. - int run_nesting_level_; - - // The deepest (numerically highest) recursion depth encountered since the - // most recent attempt to run nesting-deferred work. - int deepest_nesting_level_; - - // "Delegateless" work flags are set when work is ready to be performed but - // must wait until a delegate is available to process it. This can happen - // when a MessagePumpCFRunLoopBase is instantiated and work arrives without - // any call to Run on the stack. The Run method will check for delegateless - // work on entry and redispatch it as needed once a delegate is available. - bool delegateless_work_; - bool delegateless_idle_work_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); -}; - -class BASE_EXPORT MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase { - public: - MessagePumpCFRunLoop(); - ~MessagePumpCFRunLoop() override; - - void DoRun(Delegate* delegate) override; - void Quit() override; - - private: - void EnterExitRunLoop(CFRunLoopActivity activity) override; - - // True if Quit is called to stop the innermost MessagePump - // (innermost_quittable_) but some other CFRunLoopRun loop (nesting_level_) - // is running inside the MessagePump's innermost Run call. - bool quit_pending_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoop); -}; - -class BASE_EXPORT MessagePumpNSRunLoop : public MessagePumpCFRunLoopBase { - public: - MessagePumpNSRunLoop(); - ~MessagePumpNSRunLoop() override; - - void DoRun(Delegate* delegate) override; - void Quit() override; - - private: - // A source that doesn't do anything but provide something signalable - // attached to the run loop. This source will be signalled when Quit - // is called, to cause the loop to wake up so that it can stop. - CFRunLoopSourceRef quit_source_; - - // False after Quit is called. - bool keep_running_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpNSRunLoop); -}; - -#if defined(OS_IOS) -// This is a fake message pump. It attaches sources to the main thread's -// CFRunLoop, so PostTask() will work, but it is unable to drive the loop -// directly, so calling Run() or Quit() are errors. -class MessagePumpUIApplication : public MessagePumpCFRunLoopBase { - public: - MessagePumpUIApplication(); - ~MessagePumpUIApplication() override; - void DoRun(Delegate* delegate) override; - void Quit() override; - - // This message pump can not spin the main message loop directly. Instead, - // call |Attach()| to set up a delegate. It is an error to call |Run()|. - virtual void Attach(Delegate* delegate); - - private: - RunLoop* run_loop_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpUIApplication); -}; - -#else - -class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { - public: - MessagePumpNSApplication(); - ~MessagePumpNSApplication() override; - - void DoRun(Delegate* delegate) override; - void Quit() override; - - private: - // False after Quit is called. - bool keep_running_; - - // True if DoRun is managing its own run loop as opposed to letting - // -[NSApplication run] handle it. The outermost run loop in the application - // is managed by -[NSApplication run], inner run loops are handled by a loop - // in DoRun. - bool running_own_loop_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpNSApplication); -}; - -class MessagePumpCrApplication : public MessagePumpNSApplication { - public: - MessagePumpCrApplication(); - ~MessagePumpCrApplication() override; - - protected: - // Returns nil if NSApp is currently in the middle of calling - // -sendEvent. Requires NSApp implementing CrAppProtocol. - AutoreleasePoolType* CreateAutoreleasePool() override; - - private: - DISALLOW_COPY_AND_ASSIGN(MessagePumpCrApplication); -}; -#endif // !defined(OS_IOS) - -class BASE_EXPORT MessagePumpMac { - public: - // If not on the main thread, returns a new instance of - // MessagePumpNSRunLoop. - // - // On the main thread, if NSApp exists and conforms to - // CrAppProtocol, creates an instances of MessagePumpCrApplication. - // - // Otherwise creates an instance of MessagePumpNSApplication using a - // default NSApplication. - static MessagePump* Create(); - -#if !defined(OS_IOS) - // If a pump is created before the required CrAppProtocol is - // created, the wrong MessagePump subclass could be used. - // UsingCrApp() returns false if the message pump was created before - // NSApp was initialized, or if NSApp does not implement - // CrAppProtocol. NSApp must be initialized before calling. - static bool UsingCrApp(); - - // Wrapper to query -[NSApp isHandlingSendEvent] from C++ code. - // Requires NSApp to implement CrAppProtocol. - static bool IsHandlingSendEvent(); -#endif // !defined(OS_IOS) - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePumpMac); -}; - -// Tasks posted to the message loop are posted under this mode, as well -// as kCFRunLoopCommonModes. -extern const CFStringRef BASE_EXPORT kMessageLoopExclusiveRunLoopMode; - -} // namespace base - -#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_MAC_H_ diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm deleted file mode 100644 index a3accee049..0000000000 --- a/base/message_loop/message_pump_mac.mm +++ /dev/null @@ -1,877 +0,0 @@ -// Copyright (c) 2012 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 "base/message_loop/message_pump_mac.h" - -#import <Foundation/Foundation.h> - -#include <limits> - -#include "base/logging.h" -#include "base/mac/call_with_eh_frame.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/macros.h" -#include "base/message_loop/timer_slack.h" -#include "base/run_loop.h" -#include "base/time/time.h" -#include "build/build_config.h" - -#if !defined(OS_IOS) -#import <AppKit/AppKit.h> -#endif // !defined(OS_IOS) - -namespace base { - -namespace { - -void CFRunLoopAddSourceToAllModes(CFRunLoopRef rl, CFRunLoopSourceRef source) { - CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); - CFRunLoopAddSource(rl, source, kMessageLoopExclusiveRunLoopMode); -} - -void CFRunLoopRemoveSourceFromAllModes(CFRunLoopRef rl, - CFRunLoopSourceRef source) { - CFRunLoopRemoveSource(rl, source, kCFRunLoopCommonModes); - CFRunLoopRemoveSource(rl, source, kMessageLoopExclusiveRunLoopMode); -} - -void CFRunLoopAddTimerToAllModes(CFRunLoopRef rl, CFRunLoopTimerRef timer) { - CFRunLoopAddTimer(rl, timer, kCFRunLoopCommonModes); - CFRunLoopAddTimer(rl, timer, kMessageLoopExclusiveRunLoopMode); -} - -void CFRunLoopRemoveTimerFromAllModes(CFRunLoopRef rl, - CFRunLoopTimerRef timer) { - CFRunLoopRemoveTimer(rl, timer, kCFRunLoopCommonModes); - CFRunLoopRemoveTimer(rl, timer, kMessageLoopExclusiveRunLoopMode); -} - -void CFRunLoopAddObserverToAllModes(CFRunLoopRef rl, - CFRunLoopObserverRef observer) { - CFRunLoopAddObserver(rl, observer, kCFRunLoopCommonModes); - CFRunLoopAddObserver(rl, observer, kMessageLoopExclusiveRunLoopMode); -} - -void CFRunLoopRemoveObserverFromAllModes(CFRunLoopRef rl, - CFRunLoopObserverRef observer) { - CFRunLoopRemoveObserver(rl, observer, kCFRunLoopCommonModes); - CFRunLoopRemoveObserver(rl, observer, kMessageLoopExclusiveRunLoopMode); -} - -void NoOp(void* /* info */) { -} - -const CFTimeInterval kCFTimeIntervalMax = - std::numeric_limits<CFTimeInterval>::max(); - -#if !defined(OS_IOS) -// Set to true if MessagePumpMac::Create() is called before NSApp is -// initialized. Only accessed from the main thread. -bool g_not_using_cr_app = false; - -// Various CoreFoundation definitions. -typedef struct __CFRuntimeBase { - uintptr_t _cfisa; - uint8_t _cfinfo[4]; -#if __LP64__ - uint32_t _rc; -#endif -} CFRuntimeBase; - -#if defined(__BIG_ENDIAN__) -#define __CF_BIG_ENDIAN__ 1 -#define __CF_LITTLE_ENDIAN__ 0 -#endif - -#if defined(__LITTLE_ENDIAN__) -#define __CF_LITTLE_ENDIAN__ 1 -#define __CF_BIG_ENDIAN__ 0 -#endif - -#define CF_INFO_BITS (!!(__CF_BIG_ENDIAN__)*3) - -#define __CFBitfieldMask(N1, N2) \ - ((((UInt32)~0UL) << (31UL - (N1) + (N2))) >> (31UL - N1)) -#define __CFBitfieldSetValue(V, N1, N2, X) \ - ((V) = ((V) & ~__CFBitfieldMask(N1, N2)) | \ - (((X) << (N2)) & __CFBitfieldMask(N1, N2))) - -// Marking timers as invalid at the right time by flipping their valid bit helps -// significantly reduce power use (see the explanation in -// RunDelayedWorkTimer()), however there is no public API for doing so. -// CFRuntime.h states that CFRuntimeBase can change from release to release -// and should not be accessed directly. The last known change of this struct -// occurred in 2008 in CF-476 / 10.5; unfortunately the source for 10.11 and -// 10.12 is not available for inspection at this time. -// CanInvalidateCFRunLoopTimers() will at least prevent us from invalidating -// timers if this function starts flipping the wrong bit on a future OS release. -void __ChromeCFRunLoopTimerSetValid(CFRunLoopTimerRef timer, bool valid) { - __CFBitfieldSetValue(((CFRuntimeBase*)timer)->_cfinfo[CF_INFO_BITS], 3, 3, - valid); -} -#endif // !defined(OS_IOS) - -} // namespace - -// static -const CFStringRef kMessageLoopExclusiveRunLoopMode = - CFSTR("kMessageLoopExclusiveRunLoopMode"); - -// A scoper for autorelease pools created from message pump run loops. -// Avoids dirtying up the ScopedNSAutoreleasePool interface for the rare -// case where an autorelease pool needs to be passed in. -class MessagePumpScopedAutoreleasePool { - public: - explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : - pool_(pump->CreateAutoreleasePool()) { - } - ~MessagePumpScopedAutoreleasePool() { - [pool_ drain]; - } - - private: - NSAutoreleasePool* pool_; - DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); -}; - -#if !defined(OS_IOS) -// This function uses private API to modify a test timer's valid state and -// uses public API to confirm that the private API changed the correct bit. -// static -bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() { - CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); - timer_context.info = nullptr; - ScopedCFTypeRef<CFRunLoopTimerRef> test_timer( - CFRunLoopTimerCreate(NULL, // allocator - kCFTimeIntervalMax, // fire time - kCFTimeIntervalMax, // interval - 0, // flags - 0, // priority - nullptr, &timer_context)); - // Should be valid from the start. - if (!CFRunLoopTimerIsValid(test_timer)) { - return false; - } - // Confirm that the private API can mark the timer invalid. - __ChromeCFRunLoopTimerSetValid(test_timer, false); - if (CFRunLoopTimerIsValid(test_timer)) { - return false; - } - // Confirm that the private API can mark the timer valid. - __ChromeCFRunLoopTimerSetValid(test_timer, true); - return CFRunLoopTimerIsValid(test_timer); -} -#endif // !defined(OS_IOS) - -// static -void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid( - CFRunLoopTimerRef timer, - bool valid) { -#if !defined(OS_IOS) - static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers(); - if (can_invalidate_timers) { - __ChromeCFRunLoopTimerSetValid(timer, valid); - } -#endif // !defined(OS_IOS) -} - -// Must be called on the run loop thread. -MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() - : delegate_(NULL), - delayed_work_fire_time_(kCFTimeIntervalMax), - timer_slack_(base::TIMER_SLACK_NONE), - nesting_level_(0), - run_nesting_level_(0), - deepest_nesting_level_(0), - delegateless_work_(false), - delegateless_idle_work_(false) { - run_loop_ = CFRunLoopGetCurrent(); - CFRetain(run_loop_); - - // Set a repeating timer with a preposterous firing time and interval. The - // timer will effectively never fire as-is. The firing time will be adjusted - // as needed when ScheduleDelayedWork is called. - CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); - timer_context.info = this; - delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator - kCFTimeIntervalMax, // fire time - kCFTimeIntervalMax, // interval - 0, // flags - 0, // priority - RunDelayedWorkTimer, - &timer_context); - CFRunLoopAddTimerToAllModes(run_loop_, delayed_work_timer_); - - CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); - source_context.info = this; - source_context.perform = RunWorkSource; - work_source_ = CFRunLoopSourceCreate(NULL, // allocator - 1, // priority - &source_context); - CFRunLoopAddSourceToAllModes(run_loop_, work_source_); - - source_context.perform = RunIdleWorkSource; - idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator - 2, // priority - &source_context); - CFRunLoopAddSourceToAllModes(run_loop_, idle_work_source_); - - source_context.perform = RunNestingDeferredWorkSource; - nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator - 0, // priority - &source_context); - CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_); - - CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); - observer_context.info = this; - pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator - kCFRunLoopBeforeWaiting, - true, // repeat - 0, // priority - PreWaitObserver, - &observer_context); - CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_); - - pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator - kCFRunLoopBeforeSources, - true, // repeat - 0, // priority - PreSourceObserver, - &observer_context); - CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_); - - enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator - kCFRunLoopEntry | - kCFRunLoopExit, - true, // repeat - 0, // priority - EnterExitObserver, - &observer_context); - CFRunLoopAddObserverToAllModes(run_loop_, enter_exit_observer_); -} - -// Ideally called on the run loop thread. If other run loops were running -// lower on the run loop thread's stack when this object was created, the -// same number of run loops must be running when this object is destroyed. -MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { - CFRunLoopRemoveObserverFromAllModes(run_loop_, enter_exit_observer_); - CFRelease(enter_exit_observer_); - - CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_source_observer_); - CFRelease(pre_source_observer_); - - CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_wait_observer_); - CFRelease(pre_wait_observer_); - - CFRunLoopRemoveSourceFromAllModes(run_loop_, nesting_deferred_work_source_); - CFRelease(nesting_deferred_work_source_); - - CFRunLoopRemoveSourceFromAllModes(run_loop_, idle_work_source_); - CFRelease(idle_work_source_); - - CFRunLoopRemoveSourceFromAllModes(run_loop_, work_source_); - CFRelease(work_source_); - - CFRunLoopRemoveTimerFromAllModes(run_loop_, delayed_work_timer_); - CFRelease(delayed_work_timer_); - - CFRelease(run_loop_); -} - -// Must be called on the run loop thread. -void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { - // nesting_level_ will be incremented in EnterExitRunLoop, so set - // run_nesting_level_ accordingly. - int last_run_nesting_level = run_nesting_level_; - run_nesting_level_ = nesting_level_ + 1; - - Delegate* last_delegate = delegate_; - SetDelegate(delegate); - - DoRun(delegate); - - // Restore the previous state of the object. - SetDelegate(last_delegate); - run_nesting_level_ = last_run_nesting_level; -} - -void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) { - delegate_ = delegate; - - if (delegate) { - // If any work showed up but could not be dispatched for want of a - // delegate, set it up for dispatch again now that a delegate is - // available. - if (delegateless_work_) { - CFRunLoopSourceSignal(work_source_); - delegateless_work_ = false; - } - if (delegateless_idle_work_) { - CFRunLoopSourceSignal(idle_work_source_); - delegateless_idle_work_ = false; - } - } -} - -// May be called on any thread. -void MessagePumpCFRunLoopBase::ScheduleWork() { - CFRunLoopSourceSignal(work_source_); - CFRunLoopWakeUp(run_loop_); -} - -// Must be called on the run loop thread. -void MessagePumpCFRunLoopBase::ScheduleDelayedWork( - const TimeTicks& delayed_work_time) { - TimeDelta delta = delayed_work_time - TimeTicks::Now(); - delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF(); - - // Flip the timer's validation bit just before setting the new fire time. Do - // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity - // of a timer before proceeding to set its fire date. Making the timer valid - // now won't have any side effects (such as a premature firing of the timer) - // because we're only flipping a bit. - // - // Please see the comment in RunDelayedWorkTimer() for more info on the whys - // of invalidation. - ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true); - - CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_); - if (timer_slack_ == TIMER_SLACK_MAXIMUM) { - CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5); - } else { - CFRunLoopTimerSetTolerance(delayed_work_timer_, 0); - } -} - -void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) { - timer_slack_ = timer_slack; -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::RunDelayedWorkTimer( - CFRunLoopTimerRef /* timer */, - void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - - // The timer won't fire again until it's reset. - self->delayed_work_fire_time_ = kCFTimeIntervalMax; - - // The message pump's timer needs to fire at changing and unpredictable - // intervals. Creating a new timer for each firing time is very expensive, so - // the message pump instead uses a repeating timer with a very large repeat - // rate. After each firing of the timer, the run loop sets the timer's next - // firing time to the distant future, essentially pausing the timer until the - // pump sets the next firing time. This is the solution recommended by Apple. - // - // It turns out, however, that scheduling timers is also quite expensive, and - // that every one of the message pump's timer firings incurs two - // reschedulings. The first rescheduling occurs in ScheduleDelayedWork(), - // which sets the desired next firing time. The second comes after exiting - // this method (the timer's callback method), when the run loop sets the - // timer's next firing time to far in the future. - // - // The code in __CFRunLoopDoTimer() inside CFRunLoop.c calls the timer's - // callback, confirms that the timer is valid, and then sets its future - // firing time based on its repeat frequency. Flipping the valid bit here - // causes the __CFRunLoopDoTimer() to skip setting the future firing time. - // Note that there's public API to invalidate a timer but it goes beyond - // flipping the valid bit, making the timer unusable in the future. - // - // ScheduleDelayedWork() flips the valid bit back just before setting the - // timer's new firing time. - ChromeCFRunLoopTimerSetValid(self->delayed_work_timer_, false); - - // CFRunLoopTimers fire outside of the priority scheme for CFRunLoopSources. - // In order to establish the proper priority in which work and delayed work - // are processed one for one, the timer used to schedule delayed work must - // signal a CFRunLoopSource used to dispatch both work and delayed work. - CFRunLoopSourceSignal(self->work_source_); -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::RunWorkSource(void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - base::mac::CallWithEHFrame(^{ - self->RunWork(); - }); -} - -// Called by MessagePumpCFRunLoopBase::RunWorkSource. -bool MessagePumpCFRunLoopBase::RunWork() { - if (!delegate_) { - // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. Arrange to come back - // here when a delegate is available. - delegateless_work_ = true; - return false; - } - - // The NSApplication-based run loop only drains the autorelease pool at each - // UI event (NSEvent). The autorelease pool is not drained for each - // CFRunLoopSource target that's run. Use a local pool for any autoreleased - // objects if the app is not currently handling a UI event to ensure they're - // released promptly even in the absence of UI events. - MessagePumpScopedAutoreleasePool autorelease_pool(this); - - // Call DoWork and DoDelayedWork once, and if something was done, arrange to - // come back here again as long as the loop is still running. - bool did_work = delegate_->DoWork(); - bool resignal_work_source = did_work; - - TimeTicks next_time; - delegate_->DoDelayedWork(&next_time); - if (!did_work) { - // Determine whether there's more delayed work, and if so, if it needs to - // be done at some point in the future or if it's already time to do it. - // Only do these checks if did_work is false. If did_work is true, this - // function, and therefore any additional delayed work, will get another - // chance to run before the loop goes to sleep. - bool more_delayed_work = !next_time.is_null(); - if (more_delayed_work) { - TimeDelta delay = next_time - TimeTicks::Now(); - if (delay > TimeDelta()) { - // There's more delayed work to be done in the future. - ScheduleDelayedWork(next_time); - } else { - // There's more delayed work to be done, and its time is in the past. - // Arrange to come back here directly as long as the loop is still - // running. - resignal_work_source = true; - } - } - } - - if (resignal_work_source) { - CFRunLoopSourceSignal(work_source_); - } - - return resignal_work_source; -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::RunIdleWorkSource(void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - self->RunIdleWork(); -} - -// Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. -bool MessagePumpCFRunLoopBase::RunIdleWork() { - if (!delegate_) { - // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. Arrange to come back - // here when a delegate is available. - delegateless_idle_work_ = true; - return false; - } - - // The NSApplication-based run loop only drains the autorelease pool at each - // UI event (NSEvent). The autorelease pool is not drained for each - // CFRunLoopSource target that's run. Use a local pool for any autoreleased - // objects if the app is not currently handling a UI event to ensure they're - // released promptly even in the absence of UI events. - MessagePumpScopedAutoreleasePool autorelease_pool(this); - - // Call DoIdleWork once, and if something was done, arrange to come back here - // again as long as the loop is still running. - bool did_work = delegate_->DoIdleWork(); - if (did_work) { - CFRunLoopSourceSignal(idle_work_source_); - } - - return did_work; -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource(void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - self->RunNestingDeferredWork(); -} - -// Called by MessagePumpCFRunLoopBase::RunNestingDeferredWorkSource. -bool MessagePumpCFRunLoopBase::RunNestingDeferredWork() { - if (!delegate_) { - // This point can be reached with a NULL delegate_ if Run is not on the - // stack but foreign code is spinning the CFRunLoop. There's no sense in - // attempting to do any work or signalling the work sources because - // without a delegate, work is not possible. - return false; - } - - // Immediately try work in priority order. - if (!RunWork()) { - if (!RunIdleWork()) { - return false; - } - } else { - // Work was done. Arrange for the loop to try non-nestable idle work on - // a subsequent pass. - CFRunLoopSourceSignal(idle_work_source_); - } - - return true; -} - -// Called before the run loop goes to sleep or exits, or processes sources. -void MessagePumpCFRunLoopBase::MaybeScheduleNestingDeferredWork() { - // deepest_nesting_level_ is set as run loops are entered. If the deepest - // level encountered is deeper than the current level, a nested loop - // (relative to the current level) ran since the last time nesting-deferred - // work was scheduled. When that situation is encountered, schedule - // nesting-deferred work in case any work was deferred because nested work - // was disallowed. - if (deepest_nesting_level_ > nesting_level_) { - deepest_nesting_level_ = nesting_level_; - CFRunLoopSourceSignal(nesting_deferred_work_source_); - } -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::PreWaitObserver( - CFRunLoopObserverRef /* observer */, - CFRunLoopActivity /* activity */, - void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - - // Attempt to do some idle work before going to sleep. - self->RunIdleWork(); - - // The run loop is about to go to sleep. If any of the work done since it - // started or woke up resulted in a nested run loop running, - // nesting-deferred work may have accumulated. Schedule it for processing - // if appropriate. - self->MaybeScheduleNestingDeferredWork(); -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::PreSourceObserver( - CFRunLoopObserverRef /* observer */, - CFRunLoopActivity /* activity */, - void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - - // The run loop has reached the top of the loop and is about to begin - // processing sources. If the last iteration of the loop at this nesting - // level did not sleep or exit, nesting-deferred work may have accumulated - // if a nested loop ran. Schedule nesting-deferred work for processing if - // appropriate. - self->MaybeScheduleNestingDeferredWork(); -} - -// Called from the run loop. -// static -void MessagePumpCFRunLoopBase::EnterExitObserver( - CFRunLoopObserverRef /* observer */, - CFRunLoopActivity activity, - void* info) { - MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - - switch (activity) { - case kCFRunLoopEntry: - ++self->nesting_level_; - if (self->nesting_level_ > self->deepest_nesting_level_) { - self->deepest_nesting_level_ = self->nesting_level_; - } - break; - - case kCFRunLoopExit: - // Not all run loops go to sleep. If a run loop is stopped before it - // goes to sleep due to a CFRunLoopStop call, or if the timeout passed - // to CFRunLoopRunInMode expires, the run loop may proceed directly from - // handling sources to exiting without any sleep. This most commonly - // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it - // to make a single pass through the loop and exit without sleep. Some - // native loops use CFRunLoop in this way. Because PreWaitObserver will - // not be called in these case, MaybeScheduleNestingDeferredWork needs - // to be called here, as the run loop exits. - // - // MaybeScheduleNestingDeferredWork consults self->nesting_level_ - // to determine whether to schedule nesting-deferred work. It expects - // the nesting level to be set to the depth of the loop that is going - // to sleep or exiting. It must be called before decrementing the - // value so that the value still corresponds to the level of the exiting - // loop. - self->MaybeScheduleNestingDeferredWork(); - --self->nesting_level_; - break; - - default: - break; - } - - self->EnterExitRunLoop(activity); -} - -// Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default -// implementation is a no-op. -void MessagePumpCFRunLoopBase::EnterExitRunLoop( - CFRunLoopActivity /* activity */) { -} - -// Base version returns a standard NSAutoreleasePool. -AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() { - return [[NSAutoreleasePool alloc] init]; -} - -MessagePumpCFRunLoop::MessagePumpCFRunLoop() - : quit_pending_(false) { -} - -MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {} - -// Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were -// running lower on the run loop thread's stack when this object was created, -// the same number of CFRunLoopRun loops must be running for the outermost call -// to Run. Run/DoRun are reentrant after that point. -void MessagePumpCFRunLoop::DoRun(Delegate* /* delegate */) { - // This is completely identical to calling CFRunLoopRun(), except autorelease - // pool management is introduced. - int result; - do { - MessagePumpScopedAutoreleasePool autorelease_pool(this); - result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, - kCFTimeIntervalMax, - false); - } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); -} - -// Must be called on the run loop thread. -void MessagePumpCFRunLoop::Quit() { - // Stop the innermost run loop managed by this MessagePumpCFRunLoop object. - if (nesting_level() == run_nesting_level()) { - // This object is running the innermost loop, just stop it. - CFRunLoopStop(run_loop()); - } else { - // There's another loop running inside the loop managed by this object. - // In other words, someone else called CFRunLoopRunInMode on the same - // thread, deeper on the stack than the deepest Run call. Don't preempt - // other run loops, just mark this object to quit the innermost Run as - // soon as the other inner loops not managed by Run are done. - quit_pending_ = true; - } -} - -// Called by MessagePumpCFRunLoopBase::EnterExitObserver. -void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) { - if (activity == kCFRunLoopExit && - nesting_level() == run_nesting_level() && - quit_pending_) { - // Quit was called while loops other than those managed by this object - // were running further inside a run loop managed by this object. Now - // that all unmanaged inner run loops are gone, stop the loop running - // just inside Run. - CFRunLoopStop(run_loop()); - quit_pending_ = false; - } -} - -MessagePumpNSRunLoop::MessagePumpNSRunLoop() - : keep_running_(true) { - CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); - source_context.perform = NoOp; - quit_source_ = CFRunLoopSourceCreate(NULL, // allocator - 0, // priority - &source_context); - CFRunLoopAddSourceToAllModes(run_loop(), quit_source_); -} - -MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { - CFRunLoopRemoveSourceFromAllModes(run_loop(), quit_source_); - CFRelease(quit_source_); -} - -void MessagePumpNSRunLoop::DoRun(Delegate* /* delegate */) { - while (keep_running_) { - // NSRunLoop manages autorelease pools itself. - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode - beforeDate:[NSDate distantFuture]]; - } - - keep_running_ = true; -} - -void MessagePumpNSRunLoop::Quit() { - keep_running_ = false; - CFRunLoopSourceSignal(quit_source_); - CFRunLoopWakeUp(run_loop()); -} - -#if defined(OS_IOS) -MessagePumpUIApplication::MessagePumpUIApplication() - : run_loop_(NULL) { -} - -MessagePumpUIApplication::~MessagePumpUIApplication() {} - -void MessagePumpUIApplication::DoRun(Delegate* delegate) { - NOTREACHED(); -} - -void MessagePumpUIApplication::Quit() { - NOTREACHED(); -} - -void MessagePumpUIApplication::Attach(Delegate* delegate) { - DCHECK(!run_loop_); - run_loop_ = new RunLoop(); - CHECK(run_loop_->BeforeRun()); - SetDelegate(delegate); -} - -#else - -MessagePumpNSApplication::MessagePumpNSApplication() - : keep_running_(true), - running_own_loop_(false) { -} - -MessagePumpNSApplication::~MessagePumpNSApplication() {} - -void MessagePumpNSApplication::DoRun(Delegate* /* delegate */) { - bool last_running_own_loop_ = running_own_loop_; - - // NSApp must be initialized by calling: - // [{some class which implements CrAppProtocol} sharedApplication] - // Most likely candidates are CrApplication or BrowserCrApplication. - // These can be initialized from C++ code by calling - // RegisterCrApp() or RegisterBrowserCrApp(). - CHECK(NSApp); - - if (![NSApp isRunning]) { - running_own_loop_ = false; - // NSApplication manages autorelease pools itself when run this way. - [NSApp run]; - } else { - running_own_loop_ = true; - NSDate* distant_future = [NSDate distantFuture]; - while (keep_running_) { - MessagePumpScopedAutoreleasePool autorelease_pool(this); - NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:distant_future - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event) { - [NSApp sendEvent:event]; - } - } - keep_running_ = true; - } - - running_own_loop_ = last_running_own_loop_; -} - -void MessagePumpNSApplication::Quit() { - if (!running_own_loop_) { - [[NSApplication sharedApplication] stop:nil]; - } else { - keep_running_ = false; - } - - // Send a fake event to wake the loop up. - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint - modifierFlags:0 - timestamp:0 - windowNumber:0 - context:NULL - subtype:0 - data1:0 - data2:0] - atStart:NO]; -} - -MessagePumpCrApplication::MessagePumpCrApplication() { -} - -MessagePumpCrApplication::~MessagePumpCrApplication() { -} - -// Prevents an autorelease pool from being created if the app is in the midst of -// handling a UI event because various parts of AppKit depend on objects that -// are created while handling a UI event to be autoreleased in the event loop. -// An example of this is NSWindowController. When a window with a window -// controller is closed it goes through a stack like this: -// (Several stack frames elided for clarity) -// -// #0 [NSWindowController autorelease] -// #1 DoAClose -// #2 MessagePumpCFRunLoopBase::DoWork() -// #3 [NSRunLoop run] -// #4 [NSButton performClick:] -// #5 [NSWindow sendEvent:] -// #6 [NSApp sendEvent:] -// #7 [NSApp run] -// -// -performClick: spins a nested run loop. If the pool created in DoWork was a -// standard NSAutoreleasePool, it would release the objects that were -// autoreleased into it once DoWork released it. This would cause the window -// controller, which autoreleased itself in frame #0, to release itself, and -// possibly free itself. Unfortunately this window controller controls the -// window in frame #5. When the stack is unwound to frame #5, the window would -// no longer exists and crashes may occur. Apple gets around this by never -// releasing the pool it creates in frame #4, and letting frame #7 clean it up -// when it cleans up the pool that wraps frame #7. When an autorelease pool is -// released it releases all other pools that were created after it on the -// autorelease pool stack. -// -// CrApplication is responsible for setting handlingSendEvent to true just -// before it sends the event through the event handling mechanism, and -// returning it to its previous value once the event has been sent. -AutoreleasePoolType* MessagePumpCrApplication::CreateAutoreleasePool() { - if (MessagePumpMac::IsHandlingSendEvent()) - return nil; - return MessagePumpNSApplication::CreateAutoreleasePool(); -} - -// static -bool MessagePumpMac::UsingCrApp() { - DCHECK([NSThread isMainThread]); - - // If NSApp is still not initialized, then the subclass used cannot - // be determined. - DCHECK(NSApp); - - // The pump was created using MessagePumpNSApplication. - if (g_not_using_cr_app) - return false; - - return [NSApp conformsToProtocol:@protocol(CrAppProtocol)]; -} - -// static -bool MessagePumpMac::IsHandlingSendEvent() { - DCHECK([NSApp conformsToProtocol:@protocol(CrAppProtocol)]); - NSObject<CrAppProtocol>* app = static_cast<NSObject<CrAppProtocol>*>(NSApp); - return [app isHandlingSendEvent]; -} -#endif // !defined(OS_IOS) - -// static -MessagePump* MessagePumpMac::Create() { - if ([NSThread isMainThread]) { -#if defined(OS_IOS) - return new MessagePumpUIApplication; -#else - if ([NSApp conformsToProtocol:@protocol(CrAppProtocol)]) - return new MessagePumpCrApplication; - - // The main-thread MessagePump implementations REQUIRE an NSApp. - // Executables which have specific requirements for their - // NSApplication subclass should initialize appropriately before - // creating an event loop. - [NSApplication sharedApplication]; - g_not_using_cr_app = true; - return new MessagePumpNSApplication; -#endif - } - - return new MessagePumpNSRunLoop; -} - -} // namespace base diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc deleted file mode 100644 index 3732bc1ecc..0000000000 --- a/base/process/launch_mac.cc +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/process/launch.h" - -#include <crt_externs.h> -#include <mach/mach.h> -#include <spawn.h> -#include <string.h> -#include <sys/wait.h> - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/threading/thread_restrictions.h" - -namespace base { - -namespace { - -// DPSXCHECK is a Debug Posix Spawn Check macro. The posix_spawn* family of -// functions return an errno value, as opposed to setting errno directly. This -// macro emulates a DPCHECK(). -#define DPSXCHECK(expr) \ - do { \ - int rv = (expr); \ - DCHECK_EQ(rv, 0) << #expr << ": -" << rv << " " << strerror(rv); \ - } while (0) - -class PosixSpawnAttr { - public: - PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_init(&attr_)); } - - ~PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_destroy(&attr_)); } - - posix_spawnattr_t* get() { return &attr_; } - - private: - posix_spawnattr_t attr_; -}; - -class PosixSpawnFileActions { - public: - PosixSpawnFileActions() { - DPSXCHECK(posix_spawn_file_actions_init(&file_actions_)); - } - - ~PosixSpawnFileActions() { - DPSXCHECK(posix_spawn_file_actions_destroy(&file_actions_)); - } - - void Open(int filedes, const char* path, int mode) { - DPSXCHECK(posix_spawn_file_actions_addopen(&file_actions_, filedes, path, - mode, 0)); - } - - void Dup2(int filedes, int newfiledes) { - DPSXCHECK( - posix_spawn_file_actions_adddup2(&file_actions_, filedes, newfiledes)); - } - - void Inherit(int filedes) { - DPSXCHECK(posix_spawn_file_actions_addinherit_np(&file_actions_, filedes)); - } - - const posix_spawn_file_actions_t* get() const { return &file_actions_; } - - private: - posix_spawn_file_actions_t file_actions_; - - DISALLOW_COPY_AND_ASSIGN(PosixSpawnFileActions); -}; - -} // namespace - -void RestoreDefaultExceptionHandler() { - // This function is tailored to remove the Breakpad exception handler. - // exception_mask matches s_exception_mask in - // breakpad/src/client/mac/handler/exception_handler.cc - const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | - EXC_MASK_BAD_INSTRUCTION | - EXC_MASK_ARITHMETIC | - EXC_MASK_BREAKPOINT; - - // Setting the exception port to MACH_PORT_NULL may not be entirely - // kosher to restore the default exception handler, but in practice, - // it results in the exception port being set to Apple Crash Reporter, - // the desired behavior. - task_set_exception_ports(mach_task_self(), exception_mask, MACH_PORT_NULL, - EXCEPTION_DEFAULT, THREAD_STATE_NONE); -} - -Process LaunchProcessPosixSpawn(const std::vector<std::string>& argv, - const LaunchOptions& options) { - DCHECK(!options.pre_exec_delegate) - << "LaunchProcessPosixSpawn does not support PreExecDelegate"; - DCHECK(options.current_directory.empty()) - << "LaunchProcessPosixSpawn does not support current_directory"; - - PosixSpawnAttr attr; - - short flags = POSIX_SPAWN_CLOEXEC_DEFAULT; - if (options.new_process_group) { - flags |= POSIX_SPAWN_SETPGROUP; - DPSXCHECK(posix_spawnattr_setpgroup(attr.get(), 0)); - } - DPSXCHECK(posix_spawnattr_setflags(attr.get(), flags)); - - PosixSpawnFileActions file_actions; - - // Process file descriptors for the child. By default, LaunchProcess will - // open stdin to /dev/null and inherit stdout and stderr. - bool inherit_stdout = true, inherit_stderr = true; - bool null_stdin = true; - if (options.fds_to_remap) { - for (const auto& dup2_pair : *options.fds_to_remap) { - if (dup2_pair.second == STDIN_FILENO) { - null_stdin = false; - } else if (dup2_pair.second == STDOUT_FILENO) { - inherit_stdout = false; - } else if (dup2_pair.second == STDERR_FILENO) { - inherit_stderr = false; - } - - if (dup2_pair.first == dup2_pair.second) { - file_actions.Inherit(dup2_pair.second); - } else { - file_actions.Dup2(dup2_pair.first, dup2_pair.second); - } - } - } - - if (null_stdin) { - file_actions.Open(STDIN_FILENO, "/dev/null", O_RDONLY); - } - if (inherit_stdout) { - file_actions.Inherit(STDOUT_FILENO); - } - if (inherit_stderr) { - file_actions.Inherit(STDERR_FILENO); - } - - std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); - for (size_t i = 0; i < argv.size(); i++) { - argv_cstr[i] = const_cast<char*>(argv[i].c_str()); - } - argv_cstr[argv.size()] = nullptr; - - std::unique_ptr<char* []> owned_environ; - char** new_environ = options.clear_environ ? nullptr : *_NSGetEnviron(); - if (!options.environ.empty()) { - owned_environ = AlterEnvironment(new_environ, options.environ); - new_environ = owned_environ.get(); - } - - const char* executable_path = !options.real_path.empty() - ? options.real_path.value().c_str() - : argv_cstr[0]; - - // Use posix_spawnp as some callers expect to have PATH consulted. - pid_t pid; - int rv = posix_spawnp(&pid, executable_path, file_actions.get(), attr.get(), - &argv_cstr[0], new_environ); - - if (rv != 0) { - DLOG(ERROR) << "posix_spawnp(" << executable_path << "): -" << rv << " " - << strerror(rv); - return Process(); - } - - if (options.wait) { - // While this isn't strictly disk IO, waiting for another process to - // finish is the sort of thing ThreadRestrictions is trying to prevent. - base::ThreadRestrictions::AssertIOAllowed(); - pid_t ret = HANDLE_EINTR(waitpid(pid, nullptr, 0)); - DPCHECK(ret > 0); - } - - return Process(pid); -} - -} // namespace base diff --git a/base/process/port_provider_mac.cc b/base/process/port_provider_mac.cc deleted file mode 100644 index 23d214c3f3..0000000000 --- a/base/process/port_provider_mac.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2015 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. - -#include "base/process/port_provider_mac.h" - -namespace base { - -PortProvider::PortProvider() : lock_(), observer_list_() {} -PortProvider::~PortProvider() {} - -void PortProvider::AddObserver(Observer* observer) { - base::AutoLock l(lock_); - observer_list_.AddObserver(observer); -} - -void PortProvider::RemoveObserver(Observer* observer) { - base::AutoLock l(lock_); - observer_list_.RemoveObserver(observer); -} - -void PortProvider::NotifyObservers(ProcessHandle process) { - base::AutoLock l(lock_); - for (auto& observer : observer_list_) - observer.OnReceivedTaskPort(process); -} - -} // namespace base diff --git a/base/process/port_provider_mac.h b/base/process/port_provider_mac.h deleted file mode 100644 index 2f40297f28..0000000000 --- a/base/process/port_provider_mac.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2015 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. - -#ifndef BASE_PROCESS_PORT_PROVIDER_MAC_H_ -#define BASE_PROCESS_PORT_PROVIDER_MAC_H_ - -#include <mach/mach.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/observer_list.h" -#include "base/process/process_handle.h" -#include "base/synchronization/lock.h" - -namespace base { - -// Abstract base class that provides a mapping from ProcessHandle (pid_t) to the -// Mach task port. This replicates task_for_pid(), which requires root -// privileges. -class BASE_EXPORT PortProvider { - public: - PortProvider(); - virtual ~PortProvider(); - - class Observer { - public: - virtual ~Observer() {}; - // Called by the PortProvider to notify observers that the task port was - // received for a given process. - // No guarantees are made about the thread on which this notification will - // be sent. - // Observers must not call AddObserver() or RemoveObserver() in this - // callback, as doing so will deadlock. - virtual void OnReceivedTaskPort(ProcessHandle process) = 0; - }; - - // Returns the mach task port for |process| if possible, or else - // |MACH_PORT_NULL|. - virtual mach_port_t TaskForPid(ProcessHandle process) const = 0; - - // Observer interface. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - protected: - // Called by subclasses to send a notification to observers. - void NotifyObservers(ProcessHandle process); - - private: - // ObserverList is not thread-safe, so |lock_| ensures consistency of - // |observer_list_|. - base::Lock lock_; - base::ObserverList<Observer> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(PortProvider); -}; - -} // namespace base - -#endif // BASE_PROCESS_PORT_PROVIDER_MAC_H_ diff --git a/base/process/process_handle_mac.cc b/base/process/process_handle_mac.cc deleted file mode 100644 index d9d22f7831..0000000000 --- a/base/process/process_handle_mac.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2013 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. - -#include "base/process/process_handle.h" - -#include <libproc.h> -#include <stddef.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -#include "base/logging.h" - -namespace base { - -ProcessId GetParentProcessId(ProcessHandle process) { - struct kinfo_proc info; - size_t length = sizeof(struct kinfo_proc); - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process }; - if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) { - DPLOG(ERROR) << "sysctl"; - return -1; - } - if (length == 0) - return -1; - return info.kp_eproc.e_ppid; -} - -FilePath GetProcessExecutablePath(ProcessHandle process) { - char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; - if (!proc_pidpath(process, pathbuf, sizeof(pathbuf))) - return FilePath(); - - return FilePath(pathbuf); -} - -} // namespace base diff --git a/base/process/process_info_mac.cc b/base/process/process_info_mac.cc deleted file mode 100644 index 27b9623d9e..0000000000 --- a/base/process/process_info_mac.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/process/process_info.h" - -#include <stddef.h> -#include <sys/sysctl.h> -#include <sys/time.h> -#include <unistd.h> - -#include <memory> - -#include "base/macros.h" -#include "base/memory/free_deleter.h" -#include "base/time/time.h" - -namespace base { - -// static -const Time CurrentProcessInfo::CreationTime() { - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; - size_t len = 0; - if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0) - return Time(); - - std::unique_ptr<struct kinfo_proc, base::FreeDeleter> proc( - static_cast<struct kinfo_proc*>(malloc(len))); - if (sysctl(mib, arraysize(mib), proc.get(), &len, NULL, 0) < 0) - return Time(); - return Time::FromTimeVal(proc->kp_proc.p_un.__p_starttime); -} - -} // namespace base diff --git a/base/process/process_iterator_mac.cc b/base/process/process_iterator_mac.cc deleted file mode 100644 index 3d616980ab..0000000000 --- a/base/process/process_iterator_mac.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2013 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. - -#include "base/process/process_iterator.h" - -#include <errno.h> -#include <stddef.h> -#include <sys/sysctl.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" - -namespace base { - -ProcessIterator::ProcessIterator(const ProcessFilter* filter) - : index_of_kinfo_proc_(0), - filter_(filter) { - // Get a snapshot of all of my processes (yes, as we loop it can go stale, but - // but trying to find where we were in a constantly changing list is basically - // impossible. - - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, - static_cast<int>(geteuid()) }; - - // Since more processes could start between when we get the size and when - // we get the list, we do a loop to keep trying until we get it. - bool done = false; - int try_num = 1; - const int max_tries = 10; - do { - // Get the size of the buffer - size_t len = 0; - if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0) { - DLOG(ERROR) << "failed to get the size needed for the process list"; - kinfo_procs_.resize(0); - done = true; - } else { - size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc); - // Leave some spare room for process table growth (more could show up - // between when we check and now) - num_of_kinfo_proc += 16; - kinfo_procs_.resize(num_of_kinfo_proc); - len = num_of_kinfo_proc * sizeof(struct kinfo_proc); - // Load the list of processes - if (sysctl(mib, arraysize(mib), &kinfo_procs_[0], &len, NULL, 0) < 0) { - // If we get a mem error, it just means we need a bigger buffer, so - // loop around again. Anything else is a real error and give up. - if (errno != ENOMEM) { - DLOG(ERROR) << "failed to get the process list"; - kinfo_procs_.resize(0); - done = true; - } - } else { - // Got the list, just make sure we're sized exactly right - size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc); - kinfo_procs_.resize(num_of_kinfo_proc); - done = true; - } - } - } while (!done && (try_num++ < max_tries)); - - if (!done) { - DLOG(ERROR) << "failed to collect the process list in a few tries"; - kinfo_procs_.resize(0); - } -} - -ProcessIterator::~ProcessIterator() { -} - -bool ProcessIterator::CheckForNextProcess() { - std::string data; - for (; index_of_kinfo_proc_ < kinfo_procs_.size(); ++index_of_kinfo_proc_) { - kinfo_proc& kinfo = kinfo_procs_[index_of_kinfo_proc_]; - - // Skip processes just awaiting collection - if ((kinfo.kp_proc.p_pid > 0) && (kinfo.kp_proc.p_stat == SZOMB)) - continue; - - int mib[] = { CTL_KERN, KERN_PROCARGS, kinfo.kp_proc.p_pid }; - - // Find out what size buffer we need. - size_t data_len = 0; - if (sysctl(mib, arraysize(mib), NULL, &data_len, NULL, 0) < 0) { - DVPLOG(1) << "failed to figure out the buffer size for a commandline"; - continue; - } - - data.resize(data_len); - if (sysctl(mib, arraysize(mib), &data[0], &data_len, NULL, 0) < 0) { - DVPLOG(1) << "failed to fetch a commandline"; - continue; - } - - // |data| contains all the command line parameters of the process, separated - // by blocks of one or more null characters. We tokenize |data| into a - // vector of strings using '\0' as a delimiter and populate - // |entry_.cmd_line_args_|. - std::string delimiters; - delimiters.push_back('\0'); - entry_.cmd_line_args_ = SplitString(data, delimiters, - KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY); - - // |data| starts with the full executable path followed by a null character. - // We search for the first instance of '\0' and extract everything before it - // to populate |entry_.exe_file_|. - size_t exec_name_end = data.find('\0'); - if (exec_name_end == std::string::npos) { - DLOG(ERROR) << "command line data didn't match expected format"; - continue; - } - - entry_.pid_ = kinfo.kp_proc.p_pid; - entry_.ppid_ = kinfo.kp_eproc.e_ppid; - entry_.gid_ = kinfo.kp_eproc.e_pgid; - size_t last_slash = data.rfind('/', exec_name_end); - if (last_slash == std::string::npos) - entry_.exe_file_.assign(data, 0, exec_name_end); - else - entry_.exe_file_.assign(data, last_slash + 1, - exec_name_end - last_slash - 1); - // Start w/ the next entry next time through - ++index_of_kinfo_proc_; - // Done - return true; - } - return false; -} - -bool NamedProcessIterator::IncludeEntry() { - return (executable_name_ == entry().exe_file() && - ProcessIterator::IncludeEntry()); -} - -} // namespace base diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc deleted file mode 100644 index d94024f0c5..0000000000 --- a/base/process/process_metrics_mac.cc +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright (c) 2013 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. - -#include "base/process/process_metrics.h" - -#include <mach/mach.h> -#include <mach/mach_vm.h> -#include <mach/shared_region.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/sysctl.h> - -#include "base/containers/hash_tables.h" -#include "base/logging.h" -#include "base/mac/mach_logging.h" -#include "base/mac/scoped_mach_port.h" -#include "base/memory/ptr_util.h" -#include "base/numerics/safe_conversions.h" -#include "base/sys_info.h" - -#if !defined(TASK_POWER_INFO) -// Doesn't exist in the 10.6 or 10.7 SDKs. -#define TASK_POWER_INFO 21 -struct task_power_info { - uint64_t total_user; - uint64_t total_system; - uint64_t task_interrupt_wakeups; - uint64_t task_platform_idle_wakeups; - uint64_t task_timer_wakeups_bin_1; - uint64_t task_timer_wakeups_bin_2; -}; -typedef struct task_power_info task_power_info_data_t; -typedef struct task_power_info *task_power_info_t; -#define TASK_POWER_INFO_COUNT ((mach_msg_type_number_t) \ - (sizeof (task_power_info_data_t) / sizeof (natural_t))) -#endif - -namespace base { - -namespace { - -bool GetTaskInfo(mach_port_t task, task_basic_info_64* task_info_data) { - if (task == MACH_PORT_NULL) - return false; - mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; - kern_return_t kr = task_info(task, - TASK_BASIC_INFO_64, - reinterpret_cast<task_info_t>(task_info_data), - &count); - // Most likely cause for failure: |task| is a zombie. - return kr == KERN_SUCCESS; -} - -bool GetCPUTypeForProcess(pid_t /* pid */, cpu_type_t* cpu_type) { - size_t len = sizeof(*cpu_type); - int result = sysctlbyname("sysctl.proc_cputype", - cpu_type, - &len, - NULL, - 0); - if (result != 0) { - DPLOG(ERROR) << "sysctlbyname(""sysctl.proc_cputype"")"; - return false; - } - - return true; -} - -bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) { - if (type == CPU_TYPE_I386) { - return addr >= SHARED_REGION_BASE_I386 && - addr < (SHARED_REGION_BASE_I386 + SHARED_REGION_SIZE_I386); - } else if (type == CPU_TYPE_X86_64) { - return addr >= SHARED_REGION_BASE_X86_64 && - addr < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64); - } else { - return false; - } -} - -} // namespace - -// Getting a mach task from a pid for another process requires permissions in -// general, so there doesn't really seem to be a way to do these (and spinning -// up ps to fetch each stats seems dangerous to put in a base api for anyone to -// call). Child processes ipc their port, so return something if available, -// otherwise return 0. - -// static -std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics( - ProcessHandle process, - PortProvider* port_provider) { - return WrapUnique(new ProcessMetrics(process, port_provider)); -} - -size_t ProcessMetrics::GetPagefileUsage() const { - task_basic_info_64 task_info_data; - if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) - return 0; - return task_info_data.virtual_size; -} - -size_t ProcessMetrics::GetPeakPagefileUsage() const { - return 0; -} - -size_t ProcessMetrics::GetWorkingSetSize() const { - size_t private_bytes = 0; - size_t shared_bytes = 0; - size_t resident_bytes = 0; - if (!GetMemoryBytes(&private_bytes, &shared_bytes, &resident_bytes)) - return 0; - return resident_bytes; -} - -size_t ProcessMetrics::GetPeakWorkingSetSize() const { - return 0; -} - -// This is a rough approximation of the algorithm that libtop uses. -// private_bytes is the size of private resident memory. -// shared_bytes is the size of shared resident memory. -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) const { - size_t private_pages_count = 0; - size_t shared_pages_count = 0; - - if (!private_bytes && !shared_bytes) - return true; - - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) { - DLOG(ERROR) << "Invalid process"; - return false; - } - - cpu_type_t cpu_type; - if (!GetCPUTypeForProcess(process_, &cpu_type)) - return false; - - // The same region can be referenced multiple times. To avoid double counting - // we need to keep track of which regions we've already counted. - hash_set<int> seen_objects; - - // We iterate through each VM region in the task's address map. For shared - // memory we add up all the pages that are marked as shared. Like libtop we - // try to avoid counting pages that are also referenced by other tasks. Since - // we don't have access to the VM regions of other tasks the only hint we have - // is if the address is in the shared region area. - // - // Private memory is much simpler. We simply count the pages that are marked - // as private or copy on write (COW). - // - // See libtop_update_vm_regions in - // http://www.opensource.apple.com/source/top/top-67/libtop.c - mach_vm_size_t size = 0; - for (mach_vm_address_t address = MACH_VM_MIN_ADDRESS;; address += size) { - vm_region_top_info_data_t info; - mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; - mach_port_t object_name; - kern_return_t kr = mach_vm_region(task, - &address, - &size, - VM_REGION_TOP_INFO, - reinterpret_cast<vm_region_info_t>(&info), - &info_count, - &object_name); - if (kr == KERN_INVALID_ADDRESS) { - // We're at the end of the address space. - break; - } else if (kr != KERN_SUCCESS) { - MACH_DLOG(ERROR, kr) << "mach_vm_region"; - return false; - } - - // The kernel always returns a null object for VM_REGION_TOP_INFO, but - // balance it with a deallocate in case this ever changes. See 10.9.2 - // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. - mach_port_deallocate(mach_task_self(), object_name); - - if (IsAddressInSharedRegion(address, cpu_type) && - info.share_mode != SM_PRIVATE) - continue; - - if (info.share_mode == SM_COW && info.ref_count == 1) - info.share_mode = SM_PRIVATE; - - switch (info.share_mode) { - case SM_LARGE_PAGE: - case SM_PRIVATE: - private_pages_count += info.private_pages_resident; - private_pages_count += info.shared_pages_resident; - break; - case SM_COW: - private_pages_count += info.private_pages_resident; - // Fall through - case SM_SHARED: - case SM_PRIVATE_ALIASED: - case SM_TRUESHARED: - case SM_SHARED_ALIASED: - if (seen_objects.count(info.obj_id) == 0) { - // Only count the first reference to this region. - seen_objects.insert(info.obj_id); - shared_pages_count += info.shared_pages_resident; - } - break; - default: - break; - } - } - - if (private_bytes) - *private_bytes = private_pages_count * PAGE_SIZE; - if (shared_bytes) - *shared_bytes = shared_pages_count * PAGE_SIZE; - - return true; -} - -void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { - WorkingSetKBytes unused; - if (!GetCommittedAndWorkingSetKBytes(usage, &unused)) { - *usage = CommittedKBytes(); - } -} - -bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { - CommittedKBytes unused; - return GetCommittedAndWorkingSetKBytes(&unused, ws_usage); -} - -bool ProcessMetrics::GetCommittedAndWorkingSetKBytes( - CommittedKBytes* usage, - WorkingSetKBytes* ws_usage) const { - task_basic_info_64 task_info_data; - if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) - return false; - - usage->priv = task_info_data.virtual_size / 1024; - usage->mapped = 0; - usage->image = 0; - - ws_usage->priv = task_info_data.resident_size / 1024; - ws_usage->shareable = 0; - ws_usage->shared = 0; - - return true; -} - -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes, - size_t* resident_bytes) const { - if (!GetMemoryBytes(private_bytes, shared_bytes)) - return false; - *resident_bytes = *private_bytes + *shared_bytes; - return true; -} - -#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ - (r)->tv_sec = (a)->seconds; \ - (r)->tv_usec = (a)->microseconds; \ -} while (0) - -double ProcessMetrics::GetCPUUsage() { - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) - return 0; - - // Libtop explicitly loops over the threads (libtop_pinfo_update_cpu_usage() - // in libtop.c), but this is more concise and gives the same results: - task_thread_times_info thread_info_data; - mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; - kern_return_t kr = task_info(task, - TASK_THREAD_TIMES_INFO, - reinterpret_cast<task_info_t>(&thread_info_data), - &thread_info_count); - if (kr != KERN_SUCCESS) { - // Most likely cause: |task| is a zombie. - return 0; - } - - task_basic_info_64 task_info_data; - if (!GetTaskInfo(task, &task_info_data)) - return 0; - - /* Set total_time. */ - // thread info contains live time... - struct timeval user_timeval, system_timeval, task_timeval; - TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); - TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); - timeradd(&user_timeval, &system_timeval, &task_timeval); - - // ... task info contains terminated time. - TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); - TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); - timeradd(&user_timeval, &task_timeval, &task_timeval); - timeradd(&system_timeval, &task_timeval, &task_timeval); - - TimeTicks time = TimeTicks::Now(); - int64_t task_time = TimeValToMicroseconds(task_timeval); - - if (last_system_time_ == 0) { - // First call, just set the last values. - last_cpu_time_ = time; - last_system_time_ = task_time; - return 0; - } - - int64_t system_time_delta = task_time - last_system_time_; - int64_t time_delta = (time - last_cpu_time_).InMicroseconds(); - DCHECK_NE(0U, time_delta); - if (time_delta == 0) - return 0; - - last_cpu_time_ = time; - last_system_time_ = task_time; - - return static_cast<double>(system_time_delta * 100.0) / time_delta; -} - -int ProcessMetrics::GetIdleWakeupsPerSecond() { - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) - return 0; - - task_power_info power_info_data; - mach_msg_type_number_t power_info_count = TASK_POWER_INFO_COUNT; - kern_return_t kr = task_info(task, - TASK_POWER_INFO, - reinterpret_cast<task_info_t>(&power_info_data), - &power_info_count); - if (kr != KERN_SUCCESS) { - // Most likely cause: |task| is a zombie, or this is on a pre-10.8.4 system - // where TASK_POWER_INFO isn't supported yet. - return 0; - } - - // The task_power_info struct contains two wakeup counters: - // task_interrupt_wakeups and task_platform_idle_wakeups. - // task_interrupt_wakeups is the total number of wakeups generated by the - // process, and is the number that Activity Monitor reports. - // task_platform_idle_wakeups is a subset of task_interrupt_wakeups that - // tallies the number of times the processor was taken out of its low-power - // idle state to handle a wakeup. task_platform_idle_wakeups therefore result - // in a greater power increase than the other interrupts which occur while the - // CPU is already working, and reducing them has a greater overall impact on - // power usage. See the powermetrics man page for more info. - return CalculateIdleWakeupsPerSecond( - power_info_data.task_platform_idle_wakeups); -} - -bool ProcessMetrics::GetIOCounters(IoCounters* /* io_counters */) const { - return false; -} - -ProcessMetrics::ProcessMetrics(ProcessHandle process, - PortProvider* port_provider) - : process_(process), - last_system_time_(0), - last_absolute_idle_wakeups_(0), - port_provider_(port_provider) { - processor_count_ = SysInfo::NumberOfProcessors(); -} - -mach_port_t ProcessMetrics::TaskForPid(ProcessHandle /* process */) const { - mach_port_t task = MACH_PORT_NULL; - if (port_provider_) - task = port_provider_->TaskForPid(process_); - if (task == MACH_PORT_NULL && process_ == getpid()) - task = mach_task_self(); - return task; -} - -// Bytes committed by the system. -size_t GetSystemCommitCharge() { - base::mac::ScopedMachSendRight host(mach_host_self()); - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - vm_statistics_data_t data; - kern_return_t kr = host_statistics(host.get(), HOST_VM_INFO, - reinterpret_cast<host_info_t>(&data), - &count); - if (kr != KERN_SUCCESS) { - MACH_DLOG(WARNING, kr) << "host_statistics"; - return 0; - } - - return (data.active_count * PAGE_SIZE) / 1024; -} - -bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { - struct host_basic_info hostinfo; - mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; - base::mac::ScopedMachSendRight host(mach_host_self()); - int result = host_info(host.get(), HOST_BASIC_INFO, - reinterpret_cast<host_info_t>(&hostinfo), &count); - if (result != KERN_SUCCESS) - return false; - - DCHECK_EQ(HOST_BASIC_INFO_COUNT, count); - meminfo->total = static_cast<int>(hostinfo.max_mem / 1024); - - vm_statistics64_data_t vm_info; - count = HOST_VM_INFO64_COUNT; - - if (host_statistics64(host.get(), HOST_VM_INFO64, - reinterpret_cast<host_info64_t>(&vm_info), - &count) != KERN_SUCCESS) { - return false; - } - DCHECK_EQ(HOST_VM_INFO64_COUNT, count); - - static_assert(PAGE_SIZE % 1024 == 0, "Invalid page size"); - meminfo->free = saturated_cast<int>( - PAGE_SIZE / 1024 * (vm_info.free_count - vm_info.speculative_count)); - meminfo->speculative = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.speculative_count); - meminfo->file_backed = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.external_page_count); - meminfo->purgeable = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.purgeable_count); - - return true; -} - -} // namespace base diff --git a/base/strings/sys_string_conversions_mac.mm b/base/strings/sys_string_conversions_mac.mm deleted file mode 100644 index 32fe89cc36..0000000000 --- a/base/strings/sys_string_conversions_mac.mm +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/strings/sys_string_conversions.h" - -#import <Foundation/Foundation.h> -#include <stddef.h> - -#include <vector> - -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/strings/string_piece.h" - -namespace base { - -namespace { - -// Convert the supplied CFString into the specified encoding, and return it as -// an STL string of the template type. Returns an empty string on failure. -// -// Do not assert in this function since it is used by the asssertion code! -template<typename StringType> -static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, - CFStringEncoding encoding) { - CFIndex length = CFStringGetLength(cfstring); - if (length == 0) - return StringType(); - - CFRange whole_string = CFRangeMake(0, length); - CFIndex out_size; - CFIndex converted = CFStringGetBytes(cfstring, - whole_string, - encoding, - 0, // lossByte - false, // isExternalRepresentation - NULL, // buffer - 0, // maxBufLen - &out_size); - if (converted == 0 || out_size == 0) - return StringType(); - - // out_size is the number of UInt8-sized units needed in the destination. - // A buffer allocated as UInt8 units might not be properly aligned to - // contain elements of StringType::value_type. Use a container for the - // proper value_type, and convert out_size by figuring the number of - // value_type elements per UInt8. Leave room for a NUL terminator. - typename StringType::size_type elements = - out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; - - std::vector<typename StringType::value_type> out_buffer(elements); - converted = CFStringGetBytes(cfstring, - whole_string, - encoding, - 0, // lossByte - false, // isExternalRepresentation - reinterpret_cast<UInt8*>(&out_buffer[0]), - out_size, - NULL); // usedBufLen - if (converted == 0) - return StringType(); - - out_buffer[elements - 1] = '\0'; - return StringType(&out_buffer[0], elements - 1); -} - -// Given an STL string |in| with an encoding specified by |in_encoding|, -// convert it to |out_encoding| and return it as an STL string of the -// |OutStringType| template type. Returns an empty string on failure. -// -// Do not assert in this function since it is used by the asssertion code! -template<typename InStringType, typename OutStringType> -static OutStringType STLStringToSTLStringWithEncodingsT( - const InStringType& in, - CFStringEncoding in_encoding, - CFStringEncoding out_encoding) { - typename InStringType::size_type in_length = in.length(); - if (in_length == 0) - return OutStringType(); - - base::ScopedCFTypeRef<CFStringRef> cfstring(CFStringCreateWithBytesNoCopy( - NULL, - reinterpret_cast<const UInt8*>(in.data()), - in_length * sizeof(typename InStringType::value_type), - in_encoding, - false, - kCFAllocatorNull)); - if (!cfstring) - return OutStringType(); - - return CFStringToSTLStringWithEncodingT<OutStringType>(cfstring, - out_encoding); -} - -// Given an STL string |in| with an encoding specified by |in_encoding|, -// return it as a CFStringRef. Returns NULL on failure. -template<typename StringType> -static CFStringRef STLStringToCFStringWithEncodingsT( - const StringType& in, - CFStringEncoding in_encoding) { - typename StringType::size_type in_length = in.length(); - if (in_length == 0) - return CFSTR(""); - - return CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast<const UInt8*>(in.data()), - in_length * - sizeof(typename StringType::value_type), - in_encoding, - false); -} - -// Specify the byte ordering explicitly, otherwise CFString will be confused -// when strings don't carry BOMs, as they typically won't. -static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; -#ifdef __BIG_ENDIAN__ -static const CFStringEncoding kMediumStringEncoding = kCFStringEncodingUTF16BE; -static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32BE; -#elif defined(__LITTLE_ENDIAN__) -static const CFStringEncoding kMediumStringEncoding = kCFStringEncodingUTF16LE; -static const CFStringEncoding kWideStringEncoding = kCFStringEncodingUTF32LE; -#endif // __LITTLE_ENDIAN__ - -} // namespace - -// Do not assert in this function since it is used by the asssertion code! -std::string SysWideToUTF8(const std::wstring& wide) { - return STLStringToSTLStringWithEncodingsT<std::wstring, std::string>( - wide, kWideStringEncoding, kNarrowStringEncoding); -} - -// Do not assert in this function since it is used by the asssertion code! -std::wstring SysUTF8ToWide(const StringPiece& utf8) { - return STLStringToSTLStringWithEncodingsT<StringPiece, std::wstring>( - utf8, kNarrowStringEncoding, kWideStringEncoding); -} - -std::string SysWideToNativeMB(const std::wstring& wide) { - return SysWideToUTF8(wide); -} - -std::wstring SysNativeMBToWide(const StringPiece& native_mb) { - return SysUTF8ToWide(native_mb); -} - -CFStringRef SysUTF8ToCFStringRef(const std::string& utf8) { - return STLStringToCFStringWithEncodingsT(utf8, kNarrowStringEncoding); -} - -CFStringRef SysUTF16ToCFStringRef(const string16& utf16) { - return STLStringToCFStringWithEncodingsT(utf16, kMediumStringEncoding); -} - -NSString* SysUTF8ToNSString(const std::string& utf8) { - return (NSString*)base::mac::CFTypeRefToNSObjectAutorelease( - SysUTF8ToCFStringRef(utf8)); -} - -NSString* SysUTF16ToNSString(const string16& utf16) { - return (NSString*)base::mac::CFTypeRefToNSObjectAutorelease( - SysUTF16ToCFStringRef(utf16)); -} - -std::string SysCFStringRefToUTF8(CFStringRef ref) { - return CFStringToSTLStringWithEncodingT<std::string>(ref, - kNarrowStringEncoding); -} - -string16 SysCFStringRefToUTF16(CFStringRef ref) { - return CFStringToSTLStringWithEncodingT<string16>(ref, - kMediumStringEncoding); -} - -std::string SysNSStringToUTF8(NSString* nsstring) { - if (!nsstring) - return std::string(); - return SysCFStringRefToUTF8(reinterpret_cast<CFStringRef>(nsstring)); -} - -string16 SysNSStringToUTF16(NSString* nsstring) { - if (!nsstring) - return string16(); - return SysCFStringRefToUTF16(reinterpret_cast<CFStringRef>(nsstring)); -} - -} // namespace base diff --git a/base/sys_info_mac.mm b/base/sys_info_mac.mm deleted file mode 100644 index 1141bd5577..0000000000 --- a/base/sys_info_mac.mm +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 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. - -#include "base/sys_info.h" - -#include <ApplicationServices/ApplicationServices.h> -#include <CoreServices/CoreServices.h> -#import <Foundation/Foundation.h> -#include <mach/mach_host.h> -#include <mach/mach_init.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -#include "base/logging.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_mach_port.h" -#import "base/mac/sdk_forward_declarations.h" -#include "base/macros.h" -#include "base/process/process_metrics.h" -#include "base/strings/stringprintf.h" - -namespace base { - -// static -std::string SysInfo::OperatingSystemName() { - return "Mac OS X"; -} - -// static -std::string SysInfo::OperatingSystemVersion() { - int32_t major, minor, bugfix; - OperatingSystemVersionNumbers(&major, &minor, &bugfix); - return base::StringPrintf("%d.%d.%d", major, minor, bugfix); -} - -// static -void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version, - int32_t* minor_version, - int32_t* bugfix_version) { - NSProcessInfo* processInfo = [NSProcessInfo processInfo]; - if ([processInfo respondsToSelector:@selector(operatingSystemVersion)]) { - NSOperatingSystemVersion version = [processInfo operatingSystemVersion]; - *major_version = version.majorVersion; - *minor_version = version.minorVersion; - *bugfix_version = version.patchVersion; - } else { - // -[NSProcessInfo operatingSystemVersion] is documented available in 10.10. - // It's also available via a private API since 10.9.2. For the remaining - // cases in 10.9, rely on ::Gestalt(..). Since this code is only needed for - // 10.9.0 and 10.9.1 and uses the recommended replacement thereafter, - // suppress the warning for this fallback case. - DCHECK(base::mac::IsOS10_9()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - Gestalt(gestaltSystemVersionMajor, - reinterpret_cast<SInt32*>(major_version)); - Gestalt(gestaltSystemVersionMinor, - reinterpret_cast<SInt32*>(minor_version)); - Gestalt(gestaltSystemVersionBugFix, - reinterpret_cast<SInt32*>(bugfix_version)); -#pragma clang diagnostic pop - } -} - -// static -int64_t SysInfo::AmountOfPhysicalMemory() { - struct host_basic_info hostinfo; - mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; - base::mac::ScopedMachSendRight host(mach_host_self()); - int result = host_info(host.get(), - HOST_BASIC_INFO, - reinterpret_cast<host_info_t>(&hostinfo), - &count); - if (result != KERN_SUCCESS) { - NOTREACHED(); - return 0; - } - DCHECK_EQ(HOST_BASIC_INFO_COUNT, count); - return static_cast<int64_t>(hostinfo.max_mem); -} - -// static -int64_t SysInfo::AmountOfAvailablePhysicalMemory() { - SystemMemoryInfoKB info; - if (!GetSystemMemoryInfo(&info)) - return 0; - // We should add inactive file-backed memory also but there is no such - // information from Mac OS unfortunately. - return static_cast<int64_t>(info.free + info.speculative) * 1024; -} - -// static -std::string SysInfo::CPUModelName() { - char name[256]; - size_t len = arraysize(name); - if (sysctlbyname("machdep.cpu.brand_string", &name, &len, NULL, 0) == 0) - return name; - return std::string(); -} - -std::string SysInfo::HardwareModelName() { - char model[256]; - size_t len = sizeof(model); - if (sysctlbyname("hw.model", model, &len, NULL, 0) == 0) - return std::string(model, 0, len); - return std::string(); -} - -} // namespace base diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm deleted file mode 100644 index e743044ec1..0000000000 --- a/base/threading/platform_thread_mac.mm +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/threading/platform_thread.h" - -#import <Foundation/Foundation.h> -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <mach/thread_policy.h> -#include <stddef.h> -#include <sys/resource.h> - -#include <algorithm> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/mach_logging.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/tracked_objects.h" -#include "build/build_config.h" - -namespace base { - -namespace { -NSString* const kThreadPriorityKey = @"CrThreadPriorityKey"; -} // namespace - -// If Cocoa is to be used on more than one thread, it must know that the -// application is multithreaded. Since it's possible to enter Cocoa code -// from threads created by pthread_thread_create, Cocoa won't necessarily -// be aware that the application is multithreaded. Spawning an NSThread is -// enough to get Cocoa to set up for multithreaded operation, so this is done -// if necessary before pthread_thread_create spawns any threads. -// -// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html -void InitThreading() { - static BOOL multithreaded = [NSThread isMultiThreaded]; - if (!multithreaded) { - // +[NSObject class] is idempotent. - [NSThread detachNewThreadSelector:@selector(class) - toTarget:[NSObject class] - withObject:nil]; - multithreaded = YES; - - DCHECK([NSThread isMultiThreaded]); - } -} - -// static -void PlatformThread::SetName(const std::string& name) { - ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); - tracked_objects::ThreadData::InitializeThreadContext(name); - - // Mac OS X does not expose the length limit of the name, so - // hardcode it. - const int kMaxNameLength = 63; - std::string shortened_name = name.substr(0, kMaxNameLength); - // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does. - // See http://crbug.com/47058 - pthread_setname_np(shortened_name.c_str()); -} - -namespace { - -void SetPriorityNormal(mach_port_t mach_thread_id) { - // Make thread standard policy. - // Please note that this call could fail in rare cases depending - // on runtime conditions. - thread_standard_policy policy; - kern_return_t result = - thread_policy_set(mach_thread_id, - THREAD_STANDARD_POLICY, - reinterpret_cast<thread_policy_t>(&policy), - THREAD_STANDARD_POLICY_COUNT); - - if (result != KERN_SUCCESS) - MACH_DVLOG(1, result) << "thread_policy_set"; -} - -// Enables time-contraint policy and priority suitable for low-latency, -// glitch-resistant audio. -void SetPriorityRealtimeAudio(mach_port_t mach_thread_id) { - // Increase thread priority to real-time. - - // Please note that the thread_policy_set() calls may fail in - // rare cases if the kernel decides the system is under heavy load - // and is unable to handle boosting the thread priority. - // In these cases we just return early and go on with life. - - // Make thread fixed priority. - thread_extended_policy_data_t policy; - policy.timeshare = 0; // Set to 1 for a non-fixed thread. - kern_return_t result = - thread_policy_set(mach_thread_id, - THREAD_EXTENDED_POLICY, - reinterpret_cast<thread_policy_t>(&policy), - THREAD_EXTENDED_POLICY_COUNT); - if (result != KERN_SUCCESS) { - MACH_DVLOG(1, result) << "thread_policy_set"; - return; - } - - // Set to relatively high priority. - thread_precedence_policy_data_t precedence; - precedence.importance = 63; - result = thread_policy_set(mach_thread_id, - THREAD_PRECEDENCE_POLICY, - reinterpret_cast<thread_policy_t>(&precedence), - THREAD_PRECEDENCE_POLICY_COUNT); - if (result != KERN_SUCCESS) { - MACH_DVLOG(1, result) << "thread_policy_set"; - return; - } - - // Most important, set real-time constraints. - - // Define the guaranteed and max fraction of time for the audio thread. - // These "duty cycle" values can range from 0 to 1. A value of 0.5 - // means the scheduler would give half the time to the thread. - // These values have empirically been found to yield good behavior. - // Good means that audio performance is high and other threads won't starve. - const double kGuaranteedAudioDutyCycle = 0.75; - const double kMaxAudioDutyCycle = 0.85; - - // Define constants determining how much time the audio thread can - // use in a given time quantum. All times are in milliseconds. - - // About 128 frames @44.1KHz - const double kTimeQuantum = 2.9; - - // Time guaranteed each quantum. - const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum; - - // Maximum time each quantum. - const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum; - - // Get the conversion factor from milliseconds to absolute time - // which is what the time-constraints call needs. - mach_timebase_info_data_t tb_info; - mach_timebase_info(&tb_info); - double ms_to_abs_time = - (static_cast<double>(tb_info.denom) / tb_info.numer) * 1000000; - - thread_time_constraint_policy_data_t time_constraints; - time_constraints.period = kTimeQuantum * ms_to_abs_time; - time_constraints.computation = kAudioTimeNeeded * ms_to_abs_time; - time_constraints.constraint = kMaxTimeAllowed * ms_to_abs_time; - time_constraints.preemptible = 0; - - result = - thread_policy_set(mach_thread_id, - THREAD_TIME_CONSTRAINT_POLICY, - reinterpret_cast<thread_policy_t>(&time_constraints), - THREAD_TIME_CONSTRAINT_POLICY_COUNT); - MACH_DVLOG_IF(1, result != KERN_SUCCESS, result) << "thread_policy_set"; - - return; -} - -} // anonymous namespace - -// static -bool PlatformThread::CanIncreaseCurrentThreadPriority() { - return true; -} - -// static -void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { - // Convert from pthread_t to mach thread identifier. - mach_port_t mach_thread_id = - pthread_mach_thread_np(PlatformThread::CurrentHandle().platform_handle()); - - switch (priority) { - case ThreadPriority::NORMAL: - case ThreadPriority::BACKGROUND: - case ThreadPriority::DISPLAY: - // Add support for non-NORMAL thread priorities. https://crbug.com/554651 - SetPriorityNormal(mach_thread_id); - break; - case ThreadPriority::REALTIME_AUDIO: - SetPriorityRealtimeAudio(mach_thread_id); - break; - } - - [[[NSThread currentThread] threadDictionary] - setObject:@(static_cast<int>(priority)) - forKey:kThreadPriorityKey]; -} - -// static -ThreadPriority PlatformThread::GetCurrentThreadPriority() { - NSNumber* priority = base::mac::ObjCCast<NSNumber>([[[NSThread currentThread] - threadDictionary] objectForKey:kThreadPriorityKey]); - - if (!priority) - return ThreadPriority::NORMAL; - - ThreadPriority thread_priority = - static_cast<ThreadPriority>(priority.intValue); - switch (thread_priority) { - case ThreadPriority::BACKGROUND: - case ThreadPriority::NORMAL: - case ThreadPriority::DISPLAY: - case ThreadPriority::REALTIME_AUDIO: - return thread_priority; - default: - NOTREACHED() << "Unknown priority."; - return ThreadPriority::NORMAL; - } -} - -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { -#if defined(OS_IOS) - return 0; -#else - // The Mac OS X default for a pthread stack size is 512kB. - // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses - // DEFAULT_STACK_SIZE for this purpose. - // - // 512kB isn't quite generous enough for some deeply recursive threads that - // otherwise request the default stack size by specifying 0. Here, adopt - // glibc's behavior as on Linux, which is to use the current stack size - // limit (ulimit -s) as the default stack size. See - // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To - // avoid setting the limit below the Mac OS X default or the minimum usable - // stack size, these values are also considered. If any of these values - // can't be determined, or if stack size is unlimited (ulimit -s unlimited), - // stack_size is left at 0 to get the system default. - // - // Mac OS X normally only applies ulimit -s to the main thread stack. On - // contemporary OS X and Linux systems alike, this value is generally 8MB - // or in that neighborhood. - size_t default_stack_size = 0; - struct rlimit stack_rlimit; - if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 && - getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 && - stack_rlimit.rlim_cur != RLIM_INFINITY) { - default_stack_size = - std::max(std::max(default_stack_size, - static_cast<size_t>(PTHREAD_STACK_MIN)), - static_cast<size_t>(stack_rlimit.rlim_cur)); - } - return default_stack_size; -#endif -} - -void TerminateOnThread() { -} - -} // namespace base diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc deleted file mode 100644 index c75423df9c..0000000000 --- a/base/time/time_mac.cc +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/time/time.h" - -#include <CoreFoundation/CFDate.h> -#include <CoreFoundation/CFTimeZone.h> -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/sysctl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <time.h> - -#include "base/logging.h" -#include "base/mac/mach_logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_mach_port.h" -#include "base/macros.h" -#include "base/numerics/safe_conversions.h" -#include "build/build_config.h" - -namespace { - -#if defined(OS_MACOSX) && !defined(OS_IOS) -int64_t MachAbsoluteTimeToTicks(uint64_t mach_absolute_time) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - // Zero-initialization of statics guarantees that denom will be 0 before - // calling mach_timebase_info. mach_timebase_info will never set denom to - // 0 as that would be invalid, so the zero-check can be used to determine - // whether mach_timebase_info has already been called. This is - // recommended by Apple's QA1398. - kern_return_t kr = mach_timebase_info(&timebase_info); - MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info"; - } - - // timebase_info converts absolute time tick units into nanoseconds. Convert - // to microseconds up front to stave off overflows. - base::CheckedNumeric<uint64_t> result(mach_absolute_time / - base::Time::kNanosecondsPerMicrosecond); - result *= timebase_info.numer; - result /= timebase_info.denom; - - // Don't bother with the rollover handling that the Windows version does. - // With numer and denom = 1 (the expected case), the 64-bit absolute time - // reported in nanoseconds is enough to last nearly 585 years. - return base::checked_cast<int64_t>(result.ValueOrDie()); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -int64_t ComputeCurrentTicks() { -#if defined(OS_IOS) - // On iOS mach_absolute_time stops while the device is sleeping. Instead use - // now - KERN_BOOTTIME to get a time difference that is not impacted by clock - // changes. KERN_BOOTTIME will be updated by the system whenever the system - // clock change. - struct timeval boottime; - int mib[2] = {CTL_KERN, KERN_BOOTTIME}; - size_t size = sizeof(boottime); - int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0); - DCHECK_EQ(KERN_SUCCESS, kr); - base::TimeDelta time_difference = - base::Time::Now() - (base::Time::FromTimeT(boottime.tv_sec) + - base::TimeDelta::FromMicroseconds(boottime.tv_usec)); - return time_difference.InMicroseconds(); -#else - // mach_absolute_time is it when it comes to ticks on the Mac. Other calls - // with less precision (such as TickCount) just call through to - // mach_absolute_time. - return MachAbsoluteTimeToTicks(mach_absolute_time()); -#endif // defined(OS_IOS) -} - -int64_t ComputeThreadTicks() { -#if defined(OS_IOS) - NOTREACHED(); - return 0; -#else - base::mac::ScopedMachSendRight thread(mach_thread_self()); - mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT; - thread_basic_info_data_t thread_info_data; - - if (thread.get() == MACH_PORT_NULL) { - DLOG(ERROR) << "Failed to get mach_thread_self()"; - return 0; - } - - kern_return_t kr = thread_info( - thread.get(), - THREAD_BASIC_INFO, - reinterpret_cast<thread_info_t>(&thread_info_data), - &thread_info_count); - MACH_DCHECK(kr == KERN_SUCCESS, kr) << "thread_info"; - - base::CheckedNumeric<int64_t> absolute_micros( - thread_info_data.user_time.seconds + - thread_info_data.system_time.seconds); - absolute_micros *= base::Time::kMicrosecondsPerSecond; - absolute_micros += (thread_info_data.user_time.microseconds + - thread_info_data.system_time.microseconds); - return absolute_micros.ValueOrDie(); -#endif // defined(OS_IOS) -} - -} // namespace - -namespace base { - -// The Time routines in this file use Mach and CoreFoundation APIs, since the -// POSIX definition of time_t in Mac OS X wraps around after 2038--and -// there are already cookie expiration dates, etc., past that time out in -// the field. Using CFDate prevents that problem, and using mach_absolute_time -// for TimeTicks gives us nice high-resolution interval timing. - -// Time ----------------------------------------------------------------------- - -// Core Foundation uses a double second count since 2001-01-01 00:00:00 UTC. -// The UNIX epoch is 1970-01-01 00:00:00 UTC. -// Windows uses a Gregorian epoch of 1601. We need to match this internally -// so that our time representations match across all platforms. See bug 14734. -// irb(main):010:0> Time.at(0).getutc() -// => Thu Jan 01 00:00:00 UTC 1970 -// irb(main):011:0> Time.at(-11644473600).getutc() -// => Mon Jan 01 00:00:00 UTC 1601 -static const int64_t kWindowsEpochDeltaSeconds = INT64_C(11644473600); - -// static -const int64_t Time::kWindowsEpochDeltaMicroseconds = - kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; - -// Some functions in time.cc use time_t directly, so we provide an offset -// to convert from time_t (Unix epoch) and internal (Windows epoch). -// static -const int64_t Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; - -// static -Time Time::Now() { - return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); -} - -// static -Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { - static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, - "CFAbsoluteTime must have an infinity value"); - if (t == 0) - return Time(); // Consider 0 as a null Time. - if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) - return Max(); - return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) * - kMicrosecondsPerSecond) + - kWindowsEpochDeltaMicroseconds); -} - -CFAbsoluteTime Time::ToCFAbsoluteTime() const { - static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, - "CFAbsoluteTime must have an infinity value"); - if (is_null()) - return 0; // Consider 0 as a null Time. - if (is_max()) - return std::numeric_limits<CFAbsoluteTime>::infinity(); - return (static_cast<CFAbsoluteTime>(us_ - kWindowsEpochDeltaMicroseconds) / - kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970; -} - -// static -Time Time::NowFromSystemTime() { - // Just use Now() because Now() returns the system time. - return Now(); -} - -// static -bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { - base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( - is_local - ? CFTimeZoneCopySystem() - : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); - base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( - kCFAllocatorDefault, kCFGregorianCalendar)); - CFCalendarSetTimeZone(gregorian, time_zone); - CFAbsoluteTime absolute_time; - // 'S' is not defined in componentDesc in Apple documentation, but can be - // found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c - CFCalendarComposeAbsoluteTime( - gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month, - exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, - exploded.millisecond); - CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970; - - // CFAbsolutTime is typedef of double. Convert seconds to - // microseconds and then cast to int64. If - // it cannot be suited to int64, then fail to avoid overflows. - double microseconds = - (seconds * kMicrosecondsPerSecond) + kWindowsEpochDeltaMicroseconds; - if (microseconds > std::numeric_limits<int64_t>::max() || - microseconds < std::numeric_limits<int64_t>::min()) { - *time = Time(0); - return false; - } - - base::Time converted_time = Time(static_cast<int64_t>(microseconds)); - - // If |exploded.day_of_month| is set to 31 - // on a 28-30 day month, it will return the first day of the next month. - // Thus round-trip the time and compare the initial |exploded| with - // |utc_to_exploded| time. - base::Time::Exploded to_exploded; - if (!is_local) - converted_time.UTCExplode(&to_exploded); - else - converted_time.LocalExplode(&to_exploded); - - if (ExplodedMostlyEquals(to_exploded, exploded)) { - *time = converted_time; - return true; - } - - *time = Time(0); - return false; -} - -void Time::Explode(bool is_local, Exploded* exploded) const { - // Avoid rounding issues, by only putting the integral number of seconds - // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|). - int64_t microsecond = us_ % kMicrosecondsPerSecond; - if (microsecond < 0) - microsecond += kMicrosecondsPerSecond; - CFAbsoluteTime seconds = ((us_ - microsecond) / kMicrosecondsPerSecond) - - kWindowsEpochDeltaSeconds - - kCFAbsoluteTimeIntervalSince1970; - - base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( - is_local - ? CFTimeZoneCopySystem() - : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); - base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( - kCFAllocatorDefault, kCFGregorianCalendar)); - CFCalendarSetTimeZone(gregorian, time_zone); - int second, day_of_week; - // 'E' sets the day of week, but is not defined in componentDesc in Apple - // documentation. It can be found in open source code here: - // http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c - CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE", - &exploded->year, &exploded->month, - &exploded->day_of_month, &exploded->hour, - &exploded->minute, &second, &day_of_week); - // Make sure seconds are rounded down towards -infinity. - exploded->second = floor(second); - // |Exploded|'s convention for day of week is 0 = Sunday, i.e. different - // from CF's 1 = Sunday. - exploded->day_of_week = (day_of_week - 1) % 7; - // Calculate milliseconds ourselves, since we rounded the |seconds|, making - // sure to round towards -infinity. - exploded->millisecond = - (microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond : - (microsecond - kMicrosecondsPerMillisecond + 1) / - kMicrosecondsPerMillisecond; -} - -// TimeTicks ------------------------------------------------------------------ - -// static -TimeTicks TimeTicks::Now() { - return TimeTicks(ComputeCurrentTicks()); -} - -// static -bool TimeTicks::IsHighResolution() { - return true; -} - -// static -bool TimeTicks::IsConsistentAcrossProcesses() { - return true; -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// static -TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) { - return TimeTicks(MachAbsoluteTimeToTicks(mach_absolute_time)); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -// static -TimeTicks::Clock TimeTicks::GetClock() { -#if defined(OS_IOS) - return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME; -#else - return Clock::MAC_MACH_ABSOLUTE_TIME; -#endif // defined(OS_IOS) -} - -// static -ThreadTicks ThreadTicks::Now() { - return ThreadTicks(ComputeThreadTicks()); -} - -} // namespace base |