Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform native notifications PR_3 #1202

Merged
merged 1 commit into from
Jun 17, 2019
Merged

Platform native notifications PR_3 #1202

merged 1 commit into from
Jun 17, 2019

Conversation

alameenshah
Copy link
Contributor

@alameenshah alameenshah commented May 24, 2019

Enable display of Automount notifications

This is the third incremental PR to enable platform native notifications on the Mac. In this PR, GVFS.Service sends auto-mount notifications to VFS For Git.app for display to user. Service displays two separate notifications - 1. a generic message when GVFS.Service begins on auto-mounting registered repositories and 2. for each registered repository with repo specific auto-mount success/failure messaging.

Details

  • New VFSForGitNotification class. It supports 3 different notifications - AutomountStart, MountSuccess, MountFailure. It will not display any other notification.
  • VFSForGitNotification defines the title & message body for each of the supported notification. It is not possible for GVFS.Service or another client to display random text.
  • MessageListener class creates a socket and waits for notification requests from client.
  • MessageParser class to parse the incoming JSON formatted message text.
  • New UT for VFSForGitNotification & MessageParser classes.
  • GVFS.Service does not wait for a reply from VFS For Git.app for the notification requests that it sends.
  • VFS For Git.app get automatically launched after installation.
  • VFS For Git.app has the same app version as gvfs version.

Message processing sequence

AppDelegate class creates and installs an instance of MessageListener. MessageListener creates a socket and waits for incoming messages. The following sequence diagram shows the flow of a message that arrives in MessageListener.
UserNotification-2

Testing notes

  • Installer automatically launches VFS For Git.app after successful install. If there were repositories that were registered for auto-mount before upgrade install, then auto-mount notifications for each of those repos would get displayed in the native Notification Center as GVFS.Service auto mounts them.
  • Tried sending a few hundred notifications. NotificationCenter collated notifications beyond 10 and created the following single notification (separate ones were still available in a long scroll view inside the NotificationCenter) -

Screen Shot 2019-06-12 at 3 00 08 PM

  • Tried sending huge (500MB) garbage data from client - memory usage of VFS For Git.app spiked, JSON Parsing failed, the app logged parse error and its memory footprint went down to normal.
  • Tried multiple clients sending messages simultaneously. No issues observed.

Reference

For a better understanding of the bigger picture refer this PR.

@alameenshah alameenshah added the affects: polish Good UX is hard label May 24, 2019
@alameenshah alameenshah added this to the M153 milestone May 24, 2019
@alameenshah alameenshah self-assigned this May 24, 2019
@alameenshah
Copy link
Contributor Author

/azp run GitHub VFSForGit Mac Functional Tests

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

@alameenshah
Copy link
Contributor Author

/azp run GitHub VFSForGit Mac Functional Tests

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

