Last active
December 17, 2015 11:49
-
-
Save titanous/5604757 to your computer and use it in GitHub Desktop.
NSProgress classdump from Foundation.framework and usage in Chrome
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Generated by class-dump 3.4 (64 bit). | |
* | |
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2012 by Steve Nygard. | |
*/ | |
@protocol NSProgressPublisher <NSObject> | |
- (oneway void)appWithBundleID:(id)arg1 didAcknowledgeWithSuccess:(BOOL)arg2; | |
- (oneway void)pause; | |
- (oneway void)cancel; | |
- (oneway void)stopProvidingValues; | |
- (oneway void)startProvidingValuesWithInitialAcceptor:(id)arg1; | |
@end | |
@protocol NSProgressRegistrar | |
- (oneway void)removeSubscriberForID:(id)arg1; | |
- (oneway void)addSubscriber:(id)arg1 forID:(id)arg2 appBundleID:(id)arg3 fileURL:(id)arg4; | |
- (oneway void)removePublisherForID:(id)arg1; | |
- (oneway void)observePublisherForID:(id)arg1 value:(id)arg2 forKey:(id)arg3 inUserInfo:(BOOL)arg4; | |
- (oneway void)addPublisher:(id)arg1 forID:(id)arg2 acknowledgementAppBundleIDs:(id)arg3 fileURL:(id)arg4; | |
@end | |
@protocol NSProgressSubscriber <NSObject> | |
- (oneway void)removePublisherForID:(id)arg1; | |
- (oneway void)observePublisherForID:(id)arg1 value:(id)arg2 forKey:(id)arg3 inUserInfo:(BOOL)arg4; | |
- (oneway void)addPublisher:(id)arg1 forID:(id)arg2 withValues:(id)arg3 isOld:(BOOL)arg4; | |
@end | |
@interface NSProgress : NSObject <NSProgressPublisher> | |
{ | |
NSProgress *_parent; | |
long long _portionOfParentUnitCount; | |
id _values; | |
id _valuesSeenFromMainThread; | |
id _cancellationHandler; | |
id _pausingHandler; | |
long long _pendingUnitCount; | |
id _userInfoProxy; | |
NSString *_publisherID; | |
NSXPCConnection *_connection; | |
long long _unpublishingBlockageCount; | |
long long _remoteObserverCount; | |
NSMutableDictionary *_acknowledgementHandlersByBundleID; | |
NSMutableDictionary *_lastNotificationTimesByKey; | |
NSMutableDictionary *_userInfoLastNotificationTimesByKey; | |
id _reserved1; | |
id _reserved2; | |
} | |
+ (void)removeSubscriber:(id)arg1; | |
+ (id)addSubscriberForFileURL:(id)arg1 usingBlock:(id)arg2; | |
+ (id)keyPathsForValuesAffectingFractionCompleted; | |
+ (id)keyPathsForValuesAffectingLocalizedDescription; | |
+ (BOOL)automaticallyNotifiesObserversForKey:(id)arg1; | |
+ (id)progressWithTotalUnitCount:(long long)arg1; | |
+ (id)currentProgress; | |
+ (id)_registrarInterface; | |
+ (id)_subscriberInterface; | |
+ (id)_publisherInterface; | |
@property(readonly, getter=isOld) BOOL old; | |
- (void)acknowledgeWithSuccess:(BOOL)arg1; | |
- (oneway void)appWithBundleID:(id)arg1 didAcknowledgeWithSuccess:(BOOL)arg2; | |
- (oneway void)stopProvidingValues; | |
- (oneway void)startProvidingValuesWithInitialAcceptor:(id)arg1; | |
- (void)handleAcknowledgementByAppWithBundleIdentifier:(id)arg1 usingBlock:(id)arg2; | |
- (void)unpublish; | |
- (void)_unblockUnpublishing; | |
- (void)publish; | |
@property(copy) NSString *kind; | |
- (id)ownedDictionaryObjectForKey:(id)arg1; | |
- (id)ownedDictionaryKeyEnumerator; | |
- (unsigned long long)ownedDictionaryCount; | |
- (id)userInfo; | |
- (void)pause; | |
- (void)_pause; | |
- (void)cancel; | |
- (void)_cancel; | |
@property(readonly) double fractionCompleted; | |
- (double)_fractionCompletedUsingValuesFinder:(id)arg1; | |
@property(readonly, getter=isIndeterminate) BOOL indeterminate; | |
- (void)setUserInfoObject:(id)arg1 forKey:(id)arg2; | |
- (void)_setUserInfoValue:(id)arg1 forKey:(id)arg2; | |
- (void)setPausingHandler:(id)arg1; | |
- (void)setCancellationHandler:(id)arg1; | |
@property(readonly, getter=isPaused) BOOL paused; | |
@property(readonly, getter=isCancelled) BOOL cancelled; | |
@property(getter=isPausable) BOOL pausable; | |
@property(getter=isCancellable) BOOL cancellable; | |
@property(copy) NSString *localizedDescription; | |
@property long long completedUnitCount; | |
@property long long totalUnitCount; | |
- (void)_getValueUsingBlock:(id)arg1; | |
- (void)_setValueForKey:(id)arg1 usingBlock:(id)arg2; | |
- (void)__setValueForKey:(id)arg1 usingBlock:(id)arg2; | |
- (void)_notifyRemoteObserversOfValueForKey:(id)arg1 inUserInfo:(BOOL)arg2; | |
- (void)__notifyRemoteObserversOfValueForKey:(id)arg1 inUserInfo:(BOOL)arg2; | |
- (void)resignCurrent; | |
- (void)becomeCurrentWithPendingUnitCount:(long long)arg1; | |
- (void)dealloc; | |
- (id)initWithParent:(id)arg1 userInfo:(id)arg2; | |
- (id)init; | |
- (void)_setValue:(id)arg1 forKey:(id)arg2 inUserInfo:(BOOL)arg3; | |
- (id)_initWithValues:(id)arg1; | |
@property(readonly) NSString *localizedItemCountDescription; | |
- (void)acknowledge; | |
- (void)handleAcknowledgementByAppWithBundleIdentifer:(id)arg1 usingBlock:(id)arg2; | |
@end | |
__attribute__((visibility("hidden"))) | |
@interface NSProgressPublisherProxy : NSObject <NSProgressPublisher> | |
{ | |
id <NSProgressPublisher> _forwarder; | |
id _publisherID; | |
NSFileAccessNode *_itemLocation; | |
NSMutableSet *_bundleIDsOfUnacknowledgedApps; | |
} | |
- (id)description; | |
- (id)descriptionWithIndenting:(id)arg1; | |
- (oneway void)appWithBundleID:(id)arg1 didAcknowledgeWithSuccess:(BOOL)arg2; | |
- (oneway void)pause; | |
- (oneway void)cancel; | |
- (oneway void)stopProvidingValues; | |
- (oneway void)startProvidingValuesWithInitialAcceptor:(id)arg1; | |
- (void)broadcastValue:(id)arg1 forKey:(id)arg2 inUserInfo:(BOOL)arg3; | |
- (void)setItemLocation:(id)arg1; | |
- (id)publisherID; | |
- (void)dealloc; | |
- (id)initWithForwarder:(id)arg1 publisherID:(id)arg2 acknowledgementAppBundleIDs:(id)arg3; | |
@end | |
__attribute__((visibility("hidden"))) | |
@interface NSProgressSubscriberProxy : NSObject <NSProgressSubscriber> | |
{ | |
id <NSProgressSubscriber> _forwarder; | |
id _subscriberID; | |
NSFileAccessNode *_itemLocation; | |
NSString *_appBundleIDOrNil; | |
} | |
- (id)description; | |
- (id)descriptionWithIndenting:(id)arg1; | |
- (oneway void)removePublisherForID:(id)arg1; | |
- (oneway void)observePublisherForID:(id)arg1 value:(id)arg2 forKey:(id)arg3 inUserInfo:(BOOL)arg4; | |
- (oneway void)addPublisher:(id)arg1 forID:(id)arg2 withValues:(id)arg3 isOld:(BOOL)arg4; | |
- (void)setItemLocation:(id)arg1; | |
- (id)appBundleID; | |
- (void)dealloc; | |
- (id)initWithForwarder:(id)arg1 subscriberID:(id)arg2 appBundleID:(id)arg3; | |
@end | |
@interface NSProgressRegistrar : NSObject <NSXPCListenerDelegate, NSProgressRegistrar> | |
{ | |
struct dispatch_queue_s *_queue; | |
NSFileAccessNode *_rootFileAccessNode; | |
NSMutableDictionary *_publishersAndSubscribersByID; | |
} | |
- (oneway void)removeSubscriberForID:(id)arg1; | |
- (oneway void)addSubscriber:(id)arg1 forID:(id)arg2 appBundleID:(id)arg3 fileURL:(id)arg4; | |
- (oneway void)removePublisherForID:(id)arg1; | |
- (oneway void)observePublisherForID:(id)arg1 value:(id)arg2 forKey:(id)arg3 inUserInfo:(BOOL)arg4; | |
- (oneway void)addPublisher:(id)arg1 forID:(id)arg2 acknowledgementAppBundleIDs:(id)arg3 fileURL:(id)arg4; | |
- (BOOL)listener:(id)arg1 shouldAcceptNewConnection:(id)arg2; | |
- (void)finalize; | |
- (void)dealloc; | |
- (id)initWithQueue:(struct dispatch_queue_s *)arg1 rootFileAccessNode:(id)arg2; | |
@end | |
__attribute__((visibility("hidden"))) | |
@interface NSProgressProxy : NSProgress | |
{ | |
id <NSProgressPublisher> _forwarder; | |
BOOL _isOld; | |
id _unpublishingHandler; | |
} | |
- (BOOL)isOld; | |
- (void)acknowledgeWithSuccess:(BOOL)arg1; | |
- (void)pause; | |
- (void)cancel; | |
- (void)unpublish; | |
- (void)publish; | |
- (void)setKind:(id)arg1; | |
- (void)setUserInfoObject:(id)arg1 forKey:(id)arg2; | |
- (void)setPausingHandler:(id)arg1; | |
- (void)setCancellationHandler:(id)arg1; | |
- (void)setPausable:(BOOL)arg1; | |
- (void)setCancellable:(BOOL)arg1; | |
- (void)setLocalizedDescription:(id)arg1; | |
- (void)setCompletedUnitCount:(long long)arg1; | |
- (void)setTotalUnitCount:(long long)arg1; | |
- (void)resignCurrent; | |
- (void)becomeCurrentWithPendingUnitCount:(long long)arg1; | |
- (void)_invokeUnpublishingHandler; | |
- (void)_invokePublishingHandler:(id)arg1; | |
- (void)dealloc; | |
- (id)_initWithForwarder:(id)arg1 values:(id)arg2 isOld:(BOOL)arg3; | |
@end | |
@interface NSProgressSubscriber : NSObject <NSProgressSubscriber> | |
{ | |
id _publishingHandler; | |
NSString *_subscriberID; | |
struct dispatch_queue_s *_queue; | |
NSMutableDictionary *_proxiesByPublisherID; | |
NSXPCConnection *_connection; | |
} | |
- (oneway void)removePublisherForID:(id)arg1; | |
- (oneway void)observePublisherForID:(id)arg1 value:(id)arg2 forKey:(id)arg3 inUserInfo:(BOOL)arg4; | |
- (oneway void)addPublisher:(id)arg1 forID:(id)arg2 withValues:(id)arg3 isOld:(BOOL)arg4; | |
- (void)stop; | |
- (void)startForFileURL:(id)arg1; | |
- (void)finalize; | |
- (void)dealloc; | |
- (id)initWithPublishingHandler:(id)arg1; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 "chrome/browser/download/download_status_updater.h" | |
#include "base/mac/foundation_util.h" | |
#include "base/memory/scoped_nsobject.h" | |
#include "base/supports_user_data.h" | |
#include "base/strings/sys_string_conversions.h" | |
#include "content/public/browser/download_item.h" | |
#import "chrome/browser/ui/cocoa/dock_icon.h" | |
#include "googleurl/src/gurl.h" | |
// --- Private 10.8 API for showing progress --- | |
// rdar://12058866 http://www.openradar.me/12058866 | |
namespace { | |
NSString* const kNSProgressAppBundleIdentifierKey = | |
@"NSProgressAppBundleIdentifierKey"; | |
NSString* const kNSProgressEstimatedTimeKey = | |
@"NSProgressEstimatedTimeKey"; | |
NSString* const kNSProgressFileCompletedCountKey = | |
@"NSProgressFileCompletedCountKey"; | |
NSString* const kNSProgressFileContainerURLKey = | |
@"NSProgressFileContainerURLKey"; | |
NSString* const kNSProgressFileDownloadingSourceURLKey = | |
@"NSProgressFileDownloadingSourceURLKey"; | |
NSString* const kNSProgressFileIconKey = | |
@"NSProgressFileIconKey"; | |
NSString* const kNSProgressFileIconOriginalRectKey = | |
@"NSProgressFileIconOriginalRectKey"; | |
NSString* const kNSProgressFileLocationCanChangeKey = | |
@"NSProgressFileLocationCanChangeKey"; | |
NSString* const kNSProgressFileOperationKindAirDropping = | |
@"NSProgressFileOperationKindAirDropping"; | |
NSString* const kNSProgressFileOperationKindCopying = | |
@"NSProgressFileOperationKindCopying"; | |
NSString* const kNSProgressFileOperationKindDecompressingAfterDownloading = | |
@"NSProgressFileOperationKindDecompressingAfterDownloading"; | |
NSString* const kNSProgressFileOperationKindDownloading = | |
@"NSProgressFileOperationKindDownloading"; | |
NSString* const kNSProgressFileOperationKindEncrypting = | |
@"NSProgressFileOperationKindEncrypting"; | |
NSString* const kNSProgressFileOperationKindKey = | |
@"NSProgressFileOperationKindKey"; | |
NSString* const kNSProgressFileTotalCountKey = | |
@"NSProgressFileTotalCountKey"; | |
NSString* const kNSProgressFileURLKey = | |
@"NSProgressFileURLKey"; | |
NSString* const kNSProgressIsWaitingKey = | |
@"NSProgressIsWaitingKey"; | |
NSString* const kNSProgressKindFile = | |
@"NSProgressKindFile"; | |
NSString* const kNSProgressThroughputKey = | |
@"NSProgressThroughputKey"; | |
NSString* ProgressString(NSString* string) { | |
static NSMutableDictionary* cache; | |
static CFBundleRef foundation; | |
if (!cache) { | |
cache = [[NSMutableDictionary alloc] init]; | |
foundation = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Foundation")); | |
} | |
NSString* result = [cache objectForKey:string]; | |
if (!result) { | |
NSString** ref = static_cast<NSString**>( | |
CFBundleGetDataPointerForName(foundation, | |
base::mac::NSToCFCast(string))); | |
if (ref) { | |
result = *ref; | |
[cache setObject:result forKey:string]; | |
} | |
} | |
if (!result) { | |
// Huh. At least return a local copy of the expected string. | |
result = string; | |
NSString* const kKeySuffix = @"Key"; | |
if ([result hasSuffix:kKeySuffix]) | |
result = [result substringToIndex:[result length] - [kKeySuffix length]]; | |
} | |
return result; | |
} | |
} // namespace | |
@interface NSProgress : NSObject | |
- (id)initWithParent:(id)parent userInfo:(NSDictionary*)info; | |
@property(copy) NSString* kind; | |
- (void)unpublish; | |
- (void)publish; | |
- (void)setUserInfoObject:(id)object forKey:(NSString*)key; | |
- (NSDictionary*)userInfo; | |
@property(readonly) double fractionCompleted; | |
// Set the totalUnitCount to -1 to indicate an indeterminate download. The dock | |
// shows a non-filling progress bar; the Finder is lame and draws its progress | |
// bar off the right side. | |
@property(readonly, getter=isIndeterminate) BOOL indeterminate; | |
@property long long completedUnitCount; | |
@property long long totalUnitCount; | |
// Pausing appears to be unimplemented in 10.8.0. | |
- (void)pause; | |
@property(readonly, getter=isPaused) BOOL paused; | |
@property(getter=isPausable) BOOL pausable; | |
- (void)setPausingHandler:(id)blockOfUnknownSignature; | |
- (void)cancel; | |
@property(readonly, getter=isCancelled) BOOL cancelled; | |
@property(getter=isCancellable) BOOL cancellable; | |
// Note that the cancellation handler block will be called on a random thread. | |
- (void)setCancellationHandler:(void (^)())block; | |
// Allows other applications to provide feedback as to whether the progress is | |
// visible in that app. Note that the acknowledgement handler block will be | |
// called on a random thread. | |
// com.apple.dock => BOOL indicating whether the download target folder was | |
// successfully "flown to" at the beginning of the download. | |
// This primarily depends on whether the download target | |
// folder is in the dock. Note that if the download target | |
// folder is added or removed from the dock during the | |
// duration of the download, it will not trigger a callback. | |
// Note that if the "fly to the dock" keys were not set, the | |
// callback's parameter will always be NO. | |
// com.apple.Finder => always YES, no matter whether the download target | |
// folder's window is open. | |
- (void)handleAcknowledgementByAppWithBundleIdentifier:(NSString*)bundle | |
usingBlock:(void (^)(BOOL success))block; | |
@end | |
// --- Private 10.8 API for showing progress --- | |
namespace { | |
bool NSProgressSupported() { | |
static bool supported; | |
static bool valid; | |
if (!valid) { | |
supported = NSClassFromString(@"NSProgress"); | |
valid = true; | |
} | |
return supported; | |
} | |
const char kCrNSProgressUserDataKey[] = "CrNSProgressUserData"; | |
class CrNSProgressUserData : public base::SupportsUserData::Data { | |
public: | |
CrNSProgressUserData(NSProgress* progress, const base::FilePath& target) | |
: target_(target) { | |
progress_.reset(progress); | |
} | |
virtual ~CrNSProgressUserData() { | |
[progress_.get() unpublish]; | |
} | |
NSProgress* progress() const { return progress_.get(); } | |
base::FilePath target() const { return target_; } | |
void setTarget(const base::FilePath& target) { target_ = target; } | |
private: | |
scoped_nsobject<NSProgress> progress_; | |
base::FilePath target_; | |
}; | |
void UpdateAppIcon(int download_count, | |
bool progress_known, | |
float progress) { | |
DockIcon* dock_icon = [DockIcon sharedDockIcon]; | |
[dock_icon setDownloads:download_count]; | |
[dock_icon setIndeterminate:!progress_known]; | |
[dock_icon setProgress:progress]; | |
[dock_icon updateIcon]; | |
} | |
void CreateNSProgress(content::DownloadItem* download) { | |
NSURL* source_url = [NSURL URLWithString: | |
base::SysUTF8ToNSString(download->GetURL().possibly_invalid_spec())]; | |
base::FilePath destination_path = download->GetFullPath(); | |
NSURL* destination_url = [NSURL fileURLWithPath: | |
base::mac::FilePathToNSString(destination_path)]; | |
// If there were an image to fly to the download folder in the dock, then | |
// the keys in the userInfo to set would be: | |
// - @"NSProgressFlyToImageKey" : NSImage | |
// - kNSProgressFileIconOriginalRectKey : NSValue of NSRect in global coords | |
NSDictionary* user_info = @{ | |
ProgressString(kNSProgressFileLocationCanChangeKey) : @true, | |
ProgressString(kNSProgressFileOperationKindKey) : | |
ProgressString(kNSProgressFileOperationKindDownloading), | |
ProgressString(kNSProgressFileURLKey) : destination_url | |
}; | |
Class progress_class = NSClassFromString(@"NSProgress"); | |
NSProgress* progress = [progress_class performSelector:@selector(alloc)]; | |
progress = [progress performSelector:@selector(initWithParent:userInfo:) | |
withObject:nil | |
withObject:user_info]; | |
progress.kind = ProgressString(kNSProgressKindFile); | |
if (source_url) { | |
[progress setUserInfoObject:source_url forKey: | |
ProgressString(kNSProgressFileDownloadingSourceURLKey)]; | |
} | |
progress.pausable = NO; | |
progress.cancellable = YES; | |
[progress setCancellationHandler:^{ | |
dispatch_async(dispatch_get_main_queue(), ^{ | |
download->Cancel(true); | |
}); | |
}]; | |
progress.totalUnitCount = download->GetTotalBytes(); | |
progress.completedUnitCount = download->GetReceivedBytes(); | |
[progress publish]; | |
download->SetUserData(&kCrNSProgressUserDataKey, | |
new CrNSProgressUserData(progress, destination_path)); | |
} | |
void UpdateNSProgress(content::DownloadItem* download, | |
CrNSProgressUserData* progress_data) { | |
NSProgress* progress = progress_data->progress(); | |
progress.totalUnitCount = download->GetTotalBytes(); | |
progress.completedUnitCount = download->GetReceivedBytes(); | |
base::FilePath download_path = download->GetFullPath(); | |
if (progress_data->target() != download_path) { | |
progress_data->setTarget(download_path); | |
NSURL* download_url = [NSURL fileURLWithPath: | |
base::mac::FilePathToNSString(download_path)]; | |
[progress setUserInfoObject:download_url | |
forKey:ProgressString(kNSProgressFileURLKey)]; | |
} | |
} | |
void DestroyNSProgress(content::DownloadItem* download, | |
CrNSProgressUserData* progress_data) { | |
download->RemoveUserData(&kCrNSProgressUserDataKey); | |
} | |
} // namespace | |
void DownloadStatusUpdater::UpdateAppIconDownloadProgress( | |
content::DownloadItem* download) { | |
// Always update overall progress. | |
float progress = 0; | |
int download_count = 0; | |
bool progress_known = GetProgress(&progress, &download_count); | |
UpdateAppIcon(download_count, progress_known, progress); | |
// Update NSProgress-based indicators. | |
if (NSProgressSupported()) { | |
CrNSProgressUserData* progress_data = static_cast<CrNSProgressUserData*>( | |
download->GetUserData(&kCrNSProgressUserDataKey)); | |
// Only show progress if the download is IN_PROGRESS and it hasn't been | |
// renamed to its final name. Setting the progress after the final rename | |
// results in the file being stuck in an in-progress state on the dock. See | |
// http://crbug.com/166683. | |
if (download->GetState() == content::DownloadItem::IN_PROGRESS && | |
!download->GetFullPath().empty() && | |
download->GetFullPath() != download->GetTargetFilePath()) { | |
if (!progress_data) | |
CreateNSProgress(download); | |
else | |
UpdateNSProgress(download, progress_data); | |
} else { | |
DestroyNSProgress(download, progress_data); | |
} | |
} | |
// Handle downloads that ended. | |
if (download->GetState() != content::DownloadItem::IN_PROGRESS && | |
!download->GetTargetFilePath().empty()) { | |
NSString* download_path = | |
base::mac::FilePathToNSString(download->GetTargetFilePath()); | |
if (download->GetState() == content::DownloadItem::COMPLETE) { | |
// Bounce the dock icon. | |
[[NSDistributedNotificationCenter defaultCenter] | |
postNotificationName:@"com.apple.DownloadFileFinished" | |
object:download_path]; | |
} | |
// Notify the Finder. | |
NSString* parent_path = [download_path stringByDeletingLastPathComponent]; | |
FNNotifyByPath( | |
reinterpret_cast<const UInt8*>([parent_path fileSystemRepresentation]), | |
kFNDirectoryModifiedMessage, | |
kNilOptions); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment