class InternalLinksHandler(IInternalLinksController): browserCtrl = dependency.descriptor(IBrowserController) def __init__(self): super(InternalLinksHandler, self).__init__() self.__urlMarcos = None self._browserID = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self.browserCtrl.load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn) def _handleClubHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE) def _handleVideoHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
class InternalLinksHandler(Controller): def __init__(self, proxy): super(InternalLinksHandler, self).__init__(proxy) self.__urlMarcos = None self._browserID = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self._proxy.getController(gc_constants.CONTROLLER.BROWSER).load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn) def _handleClubHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE) def _handleVideoHelp(self, event): self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
class PromoController(Controller): PROMO_AUTO_VIEWS_TEST_VALUE = 5 def __init__(self, proxy): super(PromoController, self).__init__(proxy) self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False return def fini(self): self._stop() self.__urlMacros.clear() self.__urlMacros = None super(PromoController, self).fini() return def onLobbyInited(self, event): self._updatePromo(self._getPromoEventNotifications()) self._getEventsFotificationController().onEventNotificationsChanged += self.__onEventNotification self._getBrowserController().onBrowserDeleted += self.__onBrowserDeleted self._processPromo(self._getEventNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showPatchPromo(self, isAsync = False): self.__currentVersionBrowserID = yield self.__showPromoBrowser(self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE, version=getClientVersion()), browserID=self.__currentVersionBrowserID, isAsync=isAsync) def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None def _stop(self): self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self._getBrowserController().onBrowserDeleted -= self.__onBrowserDeleted self._getEventsFotificationController().onEventNotificationsChanged -= self.__onEventNotification return @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.__currentVersionPromoUrl not in self.__promoShown and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) self.__promoShown.add(self.__currentVersionPromoUrl) self.__savePromoShown() self.__currentVersionBrowserShown = True self._isPromoShown = True self.showPatchPromo(isAsync=True) return actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter(lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION), promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if item.eventType == gc_constants.PROMO.TEMPLATE.PATCH and self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = promoUrl promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = {url for url in promoShownSource if url in self.__availablePromo} self.__savePromoShown() return def _getEventNotifications(self): return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION).getEventsNotifications() def _getPromoEventNotifications(self): filterFunc = lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION) return self._getEventsFotificationController().getEventsNotifications(filterFunc) def _getBrowserController(self): return self._proxy.getController(gc_constants.CONTROLLER.BROWSER) def _getEventsFotificationController(self): return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION) def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent(events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID = None, isAsync = True, callback = None): browserID = yield self._getBrowserController().load(promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, background=gc_constants.BROWSER.PROMO_BACKGROUND, isDefault=False, showCloseBtn=True) callback(browserID) @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID() % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings().isPromoAutoViewsEnabled()
class BrowserController(IBrowserController): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserCreationCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browsersCallbacks.clear() self.__browsersCallbacks = None self.__browsers.clear() self.__browsers = None self.__pendingBrowsers.clear() self.__pendingBrowsers = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): """ Adds given @handler to the browser urls filter chain. Calls it if there is a @tag in url onto opened browser page. Handler should receive url and list of client-specific tags, return bool as flag that routine have to stop """ self.__filters.add(handler) def removeFilterHandler(self, handler): """ Remove given @handler from filtering chain. Handler description can be seen in addFilterhandler method doc-string """ self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False): if constants.IS_BOOTCAMP_ENABLED: from bootcamp.Bootcamp import g_bootcamp if g_bootcamp.isRunning(): return if showCreateWaiting: Waiting.show('browser/init') url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = { 'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow, 'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW, 'showCreateWaiting': showCreateWaiting, 'handlers': handlers, 'showBrowserCallback': showBrowserCallback, 'isSolidBorder': isSolidBorder } texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): LOG_BROWSER('CTRL: Queueing a browser creation: ', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: LOG_BROWSER('CTRL: Re-queuing a browser creation, overriding: ', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: LOG_BROWSER('CTRL: Re-navigating an existing browser: ', browserID, url) browser = self.__browsers[browserID] browser.navigate(url) browser.changeTitle(title) callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: LOG_BROWSER('CTRL: Deleting a browser: ', browserID) browser = self.__browsers.pop(browserID) self.__clearCallbacks(browserID, browser, True) browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() if browserID in self.__pendingBrowsers: del self.__pendingBrowsers[browserID] self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): LOG_BROWSER('CTRL: Finished creating a browser: ', self.__creatingBrowserID) if ctx['showCreateWaiting']: Waiting.hide('browser/init') def __tryCreateNextPendingBrowser(self): self.__creatingBrowserID = None if len(self.__pendingBrowsers) > 0: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) return def __createBrowser(self, ctx): browserID = ctx['browserID'] LOG_BROWSER('CTRL: Creating a browser: ', browserID, ctx['url']) self.__creatingBrowserID = browserID if not self.__browsers[browserID].create(): LOG_BROWSER('CTRL: Failed the create step: ', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createBrowserTimeout(): LOG_BROWSER('CTRL: Browser create timed out') createNextBrowser() timeoutid = BigWorld.callback(30.0, createBrowserTimeout) def createNextBrowser(): LOG_BROWSER('CTRL: Triggering create of next browser from: ', browserID) BigWorld.cancelCallback(timeoutid) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[ browserID].onCanCreateNewBrowser -= creation BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser) return def failedCreationCallback(url): LOG_BROWSER('CTRL: Failed a creation: ', browserID, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) self.delBrowser(browserID) def successfulCreationCallback(url, isLoaded, httpStatusCode=None): LOG_BROWSER('CTRL: Ready to show: ', browserID, isLoaded, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser request url was not loaded!', url) g_eventBus.handleEvent( BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__createDone(ctx) self.__browsers[ browserID].onCanCreateNewBrowser += createNextBrowser self.__browserCreationCallbacks[browserID] = createNextBrowser self.__browsers[ browserID].onFailedCreation += failedCreationCallback if ctx['isAsync']: self.__browsersCallbacks[browserID] = ( None, successfulCreationCallback, failedCreationCallback) self.__browsers[ browserID].onLoadEnd += successfulCreationCallback else: self.__browsersCallbacks[browserID] = ( successfulCreationCallback, None, failedCreationCallback) self.__browsers[ browserID].onReady += successfulCreationCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() self.__clearCallbacks(browserID, browser, True) browser.destroy() def __clearCallbacks(self, browserID, browser, incDelayedCreation): ready, loadEnd, failed = self.__browsersCallbacks.pop( browserID, (None, None, None)) if browser is not None: if failed is not None: browser.onFailedCreation -= failed if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd if incDelayedCreation: creation = self.__browserCreationCallbacks.pop(browserID, None) if browser is not None and creation is not None: browser.onCanCreateNewBrowser -= creation return def __showBrowser(self, browserID, ctx): LOG_BROWSER('CTRL: Showing a browser: ', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent( LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY) showBrowserCallback = ctx.get('showBrowserCallback') if showBrowserCallback: showBrowserCallback()
class RssNewsFeed(RssNewsFeedMeta): UPDATE_INTERVAL = 60 DESCRIPTION_MAX_LENGTH = 250 DESCRIPTION_TAIL = '...' DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL) SHOW_NEWS_COUNT = 3 def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMarcos() return def getFeed(self): return self.__feed def openBrowser(self, linkToOpen): if linkToOpen: openBrowser = game_control.g_instance.links.open if GUI_SETTINGS.loginRssFeed.internalBrowser: browser = game_control.g_instance.browser if browser is not None: openBrowser = browser.load else: LOG_ERROR('Attempting to open internal browser, but browseris not exist. External browser will be opened', str(linkToOpen)) LOG_DEBUG('Open browser', linkToOpen) openBrowser(linkToOpen) return def _populate(self): super(RssNewsFeed, self)._populate() self.__updateCallback() def _dispose(self): self.__urlMacros.clear() self.__urlMacros = None self.__feed = [] self.__clearCallback() super(RssNewsFeed, self)._dispose() return @process def __requestFeed(self): yield lambda callback: callback(True) if GUI_SETTINGS.loginRssFeed.show: requestUrl = yield self.__getRssUrl() from helpers.RSSDownloader import g_downloader as g_rss if g_rss is not None: g_rss.download(self.__onRssFeedReceived, url=requestUrl) LOG_DEBUG('Requesting login RSS news', requestUrl) return def __onRssFeedReceived(self, data): if self.isDisposed(): return else: self.__feed = [] for entry in reversed(data.get('entries', [])): data = self.__prepareData(entry) if data is not None: self.__feed.append(data) LOG_DEBUG('RSS feed received, entries count', len(self.__feed)) self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT]) return def __clearCallback(self): if self.__requestCbID is not None: BigWorld.cancelCallback(self.__requestCbID) self.__requestCbID = None return def __updateCallback(self): self.__requestFeed() self.__clearCallback() self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback) @async @process def __getRssUrl(self, callback): if constants.IS_CHINA: callback('http://wot.kongzhong.com/erji/login_ticker.xml') url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url)) callback(url) def __prepareData(self, entryData): description = entryData.get('description') if description is not None: try: section = ResMgr.DataSection() section.createSectionFromString(encodeUtf8(description)) _, section = findFirst(lambda (name, _): name == 'div', section.items()) description, _ = unicode_from_utf8(section.asString) if len(description) > self.DESCRIPTION_MAX_LENGTH: description = description[:self.DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL except Exception: LOG_ERROR('Invalid RSS entry description', entryData, description) LOG_CURRENT_EXCEPTION() return return {'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description)}
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowser = False def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useWhitelisting = False): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn} texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and (self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE) app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, useWhitelisting) self.__browsers[browserID] = browser if self.__creatingBrowser: self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: self.__browsers[browserID].navigate(url) callback(browserID) return def __createDone(self, browserID): self.__creatingBrowser = False if len(self.__pendingBrowsers) > 0: ctx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(ctx) def __createBrowser(self, ctx): self.__creatingBrowser = True browserID = ctx['browserID'] self.__browsers[browserID].create() self.onBrowserAdded(browserID) def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) self.__createDone(browserID) def browserAsyncCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser async request url was not loaded!', url) self.__createDone(browserID) if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, browserAsyncCallback) self.__browsers[browserID].onLoadEnd += browserAsyncCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onReady += browserCallback return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: self.__browsers[browserID].onReady -= ready if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class CalendarController(ICalendarController): browserCtrl = dependency.descriptor(IBrowserController) eventsCache = dependency.descriptor(IEventsCache) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(CalendarController, self).__init__() self.__browserID = None self.__showOnSplash = False self.__urlMacros = URLMarcos() return def onLobbyInited(self, event): self.eventsCache.onSyncCompleted += self.__onSyncCompleted self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted def fini(self): self.__urlMacros.clear() self.__urlMacros = None self.hideCalendar() self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.eventsCache.onSyncCompleted -= self.__onSyncCompleted super(CalendarController, self).fini() return def mustShow(self): result = False lastShowTstamp = self.__getShowTimestamp() if not lastShowTstamp or lastShowTstamp < 0: return True else: now = time_utils.getServerRegionalTime() if lastShowTstamp > now: return True actions = self.eventsCache.getActions( calendarEnabledActionFilter).values() for action in actions: if action.getFinishTime() < now: continue stepDuration = None for modifier in action.getModifiers(): duration = modifier.getDuration() if modifier else None if duration: stepDuration = min( stepDuration, duration) if stepDuration else duration stepDuration = (stepDuration or GUI_SETTINGS.adventCalendar[ 'popupIntervalInHours']) * ONE_HOUR offerChangedTime = now - int( now - action.getStartTime()) % stepDuration wasntVisibleAtAll = not lastShowTstamp or lastShowTstamp > now wasntVisibleCurrentOffer = not wasntVisibleAtAll and lastShowTstamp < offerChangedTime result = wasntVisibleAtAll or wasntVisibleCurrentOffer return result def onLobbyStarted(self, event): self.__updateActions() if self.__showOnSplash and self.mustShow(): self.showCalendar(CalendarInvokeOrigin.SPLASH) def onAvatarBecomePlayer(self): self.hideCalendar() def onDisconnected(self): self.hideCalendar() def showCalendar(self, invokedFrom): self.hideCalendar() try: while self.__browserID is None: browserID = next(_browserIDGen) if self.browserCtrl.getBrowser(browserID) is None: self.__browserID = browserID except StopIteration: _logger.error('Could not allocate a browser ID for calendar') return self.__openBrowser(self.__browserID, _BROWSER_SIZE, invokedFrom) self.__setShowTimestamp(time_utils.getServerRegionalTime()) _logger.debug('Calendar opened in web browser (browserID=%d)', self.__browserID) return def hideCalendar(self): if self.__browserID is None: return else: self.browserCtrl.delBrowser(self.__browserID) return def __onSyncCompleted(self, *_): self.__updateActions() def __updateActions(self): self.__showOnSplash = len( self.eventsCache.getActions(calendarEnabledActionFilter)) > 0 def __onBrowserDeleted(self, browserID): if browserID == self.__browserID: _logger.debug('Calendar web browser destroyed (browserID=%d)', browserID) self.__browserID = None return def __getShowTimestamp(self): tstampStr = AccountSettings.getSettings(LAST_CALENDAR_SHOW_TIMESTAMP) if tstampStr: try: return float(tstampStr) except (TypeError, ValueError): _logger.warning('Invalid calendar show timestamp') return None def __setShowTimestamp(self, tstamp): AccountSettings.setSettings(LAST_CALENDAR_SHOW_TIMESTAMP, str(tstamp)) @process def __openBrowser(self, browserID, browserSize, invokedFrom): url = yield self.__urlMacros.parse( GUI_SETTINGS.adventCalendar['baseURL']) if not url: _logger.error('Invalid calendar URL') return browserHandlers = webApiCollection(SoundWebApi, RequestWebApi) def showBrowserWindow(): ctx = { 'size': browserSize, 'title': i18n.makeString(MENU.ADVENTCALENDAR_WINDOW_TITLE), 'handlers': browserHandlers, 'browserID': browserID, 'alias': VIEW_ALIAS.ADVENT_CALENDAR, 'showCloseBtn': False, 'showWaiting': True, 'showActionBtn': False } browser = self.browserCtrl.getBrowser(browserID) browser.useSpecialKeys = False g_eventBus.handleEvent(events.LoadViewEvent( VIEW_ALIAS.ADVENT_CALENDAR, ctx=ctx), scope=EVENT_BUS_SCOPE.LOBBY) title = i18n.makeString(MENU.ADVENTCALENDAR_WINDOW_TITLE) yield self.browserCtrl.load(url=url, browserID=browserID, browserSize=browserSize, isAsync=False, useBrowserWindow=False, showBrowserCallback=showBrowserWindow, showCreateWaiting=False, title=title)
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): """ Adds given @handler to the browser urls filter chain. Calls it if there is a @tag in url onto opened browser page. Handler should receive url and list of client-specific tags, return bool as flag that routine have to stop """ self.__filters.add(handler) def removeFilterHandler(self, handler): """ Remove given @handler from filtering chain. Handler description can be seen in addFilterhandler method doc-string """ self.__filters.discard(handler) @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useBrowserWindow = True): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow} texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: self.__browsers[browserID].navigate(url) callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): self.__creatingBrowserID = None g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__tryCreateNextPendingBrowser() return def __tryCreateNextPendingBrowser(self): if len(self.__pendingBrowsers) > 0: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) def __createBrowser(self, ctx): browserID = ctx['browserID'] self.__creatingBrowserID = browserID self.__browsers[browserID].create() self.onBrowserAdded(browserID) def browserCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser request url was not loaded!', url) self.__createDone(browserID) if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onReady += browserCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: self.__browsers[browserID].onReady -= ready if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): if ctx.get('showWindow'): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class ExternalLinksHandler(IExternalLinksController): def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMarcos = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: LOG_ERROR('URL is empty', url) return try: BigWorld.wg_openWebBrowser(url) except Exception: LOG_ERROR('There is error while opening web browser at page:', url) LOG_CURRENT_EXCEPTION() @async @process def getURL(self, name, params=None, callback=lambda *args: None): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings), params) else: url = yield lambda callback: callback('') callback(url) def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName, params=None): parsedUrl = yield self.getURL(urlName, params) self.open(parsedUrl) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo') def _handleOpenPremShopURL(self, _): self.__openParsedUrl('premShopURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params)
class PromoController(IPromoController): browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) __webController = dependency.descriptor(IWebController) __settingsCore = dependency.descriptor(ISettingsCore) __lobbyContext = dependency.descriptor(ILobbyContext) __logger = dependency.descriptor(IPromoLogger) __bootcamp = dependency.descriptor(IBootcampController) _CHECK_FREQUENCY_IN_BATTLES = 10 def __init__(self): super(PromoController, self).__init__() self.__urlMacros = URLMarcos() self.__externalCloseCallback = None self.__isLobbyInited = False self.__pendingPromo = None self.__promoCount = 0 self.__lastUpdateTimeMark = 0 self.__promoData = None self.__webBrgDataRequested = False self.__battlesFromLastTeaser = 0 self.__wasInBattle = False self.__hasPendingTeaser = False self.__isPromoOpen = False self.__browserCreationCallbacks = {} self.__browserWatchers = {} self.__isInHangar = False self.__isTeaserOpen = False self.__em = EventManager() self.onNewTeaserReceived = Event(self.__em) self.onPromoCountChanged = Event(self.__em) return @sf_lobby def app(self): pass def fini(self): self.__stop() self.__pendingPromo = None self.__urlMacros.clear() self.__urlMacros = None self.__externalCloseCallback = None self.__em.clear() g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} self.__browserWatchers = {} super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return g_eventBus.addListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__isLobbyInited = True if self.__hasPendingTeaser: self.__tryToShowTeaser() elif self.__battlesFromLastTeaser % self._CHECK_FREQUENCY_IN_BATTLES == 0: self.__updateWebBrgData() self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification if not isPopupsWindowsOpenDisabled(): self.__processPromo( self.eventsNotification.getEventsNotifications()) self.app.loaderManager.onViewLoaded += self.__onViewLoaded def setNewTeaserData(self, teaserData): timestamp = teaserData['timestamp'] if self.__lastUpdateTimeMark < timestamp and not self.__isPromoOpen and not self.__isTeaserOpen: self.__updateTeaserData(teaserData) def showFieldPost(self): url = GUI_SETTINGS.promoscreens loadingCallback = self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_FROM_MENU, type=PromoLogSubjectType.INDEX, url=url) self.__showBrowserView(url, loadingCallback) @process def showLastTeaserPromo(self): rowUrl = self.__promoData.get('url', '') loadingCallback = self.__logger.getLoggingFuture( self.__promoData, action=PromoLogActions.OPEN_FROM_TEASER, type=PromoLogSubjectType.PROMO_SCREEN, url=rowUrl) url = yield self.__addAuthParams(rowUrl) self.__showBrowserView(url, loadingCallback) def setUnreadPromoCount(self, count): self.__updatePromoCount(count) def onAvatarBecomePlayer(self): if self.__isLobbyInited: self.__battlesFromLastTeaser += 1 self.__stop() def onDisconnected(self): self.__stop() def isActive(self): return self.__lobbyContext.getServerSettings().isFieldPostEnabled( ) and not self.__bootcamp.isInBootcamp() def getPromoCount(self): return self.__promoCount def showPromo(self, url, closeCallback=None, source=None): if self.__isLobbyInited: if not self.__isPromoOpen and not self.__webBrgDataRequested: self.__registerAndShowPromoBrowser( url, closeCallback, self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_IN_OLD, type=PromoLogSubjectType.PROMO_SCREEN, source=source, url=url)) else: self.__pendingPromo = _PromoData(url, closeCallback, source) def __onTeaserClosed(self, byUser=False): self.__isTeaserOpen = False if byUser: self.__showBubbleTooltip() def __showBubbleTooltip(self): storageData = self.__settingsCore.serverSettings.getUIStorage() if not storageData.get(UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN): showBubbleTooltip(i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)) self.__settingsCore.serverSettings.saveInUIStorage( {UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN: True}) @process def __updateWebBrgData(self): ctx = PromoGetTeaserRequestCtx() if self.__battlesFromLastTeaser == 0: sourceType = PromoLogSourceType.FIRST_LOGIN else: sourceType = PromoLogSourceType.AFTER_BATTLE answerCallback = self.__logger.getLoggingFuture( action=PromoLogActions.GET_MOST_IMPORTANT, source=sourceType) self.__webBrgDataRequested = True response = yield self.__webController.sendRequest(ctx=ctx) if response.isSuccess(): self.__updateTeaserData(ctx.getDataObj(response.getData())) self.__webBrgDataRequested = False if answerCallback: answerCallback(success=response.extraCode) def __onPromoClosed(self, **kwargs): self.__isPromoOpen = False self.__showBubbleTooltip() if self.__externalCloseCallback: self.__externalCloseCallback() self.__requestPromoCount() actionType = PromoLogActions.CLOSED_BY_USER if kwargs.get( 'byUser') else PromoLogActions.KILLED_BY_SYSTEM self.__logger.logAction(action=actionType, type=PromoLogSubjectType.PROMO_SCREEN_OR_INDEX, url=kwargs.get('url')) @process def __requestPromoCount(self): if not self.isActive(): _logger.warning( 'Trying to request unread promos count when promo functionality is disabled' ) return ctx = PromoGetUnreadCountRequestCtx() response = yield self.__webController.sendRequest(ctx=ctx) if response.isSuccess(): self.__updatePromoCount(ctx.getCount(response)) def __updatePromoCount(self, count): countChanged = count != self.__promoCount self.__promoCount = count if countChanged: self.onPromoCountChanged() def __updateTeaserData(self, teaserData): self.__lastUpdateTimeMark = teaserData['timestamp'] self.__promoData = teaserData['lastPromo'] self.__updatePromoCount(teaserData['count']) if self.__promoData.get('url'): self.__tryToShowTeaser() def __showTeaser(self): if self.isActive(): self.__battlesFromLastTeaser = 0 self.__hasPendingTeaser = False self.onNewTeaserReceived(self.__promoData, self.__onTeaserShown, self.__onTeaserClosed) else: _logger.warning( 'Impossible to show teaser, functionality is disabled') @process def __onTeaserShown(self, promoID): self.__isTeaserOpen = True yield self.__webController.sendRequest( PromoSendTeaserShownRequestCtx(promoID)) def __tryToShowTeaser(self): if self.__isLobbyInited and self.__isInHangar: self.__showTeaser() else: self.__hasPendingTeaser = True def __stop(self): if self.app and self.app.loaderManager: self.app.loaderManager.onViewLoaded -= self.__onViewLoaded self.__isLobbyInited = False self.__isPromoOpen = False self.__currentVersionBrowserID = None self.__externalCloseCallback = None self.__isTeaserOpen = False self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} watcherKeys = self.__browserWatchers.keys() for browserID in watcherKeys: self.__clearWatcher(browserID) return def __processPromo(self, promos): if not self.__isPromoOpen and not self.__webBrgDataRequested: logData = { 'action': PromoLogActions.OPEN_IN_OLD, 'type': PromoLogSubjectType.PROMO_SCREEN } if self.__pendingPromo is not None: promoData = self.__pendingPromo logData.update({ 'source': promoData.source, 'url': promoData.url }) loadingCallback = self.__logger.getLoggingFuture(**logData) self.__registerAndShowPromoBrowser(promoData.url, promoData.closeCallback, loadingCallback) self.__pendingPromo = None return promo = findFirst( lambda item: item.eventType.startswith( gc_constants.PROMO.TEMPLATE.ACTION), promos) if promo: logData.update({ 'source': PromoLogSourceType.SSE, 'url': promo.data }) self.__showBrowserView( promo.data, self.__logger.getLoggingFuture(**logData)) return def __onEventNotification(self, added, _): self.__processPromo(added) def __registerAndShowPromoBrowser(self, url, closeCallback, loadingCallback): self.__externalCloseCallback = closeCallback self.__showBrowserView(url, loadingCallback) @process def __showBrowserView(self, url, loadingCallback=None): promoUrl = yield self.__urlMacros.parse(url) self.__registerLoadingCallback(promoUrl, loadingCallback) _showBrowserView(promoUrl, self.__onPromoClosed) self.__isPromoOpen = True def __registerLoadingCallback(self, url, callback): if callback is not None: self.__browserCreationCallbacks[url] = callback return def __handleBrowserCreated(self, event): url = event.ctx.get('url') if url in self.__browserCreationCallbacks: callback = self.__browserCreationCallbacks.pop(url) browserID = event.ctx.get('browserID') browser = self.browserCtrl.getBrowser(browserID) if browser is None: return def callbackWrapper(clbUrl, _, statusCode): if clbUrl == url: callback(url=url, success=statusCode) self.__clearWatcher(browserID) browser.onLoadEnd += callbackWrapper self.__browserWatchers[browserID] = callbackWrapper return def __clearWatcher(self, browserID): if browserID in self.__browserWatchers: watcher = self.__browserWatchers.pop(browserID) browser = self.browserCtrl.getBrowser(browserID) if browser is not None: browser.onLoadEnd -= watcher return @async @process def __addAuthParams(self, url, callback): if not url or not self.__webController: callback(url) accessTokenData = yield self.__webController.getAccessTokenData( force=True) params = { 'access_token': str(accessTokenData.accessToken), 'spa_id': BigWorld.player().databaseID } callback(url_formatters.addParamsToUrlQuery(url, params)) def __onViewLoaded(self, pyView, _): if self.__isLobbyInited: if pyView.alias == VIEW_ALIAS.LOBBY_HANGAR: self.__isInHangar = True if self.__hasPendingTeaser: self.__tryToShowTeaser() elif pyView.viewType == ViewTypes.LOBBY_SUB: self.__isInHangar = False
class BrowserController(Controller): _BROWSER_TEXTURE = "BrowserBg" _ALT_BROWSER_TEXTURE = "AltBrowserBg" def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load( self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, background=None, isDefault=True, callback=None, showCloseBtn=False, ): url = url or GUI_SETTINGS.browser.url suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = "&" if "?" in url else "?" if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE background = background or BROWSER.BACKGROUND if browserID is None: browserID = self.__browserIDGenerator.next() if browserID not in self.__browsers: texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError("Application can not be None") self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url, backgroundUrl=background) self.onBrowserAdded(browserID) ctx = { "url": url, "title": title, "showActionBtn": showActionBtn, "showWaiting": showWaiting, "browserID": browserID, "size": size, "isDefault": isDefault, "isAsync": isAsync, "showCloseBtn": showCloseBtn, } def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent( LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY, )
class BrowserController(Controller, AppRef): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onBattleStarted(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, background = None, isDefault = True, callback = None): url = url or GUI_SETTINGS.browser.url suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE background = background or BROWSER.BACKGROUND if browserID not in self.__browsers: browserID = self.__browserIDGenerator.next() texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE self.__browsers[browserID] = WebBrowser(browserID, self.app, texture, size, url, backgroundUrl=background) self.onBrowserAdded(browserID) ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync} def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) if isAsync: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): self.app.fireEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class CalendarController(ICalendarController): """Advent calendar controller. This controller shows the in-game browser pointing to the advent calendar web-app in following scenarios: * The player clicks on related item in the Hangar. * The player clicks on related Action in the Shop. * On lobby startup once in a day, if allowed by server. """ browserCtrl = dependency.descriptor(IBrowserController) eventsCache = dependency.descriptor(IEventsCache) def __init__(self): super(CalendarController, self).__init__() self.__browserID = None self.__browserLoaded = False self.__showOnSplash = False self.__urlMacros = URLMarcos() return def init(self): self.eventsCache.onSyncCompleted += self.__onSyncCompleted self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted g_eventBus.addListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated) def fini(self): self.__urlMacros.clear() self.__urlMacros = None self.hideCalendar() g_eventBus.removeListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated) self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.eventsCache.onSyncCompleted -= self.__onSyncCompleted super(CalendarController, self).fini() return def onLobbyStarted(self, event): if self.__showOnSplash: lastShowTstamp = self.__getShowTimestamp() now = time_utils.getServerUTCTime() if lastShowTstamp is not None: today = time_utils.getDayTimeBoundsForUTC(now)[0] offset = _START_OF_DAY_OFFSET.get(constants.CURRENT_REALM, timedelta(0)).total_seconds() dayStart = today + offset mustShow = lastShowTstamp < dayStart <= now or lastShowTstamp > now else: mustShow = True if mustShow: self.showCalendar(CalendarInvokeOrigin.SPLASH) self.__setShowTimestamp(now) return def onAvatarBecomePlayer(self): self.hideCalendar() def onDisconnected(self): self.hideCalendar() def showCalendar(self, invokedFrom): """Show the advent calendar in browser window.""" if self.__browserID is not None: if self.__browserLoaded: _logger.debug('Calendar already opened, bringing window to focus (browserID=%d)' % self.__browserID) g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(self.__browserID)), scope=EVENT_BUS_SCOPE.LOBBY) return else: try: while self.__browserID is None: browserID = next(_browserIDGen) if self.browserCtrl.getBrowser(browserID) is None: self.__browserID = browserID except StopIteration: _logger.error('Could not allocate a browser ID for calendar') return self.__openBrowser(self.__browserID, _BROWSER_SIZE, invokedFrom) _logger.debug('Calendar opening scheduled (browserID=%d)' % self.__browserID) return def hideCalendar(self): if self.__browserID is None: return else: self.browserCtrl.delBrowser(self.__browserID) return def __onSyncCompleted(self, *_): def calendarEnabledActionFilter(act): return any((isinstance(mod, CalendarSplashModifier) for mod in act.getModifiers())) self.__showOnSplash = len(self.eventsCache.getActions(calendarEnabledActionFilter)) > 0 def __onBrowserDeleted(self, browserID): if browserID == self.__browserID: _logger.debug('Calendar WebBrowser instance destroyed (browserID=%d)' % browserID) self.__browserID = None self.__browserLoaded = False return def __onBrowserCreated(self, event): browserID = event.ctx.get('browserID') if browserID == self.__browserID: _logger.debug('Calendar WebBrowser instance created (browserID=%d)' % browserID) browser = self.browserCtrl.getBrowser(browserID) browser.useSpecialKeys = False self.__browserLoaded = True def __getShowTimestamp(self): tstampStr = AccountSettings.getSettings(LAST_CALENDAR_SHOW_TIMESTAMP) if tstampStr: try: return float(tstampStr) except (TypeError, ValueError): _logger.warning('Invalid calendar show timestamp') return None def __setShowTimestamp(self, tstamp): AccountSettings.setSettings(LAST_CALENDAR_SHOW_TIMESTAMP, str(tstamp)) @process def __openBrowser(self, browserID, browserSize, invokedFrom): """Shows the event calendar browser window, pointing to remote calendar single-page web application. """ url = yield self.__urlMacros.parse(GUI_SETTINGS.adventCalendarBaseURL, params={'called': invokedFrom}) if not url: _logger.error('Invalid calendar URL') return browserHandlers = [createRequestHandler(handleRequestCommand)] def showBrowserWindow(): ctx = {'size': browserSize, 'handlers': browserHandlers, 'browserID': browserID, 'alias': VIEW_ALIAS.ADVENT_CALENDAR, 'showCloseBtn': False, 'showWaiting': True, 'showActionBtn': False} g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(browserID), ctx=ctx), scope=EVENT_BUS_SCOPE.LOBBY) _logger.debug('Calendar browser window shown (browserID=%d)' % browserID) yield self.browserCtrl.load(url=url, browserID=browserID, browserSize=browserSize, isAsync=False, useBrowserWindow=False, showBrowserCallback=showBrowserWindow, showCreateWaiting=False)
class BrowserController(IBrowserController): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): """ Adds given @handler to the browser urls filter chain. Calls it if there is a @tag in url onto opened browser page. Handler should receive url and list of client-specific tags, return bool as flag that routine have to stop """ self.__filters.add(handler) def removeFilterHandler(self, handler): """ Remove given @handler from filtering chain. Handler description can be seen in addFilterhandler method doc-string """ self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = { 'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow } texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: self.__browsers[browserID].navigate(url) callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop( browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): self.__creatingBrowserID = None g_eventBus.handleEvent( BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__tryCreateNextPendingBrowser() return def __tryCreateNextPendingBrowser(self): if len(self.__pendingBrowsers) > 0: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) def __createBrowser(self, ctx): browserID = ctx['browserID'] self.__creatingBrowserID = browserID self.__browsers[browserID].create() self.onBrowserAdded(browserID) def browserCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser request url was not loaded!', url) self.__createDone(browserID) if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onReady += browserCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() ready, loadEnd = self.__browsersCallbacks.pop( browserID, (None, None)) if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if ready is not None: self.__browsers[browserID].onReady -= ready if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): if ctx.get('showWindow'): g_eventBus.handleEvent( LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class PromoController(Controller): PROMO_AUTO_VIEWS_TEST_VALUE = 5 def __init__(self, proxy): super(PromoController, self).__init__(proxy) self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False def fini(self): self._stop() self.__urlMacros.clear() self.__urlMacros = None super(PromoController, self).fini() def onLobbyInited(self, event): self._updatePromo(self._getPromoEventNotifications()) self._getEventsFotificationController( ).onEventNotificationsChanged += self.__onEventNotification self._getBrowserController( ).onBrowserDeleted += self.__onBrowserDeleted self._processPromo(self._getEventNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showPatchPromo(self, isAsync=False): self.__currentVersionBrowserID = yield self.__showPromoBrowser( self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE, version=getClientVersion()), browserID=self.__currentVersionBrowserID, isAsync=isAsync) def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None def _stop(self): self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self._getBrowserController( ).onBrowserDeleted -= self.__onBrowserDeleted self._getEventsFotificationController( ).onEventNotificationsChanged -= self.__onEventNotification @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable( ) and self.__currentVersionPromoUrl not in self.__promoShown and self.isPromoAutoViewsEnabled( ) and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) self.__promoShown.add(self.__currentVersionPromoUrl) self.__savePromoShown() self.__currentVersionBrowserShown = True self._isPromoShown = True self.showPatchPromo(isAsync=True) return actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter( lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE. ACTION), promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if item.eventType == gc_constants.PROMO.TEMPLATE.PATCH and self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = promoUrl promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = { url for url in promoShownSource if url in self.__availablePromo } self.__savePromoShown() def _getEventNotifications(self): return self._proxy.getController( gc_constants.CONTROLLER.EVENTS_NOTIFICATION ).getEventsNotifications() def _getPromoEventNotifications(self): filterFunc = lambda item: item.eventType in ( gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE. ACTION) return self._getEventsFotificationController().getEventsNotifications( filterFunc) def _getBrowserController(self): return self._proxy.getController(gc_constants.CONTROLLER.BROWSER) def _getEventsFotificationController(self): return self._proxy.getController( gc_constants.CONTROLLER.EVENTS_NOTIFICATION) def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent( events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID=None, isAsync=True, callback=None): browserID = yield self._getBrowserController().load( promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, background=gc_constants.BROWSER.PROMO_BACKGROUND, isDefault=False, showCloseBtn=True) callback(browserID) @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID( ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings( ).isPromoAutoViewsEnabled()
class BrowserController(IBrowserController): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserCreationCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browsersCallbacks.clear() self.__browsersCallbacks = None self.__browsers.clear() self.__browsers = None self.__pendingBrowsers.clear() self.__pendingBrowsers = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def addFilterHandler(self, handler): self.__filters.add(handler) def removeFilterHandler(self, handler): self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False): if showCreateWaiting: Waiting.show('browser/init') url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif type(browserID) is not int: webBrowserID = self.__browserIDGenerator.next() ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow, 'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW, 'showCreateWaiting': showCreateWaiting, 'handlers': handlers, 'showBrowserCallback': showBrowserCallback, 'isSolidBorder': isSolidBorder} if browserID not in self.__browsers and browserID not in self.__pendingBrowsers: texture = self._BROWSER_TEXTURE app = g_appLoader.getApp() if app is None: raise SoftException('Application can not be None') browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): _logger.debug('CTRL: Queueing a browser creation: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: _logger.debug('CTRL: Re-queuing a browser creation, overriding: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: _logger.debug('CTRL: Re-navigating an existing browser: %r - %s', browserID, url) browser = self.__browsers[browserID] browser.navigate(url) browser.changeTitle(title) callback(browserID) return def getAllBrowsers(self): return self.__browsers def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: _logger.debug('CTRL: Deleting a browser: %s', browserID) browser = self.__browsers.pop(browserID) self.__clearCallbacks(browserID, browser, True) browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() if browserID in self.__pendingBrowsers: del self.__pendingBrowsers[browserID] self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): _logger.debug('CTRL: Finished creating a browser: %s', self.__creatingBrowserID) if ctx['showCreateWaiting']: Waiting.hide('browser/init') def __tryCreateNextPendingBrowser(self): self.__creatingBrowserID = None if self.__pendingBrowsers: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) return def __createBrowser(self, ctx): browserID = ctx['browserID'] _logger.debug('CTRL: Creating a browser: %r - %s', browserID, ctx['url']) self.__creatingBrowserID = browserID browser = self.__browsers[browserID] if not browser.create(): _logger.debug('CTRL: Failed the create step: %r', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createBrowserTimeout(): _logger.debug('CTRL: Browser create timed out') createNextBrowser() timeoutid = BigWorld.callback(30.0, createBrowserTimeout) def createNextBrowser(): _logger.debug('CTRL: Triggering create of next browser from: %s', browserID) BigWorld.cancelCallback(timeoutid) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[browserID].onCanCreateNewBrowser -= creation BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser) return def failedCreationCallback(url): _logger.debug('CTRL: Failed a creation: %r - %s', browserID, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) self.delBrowser(browserID) def successfulCreationCallback(url, isLoaded, httpStatusCode=None): _logger.debug('CTRL: Ready to show: %r - %r - %s', browserID, isLoaded, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) if isLoaded: self.__showBrowser(browserID, ctx) else: _logger.warning('Browser request url %s was not loaded!', url) g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__createDone(ctx) def titleUpdateCallback(title): ctx['title'] = title browser.onCanCreateNewBrowser += createNextBrowser self.__browserCreationCallbacks[browserID] = createNextBrowser browser.onFailedCreation += failedCreationCallback browser.onTitleChange += titleUpdateCallback if ctx['isAsync']: self.__browsersCallbacks[browserID] = (None, successfulCreationCallback, failedCreationCallback, titleUpdateCallback) browser.onLoadEnd += successfulCreationCallback else: self.__browsersCallbacks[browserID] = (successfulCreationCallback, None, failedCreationCallback, titleUpdateCallback) browser.onReady += successfulCreationCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() self.__clearCallbacks(browserID, browser, True) browser.destroy() def __clearCallbacks(self, browserID, browser, incDelayedCreation): ready, loadEnd, failed, title = self.__browsersCallbacks.pop(browserID, (None, None, None, None)) if browser is not None: if failed is not None: browser.onFailedCreation -= failed if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd if title is not None: browser.onTitleChange -= title if incDelayedCreation: creation = self.__browserCreationCallbacks.pop(browserID, None) if browser is not None and creation is not None: browser.onCanCreateNewBrowser -= creation return def __showBrowser(self, browserID, ctx): _logger.debug('CTRL: Showing a browser: %r - %s', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent(LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY) showBrowserCallback = ctx.get('showBrowserCallback') if showBrowserCallback: showBrowserCallback()
class ExternalLinksHandler(Controller): def __init__(self, proxy): super(ExternalLinksHandler, self).__init__(proxy) self.__urlMarcos = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: LOG_ERROR('URL is empty', url) return try: BigWorld.wg_openWebBrowser(url) except Exception: LOG_ERROR('There is error while opening web browser at page:', url) LOG_CURRENT_EXCEPTION() @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName): parsedUrl = yield self.getURL(urlName) self.open(parsedUrl) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleClubSettings(self, _): self.__openParsedUrl('clubSettings') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo')
class RssNewsFeed(RssNewsFeedMeta): UPDATE_INTERVAL = 60 DESCRIPTION_MAX_LENGTH = 250 DESCRIPTION_TAIL = '...' DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL) SHOW_NEWS_COUNT = 3 externalBrowser = dependency.descriptor(IExternalLinksController) internalBrowser = dependency.descriptor(IBrowserController) def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMarcos() return def getFeed(self): return self.__feed def openBrowser(self, linkToOpen): if linkToOpen: openBrowser = self.externalBrowser.open if GUI_SETTINGS.loginRssFeed.internalBrowser: browser = self.internalBrowser if browser is not None: openBrowser = browser.load else: LOG_ERROR( 'Attempting to open internal browser, but browseris not exist. External browser will be opened', str(linkToOpen)) LOG_DEBUG('Open browser', linkToOpen) openBrowser(linkToOpen) return def _populate(self): super(RssNewsFeed, self)._populate() self.__updateCallback() def _dispose(self): self.__urlMacros.clear() self.__urlMacros = None self.__feed = [] self.__clearCallback() super(RssNewsFeed, self)._dispose() return @process def __requestFeed(self): yield lambda callback: callback(True) if GUI_SETTINGS.loginRssFeed.show: requestUrl = yield self.__getRssUrl() from helpers.RSSDownloader import g_downloader as g_rss if g_rss is not None: g_rss.download(self.__onRssFeedReceived, url=requestUrl) LOG_DEBUG('Requesting login RSS news', requestUrl) return def __onRssFeedReceived(self, data): if self.isDisposed(): return else: self.__feed = [] for entry in reversed(data.get('entries', [])): data = self.__prepareData(entry) if data is not None: self.__feed.append(data) LOG_DEBUG('RSS feed received, entries count', len(self.__feed)) self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT]) return def __clearCallback(self): if self.__requestCbID is not None: BigWorld.cancelCallback(self.__requestCbID) self.__requestCbID = None return def __updateCallback(self): self.__requestFeed() self.__clearCallback() self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback) @async @process def __getRssUrl(self, callback): if constants.IS_CHINA: callback('http://wot.kongzhong.com/erji/login_ticker.xml') url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url)) callback(url) def __prepareData(self, entryData): description = entryData.get('description') if description is not None: try: section = ResMgr.DataSection() section.createSectionFromString(encodeUtf8(description)) _, section = findFirst(lambda (name, _): name == 'div', section.items()) description, _ = unicode_from_utf8(section.asString) if len(description) > self.DESCRIPTION_MAX_LENGTH: description = description[:self. DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL except Exception: LOG_ERROR('Invalid RSS entry description', entryData, description) LOG_CURRENT_EXCEPTION() return return { 'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description) }
class PromoController(IPromoController): PROMO_AUTO_VIEWS_TEST_VALUE = 5 browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) lobbyContext = dependency.descriptor(ILobbyContext) class GUI_EVENTS(CONST_CONTAINER): CLOSE_GUI_EVENT = 'close_window' def __init__(self): super(PromoController, self).__init__() self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self.__guiActionsHandlers = None self.__isLobbyInited = False self.__pendingPromo = None self._isPromoShown = False return def fini(self): self._stop() self.__pendingPromo = None self.__urlMacros.clear() self.__urlMacros = None self.__guiActionsHandlers = None super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return self.__isLobbyInited = True self._updatePromo(self._getPromoEventNotifications()) self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted popupsWindowsDisabled = isPopupsWindowsOpenDisabled() if not popupsWindowsDisabled: self._processPromo( self.eventsNotification.getEventsNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showVersionsPatchPromo(self): promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens) webBrowser = self.__getCurrentBrowser() if not webBrowser or promoUrl != webBrowser.url: promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, promoTitle, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) def showPromo(self, url, title, forced=False, handlers=None): """ :param url: url that should be opened in the browser: :param title: the title of browser window: :param forced: True - promowindow with new URL will be shown in any case, False - new promowindow will be shown if there has not been already shown promowindow during the session: :param handlers: Dict: key - gui action self.GUI_EVENTS.* value - functions that should to be invoked when particular gui action has happened """ if forced: self.__registerAndShowPromoBrowser(url, title, handlers) self._isPromoShown = True elif self.__isLobbyInited: if not self._isPromoShown: self.__registerAndShowPromoBrowser(url, title, handlers) self._isPromoShown = True else: self.__pendingPromo = _PromoData(url, title, handlers) def getCurrentVersionBrowserID(self): return self.__currentVersionBrowserID @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID( ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and cls.lobbyContext.getServerSettings( ).isPromoAutoViewsEnabled() def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled def isPatchChanged(self): mainVersion = getClientMainVersion() return mainVersion is not None and AccountSettings.getSettings( LAST_PROMO_PATCH_VERSION) != mainVersion def _stop(self): self.__isLobbyInited = False self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.__cleanupGuiActionHandlers() self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification return @process def _showCurrentVersionPatchPromo(self, isAsync=False): self.__currentVersionBrowserID = yield self.__showPromoBrowser( self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE), browserID=self.__currentVersionBrowserID, isAsync=isAsync, showWaiting=not isAsync) @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.isPatchChanged( ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION, getClientMainVersion()) self.__currentVersionBrowserShown = True self._isPromoShown = True self._showCurrentVersionPatchPromo(isAsync=True) return elif not self._isPromoShown and self.__pendingPromo is not None: self.__registerAndShowPromoBrowser(*self.__pendingPromo) self.__pendingPromo = None return else: actionsPromo = [ item for item in promo if item.eventType.startswith( gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter( lambda item: item.eventType == gc_constants.PROMO.TEMPLATE. ACTION, promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = yield self.__urlMacros.parse( GUI_SETTINGS.currentVersionPromo) promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = { url for url in promoShownSource if url in self.__availablePromo } self.__savePromoShown() return def _getPromoEventNotifications(self): def filterFunc(item): return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION return self.eventsNotification.getEventsNotifications(filterFunc) def __onUserRequestToClose(self): self.__guiActionsHandlers[self.GUI_EVENTS.CLOSE_GUI_EVENT]() self.__cleanupGuiActionHandlers() def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent( events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return def __registerGuiActionHandlers(self, handlers): self.__guiActionsHandlers = handlers if handlers: webBrowser = self.__getCurrentBrowser() if webBrowser is not None: webBrowser.onUserRequestToClose += self.__onUserRequestToClose else: LOG_WARNING('Browser with id = "{}" has not been found'.format( self.__currentVersionBrowserID)) return def __cleanupGuiActionHandlers(self): webBrowser = self.__getCurrentBrowser() if self.__guiActionsHandlers is not None and webBrowser: webBrowser.onUserRequestToClose -= self.__onUserRequestToClose self.__guiActionsHandlers = None return @process def __registerAndShowPromoBrowser(self, url, title, handlers): promoUrl = yield self.__urlMacros.parse(url) LOG_DEBUG('Showing promo:', promoUrl) webBrowser = self.__getCurrentBrowser() if not webBrowser or promoUrl != webBrowser.url: self.__cleanupGuiActionHandlers() self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, title, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) self.__registerGuiActionHandlers(handlers) def __getCurrentBrowser(self): return self.browserCtrl.getBrowser(self.__currentVersionBrowserID) @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID=None, isAsync=True, showWaiting=False, callback=None): browserID = yield self.browserCtrl.load( promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, isDefault=False, showCloseBtn=True, showWaiting=showWaiting, handlers=self.__createPromoWebHandlers()) callback(browserID) def __createPromoWebHandlers(self): return [ createHangarSoundHandler(handleHangarSoundCommand, handleHangarSoundCommandFini) ]
class PromoController(IPromoController): PROMO_AUTO_VIEWS_TEST_VALUE = 5 browserCtrl = dependency.descriptor(IBrowserController) eventsNotification = dependency.descriptor(IEventsNotificationsController) def __init__(self): super(PromoController, self).__init__() self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.__promoShown = set() self.__availablePromo = set() self.__urlMacros = URLMarcos() self._isPromoShown = False return def fini(self): self._stop() self.__urlMacros.clear() self.__urlMacros = None super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return self._updatePromo(self._getPromoEventNotifications()) self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted self._processPromo(self.eventsNotification.getEventsNotifications()) def onAvatarBecomePlayer(self): self._stop() def onDisconnected(self): self._stop() self._isPromoShown = False @process def showCurrentVersionPatchPromo(self, isAsync=False): self.__currentVersionBrowserID = yield self.__showPromoBrowser( self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE), browserID=self.__currentVersionBrowserID, isAsync=isAsync, showWaiting=not isAsync) @process def showVersionsPatchPromo(self): promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens) promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, promoTitle, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) @process def showPromo(self, url, title): promoUrl = yield self.__urlMacros.parse(url) self.__currentVersionBrowserID = yield self.__showPromoBrowser( promoUrl, title, browserID=self.__currentVersionBrowserID, isAsync=False, showWaiting=True) def isPatchPromoAvailable(self): return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled def isPatchChanged(self): mainVersion = getClientMainVersion() return mainVersion is not None and AccountSettings.getSettings( LAST_PROMO_PATCH_VERSION) != mainVersion def _stop(self): self.__currentVersionPromoUrl = None self.__currentVersionBrowserID = None self.__currentVersionBrowserShown = False self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification return @process def _processPromo(self, promo): yield lambda callback: callback(True) if self.isPatchPromoAvailable() and self.isPatchChanged( ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown: LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl) AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION, getClientMainVersion()) self.__currentVersionBrowserShown = True self._isPromoShown = True self.showCurrentVersionPatchPromo(isAsync=True) return actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ] for actionPromo in actionsPromo: promoUrl = yield self.__urlMacros.parse(actionPromo.data) promoTitle = actionPromo.text if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl: LOG_DEBUG('Showing action promo:', promoUrl) self.__promoShown.add(promoUrl) self.__savePromoShown() self._isPromoShown = True yield self.__showPromoBrowser(promoUrl, promoTitle) return @process def _updatePromo(self, promosData): yield lambda callback: callback(True) for item in filter( lambda item: item.eventType == gc_constants.PROMO.TEMPLATE. ACTION, promosData): promoUrl = yield self.__urlMacros.parse(item.data) self.__availablePromo.add(promoUrl) if self.__currentVersionPromoUrl is None: self.__currentVersionPromoUrl = yield self.__urlMacros.parse( GUI_SETTINGS.currentVersionPromo) promoShownSource = AccountSettings.getFilter(PROMO) self.__promoShown = { url for url in promoShownSource if url in self.__availablePromo } self.__savePromoShown() return def _getPromoEventNotifications(self): def filterFunc(item): return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION return self.eventsNotification.getEventsNotifications(filterFunc) def __savePromoShown(self): AccountSettings.setFilter(PROMO, self.__promoShown) def __onEventNotification(self, added, removed): self._updatePromo(self._getPromoEventNotifications()) self._processPromo(added) def __onBrowserDeleted(self, browserID): if self.__currentVersionBrowserID == browserID: self.__currentVersionBrowserID = None if self.__currentVersionBrowserShown: self.__currentVersionBrowserShown = False g_eventBus.handleEvent(events.BubbleTooltipEvent( events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY) return @async @process def __showPromoBrowser(self, promoUrl, promoTitle, browserID=None, isAsync=True, showWaiting=False, callback=None): browserID = yield self.browserCtrl.load( promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, isDefault=False, showCloseBtn=True, showWaiting=showWaiting) callback(browserID) @classmethod def isPromoAutoViewsEnabled(cls): return getAccountDatabaseID( ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings( ).isPromoAutoViewsEnabled()
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False): url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE if browserID is None: browserID = self.__browserIDGenerator.next() if browserID not in self.__browsers: texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE app = g_appLoader.getApp() if not app: raise AssertionError('Application can not be None') self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url) self.onBrowserAdded(browserID) ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn} def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) def browserAsyncCallback(url, isLoaded): self.__clearCallback(browserID) if isLoaded: self.__showBrowser(browserID, ctx) else: LOG_WARNING('Browser async request url was not loaded!', url) self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserAsyncCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) return def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() return def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd return def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class BrowserController(Controller): _BROWSER_TEXTURE = 'BrowserBg' _ALT_BROWSER_TEXTURE = 'AltBrowserBg' def __init__(self, proxy): super(BrowserController, self).__init__(proxy) self.__browsers = {} self.__browsersCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMarcos() def fini(self): self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browserIDGenerator = None super(BrowserController, self).fini() def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() @async @process def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, background = None, isDefault = True, callback = None, showCloseBtn = False): url = url or GUI_SETTINGS.browser.url suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE background = background or BROWSER.BACKGROUND if browserID is None: browserID = self.__browserIDGenerator.next() if browserID not in self.__browsers: texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE app = g_appLoader.getApp() assert app, 'Application can not be None' self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url, backgroundUrl=background) self.onBrowserAdded(browserID) ctx = {'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isDefault': isDefault, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn} def browserCallback(*args): self.__clearCallback(browserID) self.__showBrowser(browserID, ctx) if isAsync: self.__browsersCallbacks[browserID] = (None, browserCallback) self.__browsers[browserID].onLoadEnd += browserCallback else: self.__browsersCallbacks[browserID] = (browserCallback, None) self.__browsers[browserID].onLoadStart += browserCallback callback(browserID) def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: browser = self.__browsers.pop(browserID) loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() self.onBrowserDeleted(browserID) def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: browser.onLoadStart -= loadStart if loadEnd is not None: browser.onLoadEnd -= loadEnd browser.destroy() def __clearCallback(self, browserID): if browserID in self.__browsersCallbacks: loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None)) if loadStart is not None: self.__browsers[browserID].onLoadStart -= loadStart if loadEnd is not None: self.__browsers[browserID].onLoadEnd -= loadEnd def __showBrowser(self, browserID, ctx): g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)