/*
 * Copyright 2010 Google Inc.
 *
 * 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 com.google.gwt.core.linker;

import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.CompilationResult;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.core.ext.linker.ScriptReference;
import com.google.gwt.core.ext.linker.Shardable;
import com.google.gwt.core.ext.linker.impl.PropertiesMappingArtifact;
import com.google.gwt.core.ext.linker.impl.PropertiesUtil;
import com.google.gwt.core.ext.linker.impl.ResourceInjectionUtil;
import com.google.gwt.core.ext.linker.impl.SelectionScriptLinker;
import com.google.gwt.dev.About;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.TextOutput;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Splitter;
import com.google.gwt.util.tools.Utility;
import com.google.gwt.util.tools.shared.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;

/**
 * This linker uses an iframe to hold the code and a script tag to download the
 * code. It can download code cross-site, because it uses a script tag to
 * download it and because it never uses XHR. The iframe, meanwhile, makes it
 * trivial to install additional code as the app runs.
 */
@LinkerOrder(Order.PRIMARY)
@Shardable
public class CrossSiteIframeLinker extends SelectionScriptLinker {
  /**
   * A configuration property that can be used to have the linker ignore the
   * script tags in gwt.xml rather than fail to compile if they are present.
   */
  private static final String FAIL_IF_SCRIPT_TAG_PROPERTY = "xsiframe.failIfScriptTag";

  @Override
  public String getDescription() {
    return "Cross-Site-Iframe";
  }

