michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.background.announcements; michael@0: michael@0: import java.io.UnsupportedEncodingException; michael@0: import java.net.URI; michael@0: import java.net.URISyntaxException; michael@0: import java.net.URLEncoder; michael@0: michael@0: import org.mozilla.gecko.background.common.GlobalConstants; michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: import org.mozilla.gecko.sync.net.BaseResource; michael@0: michael@0: public class AnnouncementsFetcher { michael@0: private static final String LOG_TAG = "AnnounceFetch"; michael@0: private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; michael@0: michael@0: public static URI getSnippetURI(String base, String channel, michael@0: String version, String platform, michael@0: int idleDays) michael@0: throws URISyntaxException { michael@0: try { michael@0: final String c = URLEncoder.encode(channel, "UTF-8"); michael@0: final String v = URLEncoder.encode(version, "UTF-8"); michael@0: final String p = URLEncoder.encode(platform, "UTF-8"); michael@0: final String s = base + c + "/" + v + "/" + p + ((idleDays == -1) ? "" : ("?idle=" + idleDays)); michael@0: return new URI(s); michael@0: } catch (UnsupportedEncodingException e) { michael@0: // Nonsense. michael@0: return null; michael@0: } michael@0: } michael@0: michael@0: public static URI getAnnounceURI(final String baseURL, final long lastLaunch) throws URISyntaxException { michael@0: final String channel = getChannel(); michael@0: final String version = getVersion(); michael@0: final String platform = getPlatform(); michael@0: final int idleDays = getIdleDays(lastLaunch); michael@0: michael@0: Logger.debug(LOG_TAG, "Fetch URI: idle for " + idleDays + " days."); michael@0: return getSnippetURI(baseURL, channel, version, platform, idleDays); michael@0: } michael@0: michael@0: protected static String getChannel() { michael@0: return AnnouncementsConstants.ANNOUNCE_CHANNEL; michael@0: } michael@0: michael@0: protected static String getVersion() { michael@0: return GlobalConstants.MOZ_APP_VERSION; michael@0: } michael@0: michael@0: protected static String getPlatform() { michael@0: return GlobalConstants.ANDROID_CPU_ARCH; michael@0: } michael@0: michael@0: /** michael@0: * Return the number of days that we've been idle, assuming that we have a michael@0: * sane last launch time and the current time is within range. If no sane idle michael@0: * time can be returned, we return -1. michael@0: * michael@0: * @param lastLaunch michael@0: * Time at which the browser was last launched, in milliseconds since epoch. michael@0: * @param now michael@0: * Milliseconds since epoch for which idle time should be calculated. michael@0: * @return number of idle days, or -1 if out of range. michael@0: */ michael@0: protected static int getIdleDays(final long lastLaunch, final long now) { michael@0: if (lastLaunch <= 0) { michael@0: return -1; michael@0: } michael@0: michael@0: if (now < GlobalConstants.BUILD_TIMESTAMP_MSEC) { michael@0: Logger.warn(LOG_TAG, "Current time " + now + " earlier than build date. Not calculating idle."); michael@0: return -1; michael@0: } michael@0: michael@0: if (now < lastLaunch) { michael@0: Logger.warn(LOG_TAG, "Current time " + now + " earlier than last launch! Not calculating idle."); michael@0: return -1; michael@0: } michael@0: michael@0: final long idleMillis = now - lastLaunch; michael@0: final int idleDays = (int) (idleMillis / MILLISECONDS_PER_DAY); michael@0: michael@0: if (idleDays > AnnouncementsConstants.MAX_SANE_IDLE_DAYS) { michael@0: Logger.warn(LOG_TAG, "Idle from " + lastLaunch + " until " + now + michael@0: ", which is insane. Not calculating idle."); michael@0: return -1; michael@0: } michael@0: michael@0: return idleDays; michael@0: } michael@0: michael@0: /** michael@0: * Return the number of days that we've been idle, assuming that we have a michael@0: * sane last launch time and the current time is within range. If no sane idle michael@0: * time can be returned, we return -1. michael@0: * The current time will be calculated from {@link System#currentTimeMillis()}. michael@0: * michael@0: * @param lastLaunch michael@0: * Unix timestamp at which the browser was last launched. michael@0: * @return number of idle days, or -1 if out of range. michael@0: */ michael@0: protected static int getIdleDays(final long lastLaunch) { michael@0: final long now = System.currentTimeMillis(); michael@0: return getIdleDays(lastLaunch, now); michael@0: } michael@0: michael@0: public static void fetchAnnouncements(URI uri, AnnouncementsFetchDelegate delegate) { michael@0: BaseResource r = new BaseResource(uri); michael@0: r.delegate = new AnnouncementsFetchResourceDelegate(r, delegate); michael@0: r.getBlocking(); michael@0: } michael@0: michael@0: /** michael@0: * Synchronous. michael@0: */ michael@0: public static void fetchAndProcessAnnouncements(long lastLaunch, michael@0: AnnouncementsFetchDelegate delegate) { michael@0: final long now = System.currentTimeMillis(); michael@0: Logger.debug(LOG_TAG, "Fetching announcements. Last launch: " + lastLaunch + "; now: " + now); michael@0: try { michael@0: final String base = delegate.getServiceURL(); michael@0: final URI uri = getAnnounceURI(base, lastLaunch); michael@0: Logger.info(LOG_TAG, "Fetching announcements from " + uri.toASCIIString()); michael@0: fetchAnnouncements(uri, delegate); michael@0: } catch (URISyntaxException e) { michael@0: Logger.warn(LOG_TAG, "Couldn't create URL.", e); michael@0: return; michael@0: } michael@0: } michael@0: }