001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.html.pages;
018
019import org.apache.wicket.markup.head.IHeaderResponse;
020import org.apache.wicket.markup.head.MetaDataHeaderItem;
021import org.apache.wicket.markup.head.OnLoadHeaderItem;
022import org.apache.wicket.markup.html.WebPage;
023import org.apache.wicket.markup.html.link.Link;
024import org.apache.wicket.model.IModel;
025import org.apache.wicket.model.LoadableDetachableModel;
026import org.apache.wicket.protocol.http.ClientProperties;
027import org.apache.wicket.protocol.http.WebSession;
028import org.apache.wicket.protocol.http.request.WebClientInfo;
029import org.apache.wicket.request.cycle.RequestCycle;
030
031/**
032 * This page uses a form post right after the page has loaded in the browser, using JavaScript or
033 * alternative means to detect and pass on settings to the embedded form. The form submit method
034 * updates this session's {@link org.apache.wicket.core.request.ClientInfo} object and then redirects to
035 * the original location as was passed in as a URL argument in the constructor.
036 * <p>
037 * If JavaScript is not enabled in the browser, a "refresh" meta-header will initiate a get on this page to
038 * continue with the original destination. As a fallback the user can click a link to do the same. 
039 * <p>
040 * This page is being used by the default implementation of {@link org.apache.wicket.Session#getClientInfo()},
041 * which in turn uses
042 * {@link org.apache.wicket.settings.RequestCycleSettings#getGatherExtendedBrowserInfo() a setting} to
043 * determine whether this page should be redirected to (it does when it is true).
044 * 
045 * @author Eelco Hillenius
046 */
047public class BrowserInfoPage extends WebPage
048{
049        private static final long serialVersionUID = 1L;
050
051        private BrowserInfoForm browserInfoForm;
052        
053        /**
054         * Bookmarkable constructor.
055         */
056        public BrowserInfoPage()
057        {
058                initComps();
059        }
060
061        @Override
062        public void renderHead(IHeaderResponse response)
063        {
064                super.renderHead(response);
065
066                response.render(OnLoadHeaderItem.forScript(
067                                String.format("Wicket.BrowserInfo.submitForm('%s')", browserInfoForm.getFormMarkupId())));
068        }
069
070        @Override
071        public boolean isVersioned()
072        {
073                return false;
074        }
075
076        protected WebClientInfo newWebClientInfo(RequestCycle requestCycle)
077        {
078                return new WebClientInfo(requestCycle);
079        }
080
081        /**
082         * Adds components.
083         */
084        private void initComps()
085        {
086                IModel<WebClientInfo> info = new LoadableDetachableModel<WebClientInfo>() {
087                        @Override
088                        protected WebClientInfo load()
089                        {
090                                return newWebClientInfo(getRequestCycle());
091                        }                       
092                };
093
094                IModel<ClientProperties> properties = new LoadableDetachableModel<ClientProperties>()
095                {
096                        @Override
097                        protected ClientProperties load()
098                        {
099                                return info.getObject().getProperties();
100                        }
101                };
102
103                add(new ContinueLink("link", info));
104
105                browserInfoForm = new BrowserInfoForm("postback", properties)
106                {
107                        private static final long serialVersionUID = 1L;
108
109                        @Override
110                        protected void afterSubmit()
111                        {
112                                getModelObject().setJavaScriptEnabled(true);
113
114                                WebSession.get().setClientInfo(info.getObject());
115
116                                continueToOriginalDestination();
117
118                                // switch to home page if no original destination was intercepted
119                                setResponsePage(getApplication().getHomePage());
120                        }
121                };
122                add(browserInfoForm);
123        }
124        
125        protected ClientProperties newClientInfo()
126        {
127                return WebSession.get().getClientInfo().getProperties();
128        }
129
130        private static class ContinueLink extends Link<WebClientInfo> {
131
132                public ContinueLink(String id, IModel<WebClientInfo> info)
133                {
134                        super(id, info);
135                }
136
137                @Override
138                public void renderHead(IHeaderResponse response)
139                {
140                        String content = "0; url=" + getURL();
141
142                        response.render(MetaDataHeaderItem.forHttpEquiv("refresh", content));
143                }
144                
145                @Override
146                public void onClick()
147                {
148                        getModelObject().getProperties().setJavaScriptEnabled(false);
149
150                        WebSession.get().setClientInfo(getModelObject());
151
152                        continueToOriginalDestination();
153
154                        // switch to home page if no original destination was intercepted
155                        setResponsePage(getApplication().getHomePage());
156                }
157        };
158}