  @Override
  protected String fillSelectionScriptTemplate(StringBuffer ss, TreeLogger logger,
      LinkerContext context, ArtifactSet artifacts, CompilationResult result)
      throws UnableToCompleteException {

    if (shouldUseSelfForWindowAndDocument(context)) {
      replaceAll(ss, "__WINDOW_DEF__", "self");
      replaceAll(ss, "__DOCUMENT_DEF__", "self");
    } else {
      replaceAll(ss, "__WINDOW_DEF__", "window");
      replaceAll(ss, "__DOCUMENT_DEF__", "document");
    }

    // Must do installScript before waitForBodyLoaded and we must do
    // waitForBodyLoaded before isBodyLoaded
    includeJs(ss, logger, getJsInstallScript(context), "__INSTALL_SCRIPT__");
    includeJs(ss, logger, getJsWaitForBodyLoaded(context), "__WAIT_FOR_BODY_LOADED__");
    includeJs(ss, logger, getJsIsBodyLoaded(context), "__IS_BODY_LOADED__");

    // Must do permutations before providers
    includeJs(ss, logger, getJsPermutations(context), "__PERMUTATIONS__");
    includeJs(ss, logger, getJsProperties(context), "__PROPERTIES__");

    // Order doesn't matter for the rest
    includeJs(ss, logger, getJsProcessMetas(context), "__PROCESS_METAS__");
    includeJs(ss, logger, getJsInstallLocation(context), "__INSTALL_LOCATION__");
    includeJs(ss, logger, getJsComputeScriptBase(context), "__COMPUTE_SCRIPT_BASE__");
    includeJs(ss, logger, getJsComputeUrlForResource(context), "__COMPUTE_URL_FOR_RESOURCE__");
    includeJs(ss, logger, getJsLoadExternalStylesheets(context), "__LOAD_STYLESHEETS__");
    includeJs(ss, logger, getJsRunAsync(context), "__RUN_ASYNC__");
    includeJs(ss, logger, getJsDevModeRedirectHook(context), "__DEV_MODE_REDIRECT_HOOK__");

    // Must go after __DEV_MODE_REDIRECT_HOOK__ because they're found in DevModeRedirectHook.js.
    includeJs(ss, logger, getJsDevModeRedirectHookPermitted(context),
        "__DEV_MODE_REDIRECT_HOOK_PERMITTED__");
    includeJs(ss, logger, getJsDevModeUrlValidation(context), "__DEV_MODE_URL_VALIDATION__");

    // This Linker does not support <script> tags in the gwt.xml
    SortedSet<ScriptReference> scripts = artifacts.find(ScriptReference.class);
    if (!scripts.isEmpty()) {
      String list = "";
      for (ScriptReference script : scripts) {
        list += (script.getSrc() + "\n");
      }
      boolean failIfScriptTags = true;
      for (ConfigurationProperty prop : context.getConfigurationProperties()) {
        if (prop.getName().equalsIgnoreCase(FAIL_IF_SCRIPT_TAG_PROPERTY)) {
          if (prop.getValues().get(0).equalsIgnoreCase("false")) {
            failIfScriptTags = false;
          }
        }
      }
      if (failIfScriptTags) {
        // CHECKSTYLE_OFF
        String msg =
            "The " + getDescription()
                + " linker does not support <script> tags in the gwt.xml files, but the"
                + " gwt.xml file (or the gwt.xml files which it includes) contains the"
                + " following script tags: \n" + list
                + "In order for your application to run correctly, you will need to"
                + " include these tags in your host page directly. In order to avoid"
                + " this error, you will need to remove the script tags from the"
                + " gwt.xml file, or add this property to the gwt.xml file:"
                + " <set-configuration-property name='xsiframe.failIfScriptTag' value='FALSE'/>";
        // CHECKSTYLE_ON
        logger.log(TreeLogger.ERROR, msg);
        throw new UnableToCompleteException();
      } else {
        if (logger.isLoggable(TreeLogger.INFO)) {
          logger.log(TreeLogger.INFO, "Ignoring the following script tags in the gwt.xml "
              + "file\n" + list);
        }
      }
    }

    ss = ResourceInjectionUtil.injectStylesheets(ss, artifacts);
    ss = permutationsUtil.addPermutationsJs(ss, logger, context);

    if (result != null) {
      replaceAll(ss, "__KNOWN_PROPERTIES__", PropertiesUtil.addKnownPropertiesJs(logger, result));
    }
    replaceAll(ss, "__MODULE_FUNC__", context.getModuleFunctionName());
    replaceAll(ss, "__MODULE_NAME__", context.getModuleName());
    replaceAll(ss, "__HOSTED_FILENAME__", getHostedFilenameFull(context));

    if (context.isOutputCompact()) {
      replaceAll(ss, "__START_OBFUSCATED_ONLY__", "");
      replaceAll(ss, "__END_OBFUSCATED_ONLY__", "");
    } else {
      replaceAll(ss, "__START_OBFUSCATED_ONLY__", "/*");
      replaceAll(ss, "__END_OBFUSCATED_ONLY__", "*/");
    }

    String jsModuleFunctionErrorCatch = getJsModuleFunctionErrorCatch(context);
    if (jsModuleFunctionErrorCatch != null) {
      replaceAll(ss, "__BEGIN_TRY_BLOCK__", "try {");
      replaceAll(ss, "__END_TRY_BLOCK_AND_START_CATCH__", "} catch (moduleError) {");
      includeJs(ss, logger, jsModuleFunctionErrorCatch, "__MODULE_FUNC_ERROR_CATCH__");
      replaceAll(ss, "__END_CATCH_BLOCK__", "}");
    } else {
      replaceAll(ss, "__BEGIN_TRY_BLOCK__", "");
      replaceAll(ss, "__END_TRY_BLOCK_AND_START_CATCH__", "");
      replaceAll(ss, "__MODULE_FUNC_ERROR_CATCH__", "");
      replaceAll(ss, "__END_CATCH_BLOCK__", "");
    }

    return ss.toString();
  }

  protected boolean getBooleanConfigurationProperty(LinkerContext context,
      String name, boolean def) {
    String value = getStringConfigurationProperty(context, name, null);
    if (value != null) {
      if (value.equalsIgnoreCase("true")) {
        return true;
      } else if (value.equalsIgnoreCase("false")) {
        return false;
      }
    }
    return def;
  }

  @Override
  protected String getCompilationExtension(TreeLogger logger, LinkerContext context) {
    return ".cache.js";
  }

  @Override
  protected String getDeferredFragmentSuffix2(TreeLogger logger, LinkerContext context,
      int fragment, String strongName) {

    DefaultTextOutput out = new DefaultTextOutput(context.isOutputCompact());
    writeMagicComments(out, context, fragment, strongName);
    return out.toString();
  }

  @Override
  protected String getHostedFilename() {
    return "devmode.js";
  }

  protected String getHostedFilenameFull(LinkerContext context) {
    return context.getModuleName() + "." + getHostedFilename();
  }

