package org.vaadin.touchkit.settings; import org.jsoup.nodes.DataNode; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.vaadin.touchkit.extensions.LocalStorage; import org.vaadin.touchkit.gwt.client.offlinemode.CacheManifestStatusIndicator; import com.vaadin.server.BootstrapFragmentResponse; import com.vaadin.server.BootstrapListener; import com.vaadin.server.BootstrapPageResponse; import com.vaadin.server.UICreateEvent; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinService; import com.vaadin.shared.VBrowserDetails; /** * This class is used to control HTML5 application cache settings. */ @SuppressWarnings("serial") public class ApplicationCacheSettings implements BootstrapListener { private boolean cacheManifestEnabled = true; private boolean offlineModeEnabled = true; @Override public void modifyBootstrapFragment(BootstrapFragmentResponse response) { // NOP } @Override public void modifyBootstrapPage(BootstrapPageResponse response) { Document document = response.getDocument(); // Add the widgetsetUrl parameter to the bootstrap parameters. // This is overridden to avoid adding the naive random query // parameter (used by core to avoid caching of js file). final VaadinService service = response.getSession().getService(); final VaadinRequest request = response.getRequest(); final String staticFilePath = service .getStaticFileLocation(request); // VAADIN folder location final String vaadinDir = staticFilePath + "/VAADIN/"; // Figure out widgetset final UICreateEvent event = new UICreateEvent(request, response.getUiClass()); String widgetset = response.getUIProvider().getWidgetset(event); if (widgetset == null) { widgetset = request.getService() .getConfiguredWidgetset(request); } // Url for the widgetset final String widgetsetUrl = String.format( "%swidgetsets/%s/%s.nocache.js", vaadinDir, widgetset, widgetset); // Update the bootstrap page Element scriptTag = document.getElementsByTag("script").last(); String script = scriptTag.html(); scriptTag.html(""); script = script.replace("});", ",\"widgetsetUrl\":\"" + widgetsetUrl + "\",\"offlineEnabled\":" + isOfflineModeEnabled() + "});"); scriptTag.appendChild(new DataNode(script, scriptTag.baseUri())); if (isCacheManifestEnabled()) { // Add cache manifest attribute to html tag document.getElementsByTag("html").attr( "manifest", vaadinDir + "widgetsets/" + widgetset + "/" + generateManifestFileName(response)); } } /** * Generates the manifest file name for the given page response * * @param response * Page response where the manifest will be added. * @return The manifest file name, eg. "safari.manifest". */ protected String generateManifestFileName(BootstrapPageResponse response) { String userAgent = response.getRequest().getHeader("user-agent"); if (userAgent == null) { // Should not happen in "normal" cases but the header is optional return "safari.manifest"; } VBrowserDetails browser = new VBrowserDetails(userAgent); if (browser.isFirefox()) { return "gecko1_8.manifest"; } else if (browser.isChrome()) { return "safari.manifest"; } else if (browser.isIE()) { if (browser.getBrowserMajorVersion() > 10) { return "gecko1_8.manifest"; } else { return "ie10.manifest"; } } else if (browser.isAndroid()) { int major = browser.getOperatingSystemMajorVersion(); int minor = browser.getOperatingSystemMinorVersion(); if (major < 4 || (major == 4 && minor < 4)) { return "aosp.manifest"; } else { return "safari.manifest"; } } else { return "safari.manifest"; } } /** * @return true if the cache manifest (and thus application cache) is * enabled. */ public boolean isCacheManifestEnabled() { return cacheManifestEnabled; } /** * Enable or disable the cache manifest (and thus application cache). * * @param cacheManifestEnabled * true to enable. */ public void setCacheManifestEnabled(boolean cacheManifestEnabled) { this.cacheManifestEnabled = cacheManifestEnabled; } /** * @return true is offline is enabled in client side. */ public boolean isOfflineModeEnabled() { return offlineModeEnabled; } /** * Enable or disable offline mode in client side. */ public void setOfflineModeEnabled(boolean offlineModeEnabled) { this.offlineModeEnabled = offlineModeEnabled; } /** * Specifies the message to show when an update to the application cache is * available. When a new version of the application cache has been loaded by * the client, this message is shown in a confirmation box. Answering 'OK' * in this box causes the application to refresh and use the new application * cache (== new version of the widget set). * * @param message * The new message. The default is * "There are updates ready to be installed. Would you like to restart now?" */ public void setUpdateNowMessage(String message) { LocalStorage.get().put(CacheManifestStatusIndicator.UPDATE_NOW_MSG_KEY, message); } /** * Specifies how often to check for and download updates to the application * cache (== widget set). * * @param interval * The interval in seconds. The default is 30 minutes (1800 * seconds). */ public void setUpdateCheckInterval(int interval) { LocalStorage.get().put( CacheManifestStatusIndicator.UPDATE_CHECK_INTERVAL_KEY, String.valueOf(interval)); } }