mirror of
https://github.com/munki/munki.git
synced 2026-05-02 10:19:32 -05:00
160 lines
6.6 KiB
Python
160 lines
6.6 KiB
Python
# encoding: utf-8
|
|
#
|
|
# MSCAppDelegate.py
|
|
# Managed Software Center
|
|
#
|
|
# Copyright 2013-2014 Greg Neagle.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# struct for the url handler
|
|
import struct
|
|
import os
|
|
from urlparse import urlparse
|
|
|
|
from objc import YES, NO, IBAction, IBOutlet, nil
|
|
import PyObjCTools
|
|
from Foundation import *
|
|
from AppKit import *
|
|
|
|
from MSCStatusController import MSCStatusController
|
|
|
|
import munki
|
|
import mschtml
|
|
import msclog
|
|
import MunkiItems
|
|
|
|
class MSCAppDelegate(NSObject):
|
|
|
|
mainWindowController = IBOutlet()
|
|
statusController = IBOutlet()
|
|
|
|
def applicationShouldTerminate_(self, sender):
|
|
'''Called if user selects 'Quit' from menu'''
|
|
return self.mainWindowController.appShouldTerminate()
|
|
|
|
def applicationDidFinishLaunching_(self, sender):
|
|
'''NSApplication delegate method called at launch'''
|
|
|
|
# userInfo dict can be nil, seems to be with 10.6
|
|
if sender.userInfo():
|
|
userNotification = sender.userInfo().get('NSApplicationLaunchUserNotificationKey')
|
|
# we get this notification at launch because it's too early to have declared ourself
|
|
# a NSUserNotificationCenterDelegate
|
|
if userNotification:
|
|
NSLog("Launched via Notification interaction")
|
|
self.userNotificationCenter_didActivateNotification_(
|
|
NSUserNotificationCenter.defaultUserNotificationCenter(), userNotification)
|
|
|
|
# Prevent automatic relaunching at login on Lion+
|
|
if NSApp.respondsToSelector_('disableRelaunchOnLogin'):
|
|
NSApp.disableRelaunchOnLogin()
|
|
|
|
ver = NSBundle.mainBundle().infoDictionary().get('CFBundleShortVersionString')
|
|
msclog.log("MSC", "launched", "VER=%s" % ver)
|
|
|
|
# if we're running under Snow Leopard, swap out the Dock icon for one
|
|
# without the Retina assets to avoid an appearance issue when the
|
|
# icon has a badge in the Dock (and App Switcher)
|
|
# Darwin major version 10 is Snow Leopard (10.6)
|
|
if os.uname()[2].split('.')[0] == '10':
|
|
myImage = NSImage.imageNamed_("Managed Software Center 10_6")
|
|
NSApp.setApplicationIconImage_(myImage)
|
|
|
|
# if we are running under Mountain Lion or later set ourselves as a delegate
|
|
# for NSUserNotificationCenter notifications
|
|
if os.uname()[2].split('.')[0] > '11':
|
|
NSUserNotificationCenter.defaultUserNotificationCenter().setDelegate_(self)
|
|
|
|
# setup client logging
|
|
msclog.setup_logging()
|
|
|
|
# have the statuscontroller register for its own notifications
|
|
self.statusController.registerForNotifications()
|
|
|
|
# user may have launched the app manually, or it may have
|
|
# been launched by /usr/local/munki/managedsoftwareupdate
|
|
# to display available updates
|
|
if munki.thereAreUpdatesToBeForcedSoon(hours=2):
|
|
# skip the check and just display the updates
|
|
# by pretending the lastcheck is now
|
|
lastcheck = NSDate.date()
|
|
else:
|
|
lastcheck = munki.pref('LastCheckDate')
|
|
max_cache_age = munki.pref('CheckResultsCacheSeconds')
|
|
# if there is no lastcheck timestamp, check for updates.
|
|
if not lastcheck:
|
|
self.mainWindowController.checkForUpdates()
|
|
elif lastcheck.timeIntervalSinceNow() * -1 > int(max_cache_age):
|
|
# check for updates if the last check is over the
|
|
# configured manualcheck cache age max.
|
|
self.mainWindowController.checkForUpdates()
|
|
elif MunkiItems.updateCheckNeeded():
|
|
# check for updates if we have optional items selected for install
|
|
# or removal that have not yet been processed
|
|
self.mainWindowController.checkForUpdates()
|
|
|
|
# load the initial view only if we are not already loading something else.
|
|
# enables launching the app to a specific panel, eg. from URL handler
|
|
if not self.mainWindowController.webView.isLoading():
|
|
self.mainWindowController.loadInitialView()
|
|
|
|
def applicationWillFinishLaunching_(self, notification):
|
|
'''Installs URL handler for calls outside the app eg. web clicks'''
|
|
man = NSAppleEventManager.sharedAppleEventManager()
|
|
man.setEventHandler_andSelector_forEventClass_andEventID_(
|
|
self,
|
|
"openURL:withReplyEvent:",
|
|
struct.unpack(">i", "GURL")[0],
|
|
struct.unpack(">i", "GURL")[0])
|
|
|
|
def openMunkiURL(self, url):
|
|
'''Display page associated with munki:// url'''
|
|
parsed_url = urlparse(url)
|
|
if parsed_url.scheme != 'munki':
|
|
msclog.debug_log("URL %s has unsupported scheme" % url)
|
|
return
|
|
filename = mschtml.unquote(parsed_url.netloc)
|
|
# add .html if no extension
|
|
if not os.path.splitext(filename)[1]:
|
|
filename += u'.html'
|
|
if filename.endswith(u'.html'):
|
|
mschtml.build_page(filename)
|
|
self.mainWindowController.load_page(filename)
|
|
else:
|
|
msclog.debug_log("%s doesn't have a valid extension. Prevented from opening" % url)
|
|
|
|
def openURL_withReplyEvent_(self, event, replyEvent):
|
|
'''Handle openURL messages'''
|
|
keyDirectObject = struct.unpack(">i", "----")[0]
|
|
url = event.paramDescriptorForKeyword_(keyDirectObject).stringValue().decode('utf8')
|
|
msclog.log("MSU", "Called by external URL: %s", url)
|
|
self.openMunkiURL(url)
|
|
|
|
def userNotificationCenter_didActivateNotification_(self, center, notification):
|
|
'''User clicked on a Notification Center alert'''
|
|
user_info = notification.userInfo()
|
|
if user_info.get('action') == 'open_url':
|
|
url = user_info.get('value')
|
|
msclog.log("MSU", "Got user notification to open %s" % url)
|
|
self.openMunkiURL(url)
|
|
center.removeDeliveredNotification_(notification)
|
|
else:
|
|
msclog.log("MSU", "Got user notification with unrecognized userInfo")
|
|
|
|
def userNotificationCenter_shouldPresentNotification_(self, center, notification):
|
|
return True
|
|
|
|
def userNotificationCenter_didDeliverNotification_(self, center, notification):
|
|
pass
|