Package com.denormans.facebookgwt.api.client.init

Source Code of com.denormans.facebookgwt.api.client.init.FBInitialization

/*
* Copyright (C) 2010 deNormans
* http://www.denormans.com/
* All rights reserved.
*
* This software is the confidential and proprietary information of deNormans ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use it only in accordance with the terms of the license
* agreement you entered into with deNormans.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* DENORMANS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.denormans.facebookgwt.api.client.init;

import com.denormans.facebookgwt.api.client.EventHandlerException;
import com.denormans.facebookgwt.api.client.init.events.FBInitFailureEvent;
import com.denormans.facebookgwt.api.client.init.events.FBInitFailureHandler;
import com.denormans.facebookgwt.api.client.init.events.FBInitSuccessEvent;
import com.denormans.facebookgwt.api.client.init.events.FBInitSuccessHandler;
import com.denormans.facebookgwt.api.client.init.events.HasFBInitHandlers;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.ScriptElement;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public final class FBInitialization implements HasFBInitHandlers  {
  private static final Logger Log = Logger.getLogger(FBInitialization.class.getName());

  public enum InitializationState { Uninitialized, LoadingScript, ScriptLoaded, Initialized;}

  public static final int InitializationTimeoutSeconds = 10;

  public static final String FacebookRootElementID = "fb-root";
  public static final String FacebookScriptElementID = "fb-script-all";
  public static final String DefaultLocale = "en_US";
  private static final String FacebookScriptServer = "connect.facebook.net";
  private static final String FacebookScriptName = "all.js";

  private EventBus eventBus = new SimpleEventBus();

  private List<Scheduler.ScheduledCommand> deferredFBCommands = new ArrayList<Scheduler.ScheduledCommand>();

  private FBInitialization.InitializationState initializationState = FBInitialization.InitializationState.Uninitialized;
  private Timer initializationTimer;

  /**
   * Determines whether or not Facebook has been initialized with this API.
   *
   * @return whether or not Facebook has been initialized.
   */
  public boolean isInitialized() {
    return initializationState == FBInitialization.InitializationState.Initialized;
  }

  /**
   * Returns the current initialization state.  If {@link #initialize} call hasn't been called yet, the state is {@link FBInitialization.InitializationState#Uninitialized}.
   *
   * @return the initialization state.
   */
  public FBInitialization.InitializationState getInitializationState() {
    return initializationState;
  }

  /**
   * Initialize Facebook.  This is handled asynchronously so callbacks should be registered to be called when Facebook is initialized.
   *
   * Uses the default initialization timeout.
   *
   * @param initOptions initialization options
   */
  public void initialize(final FBInitOptions initOptions) {
    initialize(null, initOptions, FBInitialization.InitializationTimeoutSeconds);
  }

  /**
   * Initialize Facebook.  This is handled asynchronously so callbacks should be registered to be called when Facebook is initialized.
   *
   * Uses the default initialization timeout.
   *
   * @param locale The explicit locale
   * @param initOptions initialization options
   */
  public void initialize(final String locale, final FBInitOptions initOptions) {
    initialize(locale, initOptions, FBInitialization.InitializationTimeoutSeconds);
  }

  /**
   * Initialize Facebook.  This is handled asynchronously so callbacks should be registered to be called when Facebook is initialized.
   * <p>
   * Calling this method will eventually fire all registered init events, even if already initialized.
   *
   * @param initOptions initialization options
   * @param initializationTimeout The timeout (in seconds) before an init failure event is fired.
   */
  public synchronized void initialize(final FBInitOptions initOptions, final int initializationTimeout) {
    initialize(null, initOptions, initializationTimeout);
  }

  /**
   * Initialize Facebook.  This is handled asynchronously so callbacks should be registered to be called when Facebook is initialized.
   * <p>
   * Calling this method will eventually fire all registered init events, even if already initialized.
   *
   * @param locale The explicit locale
   * @param initOptions initialization options
   * @param initializationTimeout The timeout (in seconds) before an init failure event is fired.
   */
  public synchronized void initialize(final String locale, final FBInitOptions initOptions, final int initializationTimeout) {
    if (initializationState == FBInitialization.InitializationState.LoadingScript || initializationState == FBInitialization.InitializationState.ScriptLoaded) {
      return;
    }

    if (initializationState == FBInitialization.InitializationState.Initialized) {
      if (initOptions != null) {
        executeFBInit(initOptions);
        Log.fine("Facebook reinitialized");
      }

      fireInitSuccess();
      return;
    }

    initializationState = FBInitialization.InitializationState.LoadingScript;
    Log.fine("Initializing Facebook...");

    setupFBAsyncInitCallback(initOptions);

    if (hasFacebookScriptElement()) {
      // found the script block, so assume we're initialized
      initializationState = FBInitialization.InitializationState.Initialized;
      fireInitSuccess();
      return;
    }

    Document doc = Document.get();
    Element fbRootElement = doc.getElementById(FacebookRootElementID);
    if (fbRootElement == null) {
      fbRootElement = DOM.createDiv();
      fbRootElement.setId(FacebookRootElementID);
      BodyElement bodyElement = doc.getBody();
      bodyElement.appendChild(fbRootElement);
    }

    String fbLocale = locale;
    if (fbLocale == null) {
      // todo: get default locale from user, accounting for list of Facebook-allowed locales, available from http://www.facebook.com/translations/FacebookLocales.xml
      fbLocale = DefaultLocale;
    }

    ScriptElement script = doc.createScriptElement();
    script.setType("text/javascript");
    script.setId(FacebookScriptElementID);
    script.setSrc(Window.Location.getProtocol() + "//" + FacebookScriptServer + "/" + fbLocale + "/" + FacebookScriptName);
    // facebook seems to think this async is necessary
    script.setPropertyBoolean("async", true);

    if (initializationTimeout > 0) {
      if (initializationTimer == null) {
        initializationTimer = new Timer() {
          @Override
          public void run() {
            fireInitFailure();
          }
        };
      }
      initializationTimer.cancel();
      initializationTimer.schedule(initializationTimeout * 1000);
    }

    fbRootElement.appendChild(script);
  }

  private boolean hasFacebookScriptElement() {
    Document doc = Document.get();
    if (doc.getElementById(FacebookScriptElementID) != null) {
      return true;
    }

    // enhance: check other script elements for facebook API access (?)

    return false;
  }

  /**
   * Executes the given command with Facebook, whenever it's initialized.
   *
   * @param command The command to execute
   */
  public synchronized void executeWithFB(final Scheduler.ScheduledCommand command) {
    if(isInitialized()) {
      command.execute();
    } else {
      deferredFBCommands.add(command);
    }
  }

  private native void setupFBAsyncInitCallback(final FBInitOptions initOptions) /*-{
    try {
      var self = this;
      var oldFBAsyncInit = $wnd.fbAsyncInit;
      $wnd.fbAsyncInit = function() {
        // reset the old fbAsyncInit in case this is called again
        $wnd.fbAsyncInit = oldFBAsyncInit;

        try {
          // call the old one first
          if (oldFBAsyncInit) {
            oldFBAsyncInit();
          }
        } catch(e) {
          @com.denormans.facebookgwt.gwtutil.client.js.JSError::raiseException(Ljava/lang/Object;)(e);
        }

        self.@com.denormans.facebookgwt.api.client.init.FBInitialization::handleFBAsyncInit(Lcom/denormans/facebookgwt/api/client/init/FBInitOptions;)(initOptions);
      }
    } catch(e) {
    }
  }-*/;

  @SuppressWarnings ({ "UnusedDeclaration" })
  private synchronized void handleFBAsyncInit(final FBInitOptions initOptions) {
    try {
      initializationState = InitializationState.ScriptLoaded;

      initializationTimer.cancel();
      initializationTimer = null;

      if (initOptions != null) {
        executeFBInit(initOptions);
      }

      final List<Scheduler.ScheduledCommand> deferredCommands = new ArrayList<Scheduler.ScheduledCommand>(deferredFBCommands);
      deferredFBCommands.clear();

      Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
        @Override
        public void execute() {
          for(Scheduler.ScheduledCommand deferredCommand : deferredCommands) {
            deferredCommand.execute();
          }
        }
      });

      initializationState = InitializationState.Initialized;

      Log.fine("Facebook initialized");
      fireInitSuccess();
    } catch (Throwable t) {
      GWT.UncaughtExceptionHandler uncaughtExceptionHandler = GWT.getUncaughtExceptionHandler();
      if (uncaughtExceptionHandler == null) {
        throw new EventHandlerException("Error handling Facebook init callback", t);
      }

      uncaughtExceptionHandler.onUncaughtException(t);
    }
  }

  /**
   * Must be called after FB script is loaded.
   *
   * @param initOptions The initialization options
   */
  private native void executeFBInit(final FBInitOptions initOptions) /*-{
    $wnd.FB.init(initOptions);
  }-*/;

  protected void fireInitSuccess() {
    FBInitSuccessEvent.fire(this);
  }

  protected void fireInitFailure() {
    FBInitFailureEvent.fire(this);
  }

  @Override
  public HandlerRegistration addFBInitSuccessHandler(final FBInitSuccessHandler handler) {
    return eventBus.addHandler(FBInitSuccessEvent.getType(), handler);
  }

  @Override
  public HandlerRegistration addFBInitFailureHandler(final FBInitFailureHandler handler) {
    return eventBus.addHandler(FBInitFailureEvent.getType(), handler);
  }

  @Override
  public void fireEvent(final GwtEvent<?> event) {
    eventBus.fireEvent(event);
  }
}
TOP

Related Classes of com.denormans.facebookgwt.api.client.init.FBInitialization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.