/* * Copyright 2013 cruxframework.org. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.cruxframework.crux.core.clientoffline; import java.util.logging.Level; import java.util.logging.Logger; import org.cruxframework.crux.core.client.collection.FastList; import org.cruxframework.crux.core.clientoffline.NetworkEvent.Handler; import com.google.gwt.core.client.GWT; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.logging.client.LogConfiguration; /** * A Network detection tool. * @author Thiago da Rosa de Bustamante * */ public class Network implements HasNetworkHandlers { private static Logger logger = Logger.getLogger(Network.class.getName()); private static Network instance; private Impl impl; public static abstract class Impl implements HasNetworkHandlers { protected OfflineMessages messages = GWT.create(OfflineMessages.class); protected FastList<Handler> handlers = new FastList<NetworkEvent.Handler>(); public HandlerRegistration addNetworkHandler(final Handler handler) { handlers.add(handler); return new HandlerRegistration() { @Override public void removeHandler() { int index = handlers.indexOf(handler); if (index >= 0) { handlers.remove(index); } } }; } /** * Check if this browser support Crux offline working. * @return */ public boolean isSupported() { return true; } protected void fireOnLineEvent() { fireEvent(new NetworkEvent(true)); } protected void fireOffLineEvent() { fireEvent(new NetworkEvent(false)); } public void fireEvent(NetworkEvent event) { for (int i = 0; i < handlers.size(); i++) { handlers.get(i).onNetworkChanged(event); } } } public static class SafariImpl extends Impl { public SafariImpl() { createNetworkEventListeners(this); } @Override public native boolean isOnLine()/*-{ return navigator.onLine; }-*/; private native void createNetworkEventListeners(SafariImpl instance)/*-{ $wnd.addEventListener('offline', function(event) { instance.@org.cruxframework.crux.core.clientoffline.Network.SafariImpl::fireOffLineEvent()(); }, false); $wnd.addEventListener('online', function(event) { instance.@org.cruxframework.crux.core.clientoffline.Network.SafariImpl::fireOnLineEvent()(); }, false); }-*/; } public static class UnsupportedImpl extends Impl { @Override public boolean isOnLine() { throw new UnsupportedOperationException(); } @Override public HandlerRegistration addNetworkHandler(Handler handler) { throw new UnsupportedOperationException(); }; @Override public boolean isSupported() { return false; } } public static class CacheManifestImpl extends Impl { private boolean isOnLine = getInitialState(); public CacheManifestImpl() { ApplicationCacheHandler.addApplicationCacheHandler(new ApplicationCacheEvent.Handler() { @Override public void onCacheEvent(ApplicationCacheEvent event) { switch (event.getEventType()) { case onDownloading: case onUpdateready: case onNoupdate: onCacheHitEvent(); break; case onError: onCacheFailedEvent(); default: //ignores } } }); ApplicationCacheHandler.updateCache(); } private native boolean getInitialState()/*-{ if (navigator.onLine){ return true; } return false; }-*/; @Override public boolean isOnLine() { return isOnLine; } private void onCacheHitEvent() { if (LogConfiguration.loggingIsEnabled()) { logger.log(Level.INFO, messages.networkOnLine()); logger.log(Level.FINE, "onCacheHitEvent: old status: "+isOnLine); } boolean oldStatus = isOnLine; isOnLine = true; if (!oldStatus) { fireOnLineEvent(); } } private void onCacheFailedEvent() { if (LogConfiguration.loggingIsEnabled()) { logger.log(Level.INFO, messages.networkOffLine()); logger.log(Level.FINE, "onCacheFailedEvent: old status: "+isOnLine); } boolean oldStatus = isOnLine; isOnLine = false; if (oldStatus) { fireOffLineEvent(); } } } /** * Singleton constructor */ private Network() { impl = GWT.create(Impl.class); } /** * Retrieve the Network instance * @return */ public static Network get() { if (instance == null) { if (LogConfiguration.loggingIsEnabled()) { logger.log(Level.FINE, "Creating new Network monitor"); } instance = new Network(); } return instance; } /** * Returns true if the application has network connection */ @Override public boolean isOnLine() { return impl.isOnLine(); } /** * Add a network events handler */ @Override public HandlerRegistration addNetworkHandler(Handler handler) { return impl.addNetworkHandler(handler); } /** * Check if this browser support Crux offLine working. * @return true if offLine is supported. */ public boolean isSupported() { return impl.isSupported(); } }