@alameenshah alameenshah requested a review from hi-kumar May 31, 2019 20:39
NSStringFromSelector(_cmd)];
NSString *info = [NSString stringWithFormat:@"%@: ERROR: error reading data.",
NSStringFromSelector(_cmd)];
*error = [NSError errorWithDomain:@"VFS For Git"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the domain string out to a single extern constant (declaration in some common header, single initialization in a .m file). Also see naming convention for custom error domains: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
You can create your own error domains and error codes for use in your own frameworks, or even in your own applications. It is recommended that the string constant for the domain be of the form com.company.framework_or_app.ErrorDomain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved Notification Agent specific errors to a separate file - VFSNotificationErrors.h. VFSNotificationErrors.m has only a single line with definition of the Domain - VFSForGitNotificationErrorDomain.

if (error != nil)
{
*error = [NSError errorWithDomain:@"VFS For Git"
code:-1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Ideally each error code should be unique to identify the failure. Helps when you want the caller to handle particular error conditions (by comparing error code numbers/enums).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Notification specific error codes in VFSNotificationErrors.h

return YES;
}

- (void)stopListening
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a -dealloc method to ensure the cleanup happens correctly on termination or whenever the object is released. Otherwise you are relying on the caller to call this appropriately. It may be fine right now because stopListening is called on application terminate, but could change with code refactoring etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep... added.

Couple notes

  1. [super dealloc] is not added because of ARC.
  2. Apple docs suggest it is not required to un-register notification observers from inside a dealloc method.

@jrbriggs jrbriggs removed this from the M153 milestone Jun 5, 2019
@@ -118,6 +118,9 @@ function CopyBinariesToInstall()
copyNotificationApp="cp -Rf \"${VFS_OUTPUTDIR}/GVFS.Notifications/VFSForGit.Mac/Build/Products/$CONFIGURATION/VFS For Git.app\" \"${STAGINGDIR}/${LIBRARYAPPSUPPORTDESTINATION}/.\""
eval $copyNotificationApp || exit 1

copyNotificationPlist="cp -Rf \"${SOURCEDIRECTORY}/../GVFS.Notifications/VFSForGit.Mac/org.vfsforgit.usernotification.plist\" \"${STAGINGDIR}/${AGENTPLISTDESTINATION}/.\""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

installs VFS For Git.app as launch agent


KEXTBUNDLEID="org.vfsforgit.PrjFSKext"
isKextLoadedCmd="/usr/sbin/kextstat -l -b $KEXTBUNDLEID | wc -l"
isKextLoaded=$(eval $isKextLoadedCmd)
if [ "$isKextLoaded" -gt 0 ]; then
unloadCmd="/sbin/kextunload -b $KEXTBUNDLEID"
unloadCmd="/sbin/kextunload -b $KEXTBUNDLEID"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced a tab with spaces

@@ -32,7 +38,7 @@ LEGACYKEXTBUNDLEID="io.gvfs.PrjFSKext"
isKextLoadedCmd="/usr/sbin/kextstat -l -b $LEGACYKEXTBUNDLEID | wc -l"
isKextLoaded=$(eval $isKextLoadedCmd)
if [ "$isKextLoaded" -gt 0 ]; then
unloadCmd="/sbin/kextunload -b $LEGACYKEXTBUNDLEID"
unloadCmd="/sbin/kextunload -b $LEGACYKEXTBUNDLEID"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced a tab with spaces

@alameenshah
Copy link
Contributor Author

/azp run GitHub VFSForGit Mac Functional Tests

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

this.SendNotification(sessionId, "GVFS AutoMount", "Attempting to mount {0} GVFS repo(s)", activeRepos.Count);
this.SendNotification(
sessionId,
NamedPipeMessages.Notification.Request.Identifier.AutomountStart,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should we thinking about interacting with users on macOS via notifications? Do they expect these to be fired only for special situations, or do they expect chatty notifications? I worry that notifying that we're about to mount X repos and then firing X success messages is too much. We could

  1. Only fire failure to mount
  2. Continue firing start, but only fire one notification summarizing what mounted successfully.

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about it, the more I like option 2. It's also a nice clue that you can start working. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that makes sense. Let me take a look at the options to minimize auto-mount notifications count...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed - notifying only on auto-mount failures.

Copy link
Member

@jrbriggs jrbriggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with suggestions.

Copy link
Member

@nickgra nickgra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ameen, this looks good! Sorry for the delay on my part.

[self displayNotification:messageInfo];
}];

[self.messageListener startListening];

VFSProductInfoFetcher *productInfoFetcher =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: what's going on with the whitespace here? Can we try getting Xcode to make the whitespace conform to the usual standard?

@@ -59,6 +59,10 @@ xcodebuild -configuration $CONFIGURATION -workspace $NATIVEDIR/GVFS.Native.Mac.x
USERNOTIFICATIONDIR=$VFS_SRCDIR/GVFS/GVFS.Notifications/VFSForGit.Mac
USERNOTIFICATIONPROJECT="$USERNOTIFICATIONDIR/VFSForGit.xcodeproj"
USERNOTIFICATIONSCHEME="VFS For Git"
updateAppVersionCmd="(cd \"$USERNOTIFICATIONDIR\" && /usr/bin/xcrun agvtool new-marketing-version \"$VERSION\")"
echo $updateAppVersionCmd
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For debugging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya. just to make sure the project directory and version are specified correctly.

@@ -59,6 +59,10 @@ xcodebuild -configuration $CONFIGURATION -workspace $NATIVEDIR/GVFS.Native.Mac.x
USERNOTIFICATIONDIR=$VFS_SRCDIR/GVFS/GVFS.Notifications/VFSForGit.Mac
USERNOTIFICATIONPROJECT="$USERNOTIFICATIONDIR/VFSForGit.xcodeproj"
USERNOTIFICATIONSCHEME="VFS For Git"
updateAppVersionCmd="(cd \"$USERNOTIFICATIONDIR\" && /usr/bin/xcrun agvtool new-marketing-version \"$VERSION\")"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does a new-marketing-version interact with the Info.plist? Should we move to using this to set the version of everything else that is native (the kext, log daemons, etc)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new-marketing-version updates CFBundleShortVersionString in the Info.plist file.

Should we move to using this to set the version of everything else that is native (the kext, log daemons, etc)?

I can take a look at how this is done on other native code and we can discuss offline.

This is the third incremental PR to enable platform native notifications
on the Mac. In this PR, GVFS.Service sends auto-mount notifications to
VFS For Git.app for display to user. Service displays notification for
auto-mount failures only - when it fails to auto-mount a repository that
has been registered for auto-mount.

Details
- New VFSForGitNotification class. It supports 3 different notifications
  - AutomountStart, MountSuccess, MountFailure. It will not display any
  other notification.
- VFSForGitNotification defines the title & message body for each of the
  supported notification. It is not possible for GVFS.Service or another
  client to display random text.
- MessageListener class creates a socket and waits for notification
  requests from client.
- MessageParser class to parse the incoming JSON formatted message
  text.
- New UT for VFSForGitNotification & MessageParser classes.
- GVFS.Service does not wait for a reply from VFS For Git.app for the
  notification requests that it sends.
- VFS For Git.app get automatically launched after installation.
- VFS For Git.app has the same app version as gvfs version.
- Updated MacServiceTests to not use INotificationHandler to verify
  Automount start. Now Service posts notification only on auto-mount
  failures.

More Info
- #1202
@alameenshah alameenshah merged commit 2775878 into microsoft:master Jun 17, 2019
@derrickstolee derrickstolee added this to the M155 milestone Jul 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects: polish Good UX is hard
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants