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 Mike Bowler
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 }