  /**
   * Returns the name of the {@code ComputeScriptBase} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/computeScriptBase.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsComputeScriptBase(LinkerContext context) {
    return getStringConfigurationProperty(context, "computeScriptBaseJs",
        "com/google/gwt/core/ext/linker/impl/computeScriptBase.js");
  }

  /**
   * Returns the name of the {@code UrlForResource} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/computeUrlForResource.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsComputeUrlForResource(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/computeUrlForResource.js";
  }

  /**
   * Returns a JavaScript fragment that starts Super Dev Mode, if enabled.
   * (May return either the JavaScript itself or the name of a Java resource ending with ".js".)
   */
  protected String getJsDevModeRedirectHook(LinkerContext context) {
    if (shouldUseSelfForWindowAndDocument(context)) {
      // Probably a Web Worker. Super Dev Mode isn't supported.
      return "";
    }

    // Enable Super Dev Mode for this app if the devModeRedirectEnabled config property is true.
    if (getBooleanConfigurationProperty(context, "devModeRedirectEnabled", true)) {
      return "com/google/gwt/core/linker/DevModeRedirectHook.js";
    } else {
      return "";
    }
  }

  /**
   * Returns a JavaScript fragment that validates "devModeUrl"&mdash;the URL that Super Dev Mode's
   * JavaScript is loaded from&mdash;before it's used.  The variable may be modified to change what
   * what URL is loaded, or it maybe be set to "" to disable completely.
   * (May return either the JavaScript itself or the name of a Java resource ending with ".js".)
   */
  protected String getJsDevModeUrlValidation(LinkerContext context) {
    // As a default, if the user provides devModeUrlWhitelistRegexp, then we verify that it
    // matches devModeUrl.
    String regexp = getStringConfigurationProperty(context, "devModeUrlWhitelistRegexp",
        "http://(localhost|127\\.0\\.0\\.1)(:\\d+)?/.*");
    if (!regexp.isEmpty()) {
      return ""
          + "if (!/^" + regexp.replace("/", "\\/") + "$/.test(devModeUrl)) {\n"
          + "  if (window.console && console.log) {\n"
          + "    console.log('Ignoring non-whitelisted Dev Mode URL: ' + devModeUrl);\n"
          + "  }\n"
          + "  devModeUrl = '';"
          + "}";
    }
    return "";
  }

  /**
   * Returns a JavaScript expression that determines whether Super Dev Mode may be turned on
   * for the current page. (May return either the JavaScript itself or the name of a Java resource
   * ending with ".js".)
   *
   * <p>The default implementation allows Super Dev Mode only on http: and file: pages. It could be
   * overridden to implement a blacklist or whitelist of hostnames where Super Dev Mode may run.
   * As a safety precaution, it's recommended to return false for https and for the hostnames in
   * URL's visited by end users.
   *
   * <p>If you override this method to allow https, it probably won't work anyway because
   * browsers often disallow loading JavaScript from http URL's into https pages. To make it work,
   * you will also have to find a way to run the code server using https.
   */
  protected String getJsDevModeRedirectHookPermitted(LinkerContext context) {
    return "$wnd.location.protocol == \"http:\" || $wnd.location.protocol == \"file:\"";
  }

  /**
   * Returns the name of the {@code JsInstallLocation} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/installLocationIframe.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsInstallLocation(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/installLocationIframe.js";
  }

  /**
   * Returns the name of the {@code JsInstallScript} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js"}.
   *
   * <p> If you override this to return {@code installScriptDirect.js}, then you
   * should also override {@link #shouldInstallCode(LinkerContext)} to return
   * {@code false}.
   *
   * @param context a LinkerContext
   */
  protected String getJsInstallScript(LinkerContext context) {
    return getStringConfigurationProperty(context, "installScriptJs",
        "com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js");
  }

  /**
   * Returns the name of the {@code JsIsBodyLoaded} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/isBodyLoaded.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsIsBodyLoaded(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/isBodyLoaded.js";
  }

  /**
   * Returns the name of the {@code JsLoadExternalStylesheets} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/loadExternalStylesheets.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsLoadExternalStylesheets(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/loadExternalStylesheets.js";
  }

  /**
   * Returns the name of the {@code JsModuleFunctionErrorCatch} script. By default returns null.
   * This script executes if there's an error loading the module function or executing it.
   * The error will be available under a local variable named "moduleError". If non-null, the
   * module function and the call to the module function will be placed in a try/catch block.
   *
   * @param context a LinkerContext
   */
  protected String getJsModuleFunctionErrorCatch(LinkerContext context) {
    return null;
  }

