Beispiel #1
0
        /// <summary>
        /// Attempts to extract the "current" view for the given gadget.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="spec"></param>
        /// <returns></returns>
        private View GetView(GadgetContext context, GadgetSpec spec)
        {
            String viewName = context.getView();
            View   view     = spec.getView(viewName);

            if (view == null)
            {
                JsonObject views = containerConfig.GetJsonObject(context.getContainer(), "gadgets.features/views");
                foreach (DictionaryEntry v in views)
                {
                    JsonArray aliases = ((JsonObject)v.Value)["aliases"] as JsonArray;
                    if (aliases != null && view == null)
                    {
                        for (int i = 0, j = aliases.Length; i < j; ++i)
                        {
                            if (viewName == aliases.GetString(i))
                            {
                                view = spec.getView(v.Key.ToString());
                                if (view != null)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (view == null)
            {
                view = spec.getView(GadgetSpec.DEFAULT_VIEW);
            }

            return(view);
        }
Beispiel #2
0
        /**
         * Validates that the parent parameter was acceptable.
         *
         * @return True if the parent parameter is valid for the current container.
         */
        private bool ValidateParent(GadgetContext context)
        {
            String container = context.getContainer();
            String parent    = context.getParameter("parent");

            if (parent == null)
            {
                // If there is no parent parameter, we are still safe because no
                // dependent code ever has to trust it anyway.
                return(true);
            }

            try
            {
                JsonArray parents = containerConfig.GetJsonArray(container, "gadgets.parent");
                if (parents == null)
                {
                    return(true);
                }
                // We need to check each possible parent parameter against this regex.
                for (int i = 0, j = parents.Length; i < j; ++i)
                {
                    if (Regex.IsMatch(parents[i].ToString(), parent))
                    {
                        return(true);
                    }
                }
            }
            catch (JsonException)
            {
            }
            return(false);
        }
Beispiel #3
0
        /**
         * Render the gadget into a string by performing the following steps:
         *
         * - Retrieve gadget specification information (GadgetSpec, MessageBundle, etc.)
         *
         * - Fetch any preloaded data needed to handle the request, as handled by Preloader.
         *
         * - Perform rewriting operations on the output content, handled by Rewriter.
         *
         * @param gadget The gadget for the rendering operation.
         * @return The rendered gadget content
         * @throws RenderingException if any issues arise that prevent rendering.
         */
        public String render(Gadget gadget)
        {
            try
            {
                View          view    = gadget.getCurrentView();
                GadgetContext context = gadget.getContext();
                GadgetSpec    spec    = gadget.getSpec();

                IPreloads preloads = preloader.preload(context, spec,
                                                       PreloaderService.PreloadPhase.HTML_RENDER);
                gadget.setPreloads(preloads);
                String content;

                if (view.getHref() == null)
                {
                    content = view.getContent();
                }
                else
                {
                    // TODO: Add current url to GadgetContext to support transitive proxying.
                    UriBuilder uri = new UriBuilder(view.getHref());
                    uri.addQueryParameter("lang", context.getLocale().getLanguage());
                    uri.addQueryParameter("country", context.getLocale().getCountry());

                    sRequest request = new sRequest(uri.toUri())
                                       .setIgnoreCache(context.getIgnoreCache())
                                       .setOAuthArguments(new OAuthArguments(view))
                                       .setAuthType(view.getAuthType())
                                       .setSecurityToken(context.getToken())
                                       .setContainer(context.getContainer())
                                       .setGadget(spec.getUrl());
                    sResponse response = DefaultHttpCache.Instance.getResponse(request);

                    if (response == null || response.isStale())
                    {
                        sRequest proxyRequest = createPipelinedProxyRequest(gadget, request);
                        response = requestPipeline.execute(proxyRequest);
                        DefaultHttpCache.Instance.addResponse(request, response);
                    }

                    if (response.isError())
                    {
                        throw new RenderingException("Unable to reach remote host. HTTP status " +
                                                     response.getHttpStatusCode());
                    }
                    content = response.responseString;
                }

                return(rewriter.rewriteGadget(gadget, content));
            }
            catch (GadgetException e)
            {
                throw new RenderingException(e.Message, e);
            }
        }
Beispiel #4
0
        /**
         * Creates a set of all configuration needed to satisfy the requested feature set.
         *
         * Appends special configuration for gadgets.util.hasFeature and gadgets.util.getFeatureParams to
         * the output js.
         *
         * This can't be handled via the normal configuration mechanism because it is something that
         * varies per request.
         *
         * @param reqs The features needed to satisfy the request.
         * @throws GadgetException If there is a problem with the gadget auth token
         */
        private String GetLibraryConfig(Gadget gadget, ICollection <GadgetFeature> reqs)

        {
            GadgetContext context = gadget.getContext();

            JsonObject features = containerConfig.GetJsonObject(context.getContainer(), FEATURES_KEY);

            Dictionary <String, Object> config = new Dictionary <string, object>(features == null ? 2 : features.Names.Count + 2);

            if (features != null)
            {
                // Discard what we don't care about.
                foreach (GadgetFeature feature in reqs)
                {
                    String name = feature.getName();
                    Object conf = features.Opt(name);
                    if (conf != null)
                    {
                        config.Add(name, conf);
                    }
                }
            }

            // Add gadgets.util support. This is calculated dynamically based on request inputs.
            ModulePrefs prefs  = gadget.getSpec().getModulePrefs();
            var         values = prefs.getFeatures().Values;
            Dictionary <String, Dictionary <String, String> > featureMap =
                new Dictionary <string, Dictionary <string, string> >(values.Count);

            foreach (Feature feature in values)
            {
                featureMap.Add(feature.getName(), feature.getParams());
            }
            config.Add("core.util", featureMap);

            // Add authentication token config
            ISecurityToken authToken = context.getToken();

            if (authToken != null)
            {
                Dictionary <String, String> authConfig = new Dictionary <String, String>(2);
                String updatedToken = authToken.getUpdatedToken();
                if (updatedToken != null)
                {
                    authConfig.Add("authToken", updatedToken);
                }
                String trustedJson = authToken.getTrustedJson();
                if (trustedJson != null)
                {
                    authConfig.Add("trustedJson", trustedJson);
                }
                config.Add("shindig.auth", authConfig);
            }
            return("gadgets.config.init(" + JsonConvert.ExportToString(config) + ");\n");
        }
Beispiel #5
0
 public static sRequest newHttpRequest(GadgetContext context,
             RequestAuthenticationInfo authenticationInfo)
 {
     sRequest request = new sRequest(authenticationInfo.getHref())
         .setSecurityToken(context.getToken())
         .setOAuthArguments(new OAuthArguments(authenticationInfo))
         .setAuthType(authenticationInfo.getAuthType())
         .setContainer(context.getContainer())
         .setGadget(Uri.fromJavaUri(context.getUrl()));
     return request;
 }
Beispiel #6
0
        public static sRequest newHttpRequest(GadgetContext context,
                                              RequestAuthenticationInfo authenticationInfo)
        {
            sRequest request = new sRequest(authenticationInfo.getHref())
                               .setSecurityToken(context.getToken())
                               .setOAuthArguments(new OAuthArguments(authenticationInfo))
                               .setAuthType(authenticationInfo.getAuthType())
                               .setContainer(context.getContainer())
                               .setGadget(Uri.fromJavaUri(context.getUrl()));

            return(request);
        }
Beispiel #7
0
        /**
        * Attempts to render the requested gadget.
        *
        * @return The results of the rendering attempt.
        *
        * TODO: Localize error messages.
        */
        public RenderingResults Render(GadgetContext context) 
        {
            if (!ValidateParent(context)) 
            {
                return RenderingResults.error("Unsupported parent parameter. Check your container code.");
            }

            try 
            {
                Gadget gadget = processor.Process(context);

                if (gadget.getCurrentView() == null)
                {
                    return RenderingResults.error("Unable to locate an appropriate view in this gadget. " +
                                                  "Requested: '" + gadget.getContext().getView() +
                                                  "' Available: " + String.Join(",",gadget.getSpec().getViews().Keys.ToArray()));
                }

                if (gadget.getCurrentView().getType() == View.ContentType.URL)
                {
                    return RenderingResults.mustRedirect(getRedirect(gadget));
                }

                GadgetSpec spec = gadget.getSpec();
                if (!lockedDomainService.gadgetCanRender(context.getHost(), spec, context.getContainer()))
                {
                    return RenderingResults.mustRedirect(getRedirect(gadget));
                }
                return RenderingResults.ok(renderer.render(gadget));
            }
            catch (RenderingException e) 
            {
                return LogError(context.getUrl(), e);
            } 
            catch (ProcessingException e) 
            {
                return LogError(context.getUrl(), e);
            } 
            catch (Exception e) 
            {
                if (e.GetBaseException() is GadgetException) 
                {
                    return LogError(context.getUrl(), e.GetBaseException());
                }
                throw;
            }
        }
Beispiel #8
0
        /**
         * Attempts to render the requested gadget.
         *
         * @return The results of the rendering attempt.
         *
         * TODO: Localize error messages.
         */
        public RenderingResults Render(GadgetContext context)
        {
            if (!ValidateParent(context))
            {
                return(RenderingResults.error("Unsupported parent parameter. Check your container code."));
            }

            try
            {
                Gadget gadget = processor.Process(context);

                if (gadget.getCurrentView() == null)
                {
                    return(RenderingResults.error("Unable to locate an appropriate view in this gadget. " +
                                                  "Requested: '" + gadget.getContext().getView() +
                                                  "' Available: " + String.Join(",", gadget.getSpec().getViews().Keys.ToArray())));
                }

                if (gadget.getCurrentView().getType() == View.ContentType.URL)
                {
                    return(RenderingResults.mustRedirect(getRedirect(gadget)));
                }

                GadgetSpec spec = gadget.getSpec();
                if (!lockedDomainService.gadgetCanRender(context.getHost(), spec, context.getContainer()))
                {
                    return(RenderingResults.mustRedirect(getRedirect(gadget)));
                }
                return(RenderingResults.ok(renderer.render(gadget)));
            }
            catch (RenderingException e)
            {
                return(LogError(context.getUrl(), e));
            }
            catch (ProcessingException e)
            {
                return(LogError(context.getUrl(), e));
            }
            catch (Exception e)
            {
                if (e.GetBaseException() is GadgetException)
                {
                    return(LogError(context.getUrl(), e.GetBaseException()));
                }
                throw;
            }
        }
Beispiel #9
0
        private void InjectBaseTag(Gadget gadget, Node headTag)
        {
            GadgetContext context = gadget.getContext();

            if ("true".Equals(containerConfig.Get(context.getContainer(), INSERT_BASE_ELEMENT_KEY)))
            {
                Uri  baseUrl = gadget.getSpec().getUrl();
                View view    = gadget.getCurrentView();
                if (view != null && view.getHref() != null)
                {
                    baseUrl = view.getHref();
                }
                Element baseTag = headTag.getOwnerDocument().createElement("base");
                baseTag.setAttribute("href", baseUrl.ToString());
                headTag.insertBefore(baseTag, headTag.getFirstChild());
            }
        }
Beispiel #10
0
        /**
         * Fetches js configuration for the given feature set & container.
         *
         * @param config The configuration to extract js config from.
         * @param context The request context.
         * @param features A set of all features needed.
         */
        public static JsonObject GetJsConfig(ContainerConfig config, GadgetContext context, HashSet <string> features)
        {
            JsonObject containerFeatures = config.GetJsonObject(context.getContainer(),
                                                                "gadgets.features");
            JsonObject retv = new JsonObject();

            if (containerFeatures != null)
            {
                foreach (string feat in features)
                {
                    if (containerFeatures.Contains(feat))
                    {
                        retv.Put(feat, containerFeatures[feat]);
                    }
                }
            }
            return(retv);
        }
Beispiel #11
0
        /**
        * Validates that the parent parameter was acceptable.
        *
        * @return True if the parent parameter is valid for the current container.
        */
        private bool ValidateParent(GadgetContext context) 
        {
            String container = context.getContainer();
            String parent = context.getParameter("parent");

            if (parent == null) 
            {
                // If there is no parent parameter, we are still safe because no
                // dependent code ever has to trust it anyway.
                return true;
            }

            try
            {
                JsonArray parents = containerConfig.GetJsonArray(container, "gadgets.parent");
                if (parents == null) 
                {
                    return true;
                }
                // We need to check each possible parent parameter against this regex.
                for (int i = 0, j = parents.Length; i < j; ++i) 
                {
                    if (Regex.IsMatch(parents[i].ToString(), parent))
                    {
                        return true;
                    }
                }
            } 
            catch (JsonException) 
            {

            }
            return false;
        }
Beispiel #12
0
        /// <summary>
        /// Attempts to extract the "current" view for the given gadget.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="spec"></param>
        /// <returns></returns>
        private View GetView(GadgetContext context, GadgetSpec spec) 
        {
            String viewName = context.getView();
            View view = spec.getView(viewName);
            if (view == null)
            {
                JsonObject views = containerConfig.GetJsonObject(context.getContainer(), "gadgets.features/views");
                foreach (DictionaryEntry v in views)
                {
                    JsonArray aliases = ((JsonObject)v.Value)["aliases"] as JsonArray;
                    if (aliases != null && view == null)
                    {
                        for (int i = 0, j = aliases.Length; i < j; ++i)
                        {
                            if (viewName == aliases.GetString(i))
                            {
                                view = spec.getView(v.Key.ToString());
                                if (view != null)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }  

            if (view == null) 
            {
                view = spec.getView(GadgetSpec.DEFAULT_VIEW);
            }
            
            return view;
        }
Beispiel #13
0
 /**
 * Fetches js configuration for the given feature set & container.
 *
 * @param config The configuration to extract js config from.
 * @param context The request context.
 * @param features A set of all features needed.
 */
 public static JsonObject GetJsConfig(ContainerConfig config, GadgetContext context, HashSet<string> features)
 {
     JsonObject containerFeatures = config.GetJsonObject(context.getContainer(),
                                                         "gadgets.features");
     JsonObject retv = new JsonObject();
     if (containerFeatures != null)
     {
         foreach (string feat in features)
         {
             if (containerFeatures.Contains(feat))
             {
                 retv.Put(feat, containerFeatures[feat]);
             }
         }
     }
     return retv;
 }
Beispiel #14
0
        /// <summary>
        /// Injects javascript libraries needed to satisfy feature dependencies.
        /// </summary>
        /// <param name="gadget"></param>
        /// <param name="headTag"></param>
        private void InjectFeatureLibraries(Gadget gadget, Node headTag)
        {
            // TODO: If there isn't any js in the document, we can skip this. Unfortunately, that means
            // both script tags (easy to detect) and event handlers (much more complex).
            GadgetContext    context    = gadget.getContext();
            GadgetSpec       spec       = gadget.getSpec();
            String           forcedLibs = context.getParameter("libs");
            HashKey <String> forced;

            if (string.IsNullOrEmpty(forcedLibs))
            {
                forced = new HashKey <string>();
            }
            else
            {
                forced = new HashKey <string>();
                foreach (var item in forcedLibs.Split(':'))
                {
                    forced.Add(item);
                }
            }


            // Forced libs are always done first.
            if (forced.Count != 0)
            {
                String  jsUrl   = urlGenerator.getBundledJsUrl(forced, context);
                Element libsTag = headTag.getOwnerDocument().createElement("script");
                libsTag.setAttribute("src", jsUrl);
                headTag.appendChild(libsTag);

                // Forced transitive deps need to be added as well so that they don't get pulled in twice.
                // TODO: Figure out a clean way to avoid having to call getFeatures twice.
                foreach (GadgetFeature dep in featureRegistry.GetFeatures(forced))
                {
                    forced.Add(dep.getName());
                }
            }

            // Inline any libs that weren't forced. The ugly context switch between inline and external
            // Js is needed to allow both inline and external scripts declared in feature.xml.
            String container = context.getContainer();
            ICollection <GadgetFeature> features = GetFeatures(spec, forced);

            // Precalculate the maximum length in order to avoid excessive garbage generation.
            int size = 0;

            foreach (GadgetFeature feature in features)
            {
                foreach (JsLibrary library in feature.getJsLibraries(RenderingContext.GADGET, container))
                {
                    if (library._Type == JsLibrary.Type.URL)
                    {
                        size += library.Content.Length;
                    }
                }
            }

            // Really inexact.
            StringBuilder inlineJs = new StringBuilder(size);

            foreach (GadgetFeature feature in features)
            {
                foreach (JsLibrary library in feature.getJsLibraries(RenderingContext.GADGET, container))
                {
                    if (library._Type == JsLibrary.Type.URL)
                    {
                        if (inlineJs.Length > 0)
                        {
                            Element inlineTag = headTag.getOwnerDocument().createElement("script");
                            headTag.appendChild(inlineTag);
                            inlineTag.appendChild(headTag.getOwnerDocument().createTextNode(inlineJs.ToString()));
                            inlineJs.Length = 0;
                        }
                        Element referenceTag = headTag.getOwnerDocument().createElement("script");
                        referenceTag.setAttribute("src", library.Content);
                        headTag.appendChild(referenceTag);
                    }
                    else
                    {
                        if (!forced.Contains(feature.getName()))
                        {
                            // already pulled this file in from the shared contents.
                            if (context.getDebug())
                            {
                                inlineJs.Append(library.DebugContent);
                            }
                            else
                            {
                                inlineJs.Append(library.Content);
                            }
                            inlineJs.Append(";\n");
                        }
                    }
                }
            }

            inlineJs.Append(GetLibraryConfig(gadget, features));

            if (inlineJs.Length > 0)
            {
                Element inlineTag = headTag.getOwnerDocument().createElement("script");
                headTag.appendChild(inlineTag);
                inlineTag.appendChild(headTag.getOwnerDocument().createTextNode(inlineJs.ToString()));
            }
        }