View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit;
16  
17  import org.apache.commons.logging.Log;
18  import org.apache.commons.logging.LogFactory;
19  import org.htmlunit.html.HtmlPage;
20  import org.htmlunit.util.UrlUtils;
21  
22  /**
23   * A window representing a top level browser window.
24   *
25   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
26   * @author David K. Taylor
27   * @author David D. Kilzer
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   * @author Sven Strickroth
31   */
32  public class TopLevelWindow extends WebWindowImpl {
33  
34      /** Logging support. */
35      private static final Log LOG = LogFactory.getLog(TopLevelWindow.class);
36  
37      /** The window which caused this window to be opened, if any. */
38      private WebWindow opener_;
39  
40      /**
41       * Creates an instance.
42       * @param name the name of the new window
43       * @param webClient the web client that "owns" this window
44       */
45      protected TopLevelWindow(final String name, final WebClient webClient) {
46          super(webClient);
47          WebAssert.notNull("name", name);
48          setName(name);
49          performRegistration();
50      }
51  
52      /**
53       * {@inheritDoc}
54       * Since this is a top level window, return this window.
55       */
56      @Override
57      public WebWindow getParentWindow() {
58          return this;
59      }
60  
61      /**
62       * {@inheritDoc}
63       * Since this is a top level window, return this window.
64       */
65      @Override
66      public WebWindow getTopWindow() {
67          return this;
68      }
69  
70      /**
71       * {@inheritDoc}
72       */
73      @Override
74      protected boolean isJavaScriptInitializationNeeded(final Page page) {
75          return getScriptableObject() == null
76              || page.getUrl() == UrlUtils.URL_ABOUT_BLANK
77              || !(page.getWebResponse() instanceof StringWebResponse);
78          // TODO: find a better way to distinguish content written by document.open(),...
79      }
80  
81      /**
82       * Returns a string representation of this object.
83       * @return a string representation of this object
84       */
85      @Override
86      public String toString() {
87          return "TopLevelWindow[name=\"" + getName() + "\"]";
88      }
89  
90      /**
91       * Sets the opener property. This is the WebWindow that caused this new window to be opened.
92       * @param opener the new opener
93       */
94      public void setOpener(final WebWindow opener) {
95          opener_ = opener;
96      }
97  
98      /**
99       * Returns the opener property. This is the WebWindow that caused this new window to be opened.
100      * @return the opener
101      */
102     public WebWindow getOpener() {
103         return opener_;
104     }
105 
106     /**
107      * Closes this window.
108      */
109     public void close() {
110         close(false);
111     }
112 
113     /**
114      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
115      *
116      * Closes this window.
117      * @param ignoreOnbeforeunloadAccepted if true the result of triggering the OnbeforeunloadAccepted event
118      *        will be ignored
119      */
120     public void close(final boolean ignoreOnbeforeunloadAccepted) {
121         final Page page = getEnclosedPage();
122 
123         // a bit strange code but we like to make sure that all steps are processed
124         // also if one throws
125         boolean rejected = false;
126         try {
127             if (page != null && page.isHtmlPage()) {
128                 final HtmlPage htmlPage = (HtmlPage) page;
129                 final boolean accepted = ignoreOnbeforeunloadAccepted || htmlPage.isOnbeforeunloadAccepted();
130                 if (!accepted) {
131                     LOG.debug("The registered OnbeforeunloadHandler rejected the window close event.");
132                     rejected = true;
133                 }
134             }
135         }
136         finally {
137             if (!rejected) {
138                 try {
139                     setClosed();
140                 }
141                 finally {
142                     if (page != null) {
143                         page.cleanUp();
144                     }
145 
146                     try {
147                         getJobManager().shutdown();
148                     }
149                     finally {
150                         try {
151                             destroyChildren();
152                         }
153                         finally {
154                             getWebClient().deregisterWebWindow(this);
155                         }
156                     }
157                 }
158             }
159         }
160     }
161 }