  /**
   * Returns the name of the {@code JsPermutations} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/permutations.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsPermutations(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/permutations.js";
  }

  /**
   * Returns the name of the {@code JsProcessMetas} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/processMetas.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsProcessMetas(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/processMetas.js";
  }

  /**
   * Returns the name of the {@code JsProperties} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/properties.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsProperties(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/properties.js";
  }

  /**
   * Returns the name of the {@code JsRunAsync} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/runAsync.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsRunAsync(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/runAsync.js";
  }

  /**
   * Returns the name of the {@code JsWaitForBodyLoaded} script.  By default,
   * returns {@code "com/google/gwt/core/ext/linker/impl/waitForBodyLoaded.js"}.
   *
   * @param context a LinkerContext
   */
  protected String getJsWaitForBodyLoaded(LinkerContext context) {
    return "com/google/gwt/core/ext/linker/impl/waitForBodyLoaded.js";
  }

  @Override
  protected String getModulePrefix(TreeLogger logger, LinkerContext context, String strongName)
    throws UnableToCompleteException {
    TextOutput out = new DefaultTextOutput(context.isOutputCompact());

    // $wnd is the main window that the GWT code will affect and also the
    // location where the bootstrap function was defined. In iframe-based linkers,
    // $wnd is set to window.parent. Usually, in others, $wnd = window.
    // By default, $wnd is not set when the module starts, but a replacement for
    // installLocationIframe.js may set it.

    out.print("var $wnd = $wnd || window.parent;");
    out.newlineOpt();
    out.print("var __gwtModuleFunction = $wnd." + context.getModuleFunctionName() + ";");
    out.newlineOpt();
    out.print("var $sendStats = __gwtModuleFunction.__sendStats;");
    out.newlineOpt();
    out.print("$sendStats('moduleStartup', 'moduleEvalStart');");
    out.newlineOpt();
    out.print("var $gwt_version = \"" + About.getGwtVersionNum() + "\";");
    out.newlineOpt();
    out.print("var $strongName = '" + strongName + "';");
    out.newlineOpt();
    out.print("var $doc = $wnd.document;");

    // The functions for runAsync are set up in the bootstrap script so they
    // can be overriden in the same way as other bootstrap code is, however
    // they will be called from, and expected to run in the scope of the GWT code
    // (usually an iframe) so, here we set up those pointers.
    out.print("function __gwtStartLoadingFragment(frag) {");
    out.newlineOpt();
    String fragDir = getFragmentSubdir(logger, context) + '/';
    out.print("var fragFile = '" + fragDir + "' + $strongName + '/' + frag + '" + FRAGMENT_EXTENSION + "';");
    out.newlineOpt();
    out.print("return __gwtModuleFunction.__startLoadingFragment(fragFile);");
    out.newlineOpt();
    out.print("}");
    out.newlineOpt();
    out.print("function __gwtInstallCode(code) {return __gwtModuleFunction.__installRunAsyncCode(code);}");
    out.newlineOpt();

    // Even though we call the $sendStats function in the code written in this
    // linker, some of the compilation code still needs the $stats and
    // $sessionId
    // variables to be available.
    out.print("var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null;");
    out.newlineOpt();
    out.print("var $sessionId = $wnd.__gwtStatsSessionId ? $wnd.__gwtStatsSessionId : null;");
    out.newlineOpt();

    return out.toString();
  }

  @Override
  protected String getModuleSuffix2(TreeLogger logger, LinkerContext context,
      String strongName) {

    // Note: this method won't be called if getModuleSuffix() is overridden and returns non-null.

    DefaultTextOutput out = new DefaultTextOutput(context.isOutputCompact());

    out.print("$sendStats('moduleStartup', 'moduleEvalEnd');");
    out.newlineOpt();
    out.print("gwtOnLoad(" + "__gwtModuleFunction.__errFn, " + "__gwtModuleFunction.__moduleName, "
        + "__gwtModuleFunction.__moduleBase, " + "__gwtModuleFunction.__softPermutationId,"
        + "__gwtModuleFunction.__computePropValue);");
    out.newlineOpt();
    out.print("$sendStats('moduleStartup', 'end');");

    writeMagicComments(out, context, 0, strongName);
    return out.toString();
  }

