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.javascript.background;
16  
17  import java.lang.ref.WeakReference;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.htmlunit.Page;
22  import org.htmlunit.WebWindow;
23  import org.htmlunit.html.HtmlPage;
24  
25  /**
26   * A JavaScript-triggered background job representing the execution of some JavaScript code.
27   *
28   * @author Daniel Gredler
29   * @author Ronald Brill
30   * @author Sven Strickroth
31   */
32  abstract class JavaScriptExecutionJob extends BasicJavaScriptJob {
33  
34      /** Logging support. */
35      private static final Log LOG = LogFactory.getLog(JavaScriptExecutionJob.class);
36  
37      /** The label for this job. */
38      private final String label_;
39  
40      /** The window to which this job belongs (weakly referenced, so as not to leak memory). */
41      private final WeakReference<WebWindow> window_;
42  
43      /**
44       * Creates a new JavaScript execution job, where the JavaScript code to execute is a string.
45       * @param initialDelay the initial amount of time to wait before executing this job
46       * @param period the amount of time to wait between executions of this job (may be {@code null})
47       * @param label the label for the job
48       * @param window the window to which the job belongs
49       */
50      JavaScriptExecutionJob(final int initialDelay, final Integer period, final String label,
51          final WebWindow window) {
52          super(initialDelay, period);
53          label_ = label;
54          window_ = new WeakReference<>(window);
55      }
56  
57      /** {@inheritDoc} */
58      @Override
59      public void run() {
60          final WebWindow w = window_.get();
61          if (w == null) {
62              // The window has been garbage collected! No need to execute, obviously.
63              return;
64          }
65  
66          if (LOG.isDebugEnabled()) {
67              LOG.debug("Executing " + this + ".");
68          }
69  
70          try {
71              // Verify that the window is still open
72              if (w.isClosed()) {
73                  LOG.debug("Enclosing window is now closed. Execution cancelled.");
74                  return;
75              }
76              if (!w.getWebClient().containsWebWindow(w)) {
77                  LOG.debug("Enclosing window is now closed. Execution cancelled.");
78                  return;
79              }
80  
81              // Verify that the current page is still available and a html page
82              final Page enclosedPage = w.getEnclosedPage();
83              if (enclosedPage == null || !enclosedPage.isHtmlPage()) {
84                  if (enclosedPage == null) {
85                      LOG.debug("The page that originated this job doesn't exist anymore. Execution cancelled.");
86                      return;
87                  }
88                  if (LOG.isDebugEnabled()) {
89                      LOG.debug("The page that originated this job is no html page ("
90                                  + enclosedPage.getClass().getName() + "). Execution cancelled.");
91                  }
92                  return;
93              }
94  
95              runJavaScript((HtmlPage) enclosedPage);
96          }
97          finally {
98              if (LOG.isDebugEnabled()) {
99                  LOG.debug("Finished executing " + this + ".");
100             }
101         }
102     }
103 
104     /** {@inheritDoc} */
105     @Override
106     public String toString() {
107         return "JavaScript Execution Job " + getId() + ": " + label_;
108     }
109 
110     /**
111      * Run the JavaScript from the concrete class.
112      * @param page the {@link HtmlPage} that owns the script
113      */
114     protected abstract void runJavaScript(HtmlPage page);
115 }