  @Override
  protected String getScriptChunkSeparator(TreeLogger logger, LinkerContext context) {
    return shouldInstallCode(context) ? "__SCRIPT_CHUNK_SEPARATOR_MARKER__" : "";
  }

  @Override
  protected String getSelectionScriptTemplate(TreeLogger logger, LinkerContext context) {
    return "com/google/gwt/core/linker/CrossSiteIframeTemplate.js";
  }

  /**
   * Returns the sourcemap URL that will be put in the comment at the end of a JavaScript
   * fragment, or null if the comment should be omitted. The default implementation uses
   * the includeSourceMapUrl config property.
   */
  protected String getSourceMapUrl(LinkerContext context, String strongName, int fragmentId) {
    String val = getStringConfigurationProperty(context, "includeSourceMapUrl",  "false");

    if ("false".equalsIgnoreCase(val)) {
      return null;
    }

    if ("true".equalsIgnoreCase(val)) {
      return SymbolMapsLinker.SourceMapArtifact.sourceMapFilenameForFragment(fragmentId);
    }

    return val.replaceAll("__HASH__", strongName)
        .replaceAll("__FRAGMENT__", String.valueOf(fragmentId))
        .replaceAll("__MODULE__", context.getModuleName());
  }

  protected String getStringConfigurationProperty(LinkerContext context,
      String name, String def) {
    for (ConfigurationProperty property : context.getConfigurationProperties()) {
      if (property.getName().equals(name) && property.getValues().size() > 0) {
        if (property.getValues().get(0) != null) {
          return property.getValues().get(0);
        }
      }
    }
    return def;
  }

  protected void includeJs(StringBuffer selectionScript, TreeLogger logger, String jsSource,
      String templateVar) throws UnableToCompleteException {
    String js;
    if (jsSource.endsWith(".js")) {
      try {
        js = Utility.getFileFromClassPath(jsSource);
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to read file: " + jsSource, e);
        throw new UnableToCompleteException();
      }
    } else {
      js = jsSource;
    }
    replaceAll(selectionScript, templateVar, js);
  }

  @Override
  protected void maybeAddHostedModeFile(TreeLogger logger, LinkerContext context,
      ArtifactSet artifacts, CompilationResult result) throws UnableToCompleteException {
    String filename = getHostedFilename();
    if ("".equals(filename)) {
      return;
    }

    // when we're including bootstrap in the primary fragment, we should be
    // generating devmode files for each permutation. Otherwise, we generate it
    // only in the final link stage.
    boolean isSinglePermutation = (result != null);
    if (isSinglePermutation != shouldIncludeBootstrapInPrimaryFragment(context)) {
      return;
    }

    long lastModified = System.currentTimeMillis();
    StringBuffer buffer =
        readFileToStringBuffer("com/google/gwt/core/ext/linker/impl/" + filename, logger);

    String outputFilename = filename;
    if (result != null) {
      // If we're including bootstrap in the primary fragment, we generate a
      // devmode.js for each permutation, and it's name is XXX.devmode.js,
      // where XXX is the md5 hash for this permutation
      outputFilename = result.getStrongName() + "." + outputFilename;
    } else {
      // If we're not including bootstrap in the primary fragment, we generate
      // a devmode.js for this module and it's name is XXX.devmode.js, where
      // XXX is the module name.
      outputFilename = getHostedFilenameFull(context);
    }

    replaceAll(buffer, "__MODULE_NAME__", context.getModuleName());
    String script =
        generatePrimaryFragmentString(logger, context, result, buffer.toString(), 1, artifacts);

    EmittedArtifact devArtifact = emitString(logger, script, outputFilename, lastModified);
    artifacts.add(devArtifact);
  }

  // Output compilation-mappings.txt
  @Override
  protected void maybeOutputPropertyMap(TreeLogger logger, LinkerContext context,
      ArtifactSet toReturn) {
    if (permutationsUtil.getPermutationsMap() == null
        || permutationsUtil.getPermutationsMap().isEmpty()) {
      return;
    }

    PropertiesMappingArtifact mappingArtifact =
        new PropertiesMappingArtifact(CrossSiteIframeLinker.class, permutationsUtil
            .getPermutationsMap());

    toReturn.add(mappingArtifact);
    EmittedArtifact serializedMap;
    try {
      String mappings = mappingArtifact.getSerialized();
      // CHECKSTYLE_OFF
      mappings = mappings.concat("Devmode:" + getHostedFilename());
      // CHECKSTYLE_ON
      serializedMap = emitString(logger, mappings, "compilation-mappings.txt");
      // TODO(unnurg): make this Deploy
      serializedMap.setVisibility(Visibility.Public);
      toReturn.add(serializedMap);
    } catch (UnableToCompleteException e) {
      e.printStackTrace();
    }
  }

  // If you set this to return true, you should also override
  // getJsPermutations() to return permutationsNull.js and
  // getJsInstallScript() to return installScriptAlreadyIncluded.js
  protected boolean shouldIncludeBootstrapInPrimaryFragment(LinkerContext context) {
    return false;
  }

  protected boolean shouldInstallCode(LinkerContext context) {
    return getBooleanConfigurationProperty(context, "installCode", true);
  }

  /**
   * Returns whether to use "self" for $wnd and $doc references. Defaults to false.
   * Useful for worker threads.
   */
  protected boolean shouldUseSelfForWindowAndDocument(LinkerContext context) {
    return false;
  }

  @Override
  protected String wrapDeferredFragment(TreeLogger logger,
      LinkerContext context, int fragment, String js, ArtifactSet artifacts) {
    // TODO(unnurg): This assumes that the xsiframe linker is using the
    // ScriptTagLoadingStrategy (since it is also xs compatible).  However,
    // it should be completely valid to use the XhrLoadingStrategy with this
    // linker, in which case we would not want to wrap the deferred fragment
    // in this way.  Ideally, we should make a way for this code to be dependent
    // on what strategy is being used. Otherwise, we should make a property which
    // users can set to turn this wrapping off if they override the loading strategy.
    return String.format("$wnd.%s.runAsyncCallback%d(%s)\n",
        context.getModuleFunctionName(),
        fragment,
        StringUtils.javaScriptString(js));
  }

  @Override
  protected String wrapPrimaryFragment(TreeLogger logger, LinkerContext context, String script,
      ArtifactSet artifacts, CompilationResult result) throws UnableToCompleteException {

    StringBuilder out = new StringBuilder();

    if (shouldIncludeBootstrapInPrimaryFragment(context)) {
      out.append(generateSelectionScript(logger, context, artifacts, result));
      // only needed in SSSS, breaks WebWorker linker if done all the time
      out.append("if (" + context.getModuleFunctionName() + ".succeeded) {\n");
    }


    if (shouldInstallCode(context)) {
      // Rewrite the code so it can be installed with
      // __MODULE_FUNC__.onScriptDownloaded
      out.append(context.getModuleFunctionName());
      out.append(".onScriptDownloaded([");
      Iterable<String> chunks = Splitter.on(getScriptChunkSeparator(logger, context)).split(script);
      List<String> newChunks = new ArrayList<String>();
      for (String chunk : chunks) {
        newChunks.add(StringUtils.javaScriptString(chunk));
      }
      out.append(Joiner.on(",\n").join(newChunks));
      out.append("]);\n");
    } else {
      out.append(script);
      out.append("\n");
    }
    if (shouldIncludeBootstrapInPrimaryFragment(context)) {
      out.append("}\n");
    }
    return out.toString();
  }

  private void writeMagicComments(DefaultTextOutput out, LinkerContext context, int fragmentId,
      String strongName) {
    String sourceMapUrl = getSourceMapUrl(context, strongName, fragmentId);
    if (sourceMapUrl != null) {
      // This magic comment determines where a browser debugger looks for a sourcemap,
      // except that it may be overridden by a "SourceMap" header in the HTTP response when
      // loading the JavaScript.
      // (Note: even if you're using the HTTP header, you still have to set this to an arbitrary
      // value, or Chrome won't enable sourcemaps.)
      out.print("\n//# sourceMappingURL=" + sourceMapUrl + " ");
    }

    // This magic comment determines the name of the JavaScript fragment in a browser debugger.
    // (In Chrome it typically shows up under "(no domain)".)
    // We need to set it explicitly because the JavaScript code may be installed via an "eval"
    // statement and even if we're not using an eval, the filename contains the strongname which
    // isn't stable across recompiles.
    out.print("\n//# sourceURL=" + context.getModuleName() + "-" + fragmentId + ".js\n");
  }
}
