1 21 24 package org.lobobrowser.html.js; 25 26 import java.util.*; 27 import java.lang.ref.*; 28 import javax.swing.Timer ; 29 import java.awt.event.*; 30 import java.util.logging.*; 31 32 import org.lobobrowser.html.*; 33 import org.lobobrowser.html.domimpl.*; 34 import org.lobobrowser.js.*; 35 import org.lobobrowser.util.ID; 36 import org.mozilla.javascript.Context; 37 import org.mozilla.javascript.Function; 38 import org.mozilla.javascript.Scriptable; 39 import org.mozilla.javascript.ScriptableObject; 40 import org.w3c.dom.Document ; 41 import org.w3c.dom.html2.*; 42 43 public class Window extends AbstractScriptableDelegate { 44 private static final Logger logger = Logger.getLogger(Window.class.getName()); 45 private static final Map CONTEXT_WINDOWS = new WeakHashMap(); 46 private static final JavaClassWrapper XMLHTTPREQUEST_WRAPPER = JavaClassWrapperFactory.getInstance().getClassWrapper(XMLHttpRequest.class); 48 49 private final HtmlRendererContext rcontext; 50 private final UserAgentContext uaContext; 51 52 private Navigator navigator; 53 private Screen screen; 54 private Location location; 55 private Map taskMap; 56 private volatile Document document; 57 58 public Window(HtmlRendererContext rcontext, UserAgentContext uaContext) { 59 this.rcontext = rcontext; 63 this.uaContext = uaContext; 64 } 65 66 public HtmlRendererContext getHtmlRendererContext() { 67 return this.rcontext; 68 } 69 70 public void setDocument(Document document) { 71 Document prevDocument = this.document; 72 if(prevDocument != document) { 73 this.forgetAllTasks(); 74 Function onunload = this.onunload; 75 if(onunload != null) { 76 HTMLDocumentImpl oldDoc = (HTMLDocumentImpl) this.document; 77 Executor.executeFunction(this.getWindowScope(), onunload, oldDoc.getDocumentURL(), this.uaContext); 78 this.onunload = null; 79 } 80 this.document = document; 81 } 82 } 83 84 public Document getDocument() { 85 return this.document; 86 } 87 88 private void putTask(Integer timeoutID, Timer timer) { 89 synchronized(this) { 90 Map taskMap = this.taskMap; 91 if(taskMap == null) { 92 taskMap = new HashMap(); 93 this.taskMap = taskMap; 94 } 95 taskMap.put(timeoutID, timer); 96 } 97 } 98 99 private void forgetTask(Integer timeoutID, boolean cancel) { 100 synchronized(this) { 101 Map taskMap = this.taskMap; 102 if(taskMap != null) { 103 Timer timer = (Timer ) taskMap.remove(timeoutID); 104 if(timer != null && cancel) { 105 timer.stop(); 106 } 107 } 108 } 109 } 110 111 private void forgetAllTasks() { 112 synchronized(this) { 113 Map taskMap = this.taskMap; 114 if(taskMap != null) { 115 Iterator i = taskMap.values().iterator(); 116 while(i.hasNext()) { 117 Timer timer = (Timer ) i.next(); 118 timer.stop(); 119 } 120 this.taskMap = null; 121 } 122 } 123 } 124 125 135 public void alert(String message) { 136 if(this.rcontext != null) { 137 this.rcontext.alert(message); 138 } 139 } 140 141 public void back() { 142 HtmlRendererContext rcontext = this.rcontext; 143 if(rcontext != null) { 144 rcontext.back(); 145 } 146 } 147 148 public void blur() { 149 HtmlRendererContext rcontext = this.rcontext; 150 if(rcontext != null) { 151 rcontext.blur(); 152 } 153 } 154 155 public void clearTimeout(int timeoutID) { 156 Integer key = new Integer (timeoutID); 157 this.forgetTask(key, true); 158 } 159 160 public void close() { 161 HtmlRendererContext rcontext = this.rcontext; 162 if(rcontext != null) { 163 rcontext.close(); 164 } 165 } 166 167 public boolean confirm(String message) { 168 HtmlRendererContext rcontext = this.rcontext; 169 if(rcontext != null) { 170 return rcontext.confirm(message); 171 } 172 else { 173 return false; 174 } 175 } 176 177 public Object eval(String javascript) { 178 HTMLDocumentImpl document = (HTMLDocumentImpl) this.document; 179 if(document == null) { 180 throw new IllegalStateException ("Cannot evaluate if document is not set."); 181 } 182 Context ctx = Executor.createContext(document.getDocumentURL(), this.uaContext); 183 try { 184 Scriptable scope = this.getWindowScope(); 185 if(scope == null) { 186 throw new IllegalStateException ("Scriptable (scope) instance was expected to be keyed as UserData to document using " + Executor.SCOPE_KEY); 187 } 188 String scriptURI = "window.eval"; 189 if(logger.isLoggable(Level.INFO)) { 190 logger.info("eval(): javascript follows...\r\n" + javascript); 191 } 192 return ctx.evaluateString(scope, javascript, scriptURI, 1, null); 193 } finally { 194 Context.exit(); 195 } 196 } 197 198 public void focus() { 199 HtmlRendererContext rcontext = this.rcontext; 200 if(rcontext != null) { 201 rcontext.focus(); 202 } 203 } 204 205 private ScriptableObject windowScope; 206 207 public Scriptable getWindowScope() { 208 synchronized(this) { 209 ScriptableObject windowScope = this.windowScope; 210 if(windowScope != null) { 211 return windowScope; 212 } 213 Context ctx = Context.enter(); 215 try { 216 windowScope = (ScriptableObject) JavaScript.getInstance().getJavascriptObject(this, null); 218 ctx.initStandardObjects(windowScope); 219 220 final Scriptable ws = windowScope; 222 JavaInstantiator xi = new JavaInstantiator() { 223 public Object newInstance() { 224 HTMLDocumentImpl doc = (HTMLDocumentImpl) document; 225 if(doc == null) { 226 throw new IllegalStateException ("Cannot perform operation when document is unset."); 227 } 228 return new XMLHttpRequest(uaContext, doc.getDocumentURL(), ws); 229 } 230 }; 231 Function xmlHttpRequestC = JavaObjectWrapper.getConstructor("XMLHttpRequest", XMLHTTPREQUEST_WRAPPER, windowScope, xi); 232 ScriptableObject.defineProperty(windowScope, "XMLHttpRequest", xmlHttpRequestC, ScriptableObject.READONLY); 233 234 this.defineElementClass(windowScope, "Image", "img", HTMLImageElementImpl.class); 236 this.defineElementClass(windowScope, "Script", "script", HTMLScriptElementImpl.class); 237 this.defineElementClass(windowScope, "IFrame", "iframe", HTMLIFrameElementImpl.class); 238 this.defineElementClass(windowScope, "Option", "option", HTMLOptionElementImpl.class); 239 this.defineElementClass(windowScope, "Select", "select", HTMLSelectElementImpl.class); 240 241 this.windowScope = windowScope; 242 return windowScope; 243 } finally { 244 Context.exit(); 245 } 246 } 247 } 248 249 private final void defineElementClass(Scriptable scope, final String jsClassName, final String elementName, Class javaClass) { 250 JavaInstantiator ji = new JavaInstantiator() { 251 public Object newInstance() { 252 Document document = Window.this.document; 253 if(document == null) { 254 throw new IllegalStateException ("Document not set in current context."); 255 } 256 return document.createElement(elementName); 257 } 258 }; 259 JavaClassWrapper classWrapper = JavaClassWrapperFactory.getInstance().getClassWrapper(javaClass); 260 Function constructorFunction = JavaObjectWrapper.getConstructor(jsClassName, classWrapper, scope, ji); 261 ScriptableObject.defineProperty(scope, jsClassName, constructorFunction, ScriptableObject.READONLY); 262 } 263 264 public static Window getWindow(HtmlRendererContext rcontext) { 265 if(rcontext == null) { 266 return null; 267 } 268 synchronized(CONTEXT_WINDOWS) { 269 Reference wref = (Reference) CONTEXT_WINDOWS.get(rcontext); 270 if(wref != null) { 271 Window window = (Window) wref.get(); 272 if(window != null) { 273 return window; 274 } 275 } 276 Window window = new Window(rcontext, rcontext.getUserAgentContext()); 277 CONTEXT_WINDOWS.put(rcontext, new WeakReference(window)); 278 return window; 279 } 280 } 281 282 public Window open(String relativeUrl, String windowName, String windowFeatures, boolean replace) { 283 HtmlRendererContext rcontext = this.rcontext; 284 if(rcontext != null) { 285 java.net.URL url; 286 Object document = this.document; 287 if(document instanceof HTMLDocumentImpl) { 288 url = ((HTMLDocumentImpl) document).getFullURL(relativeUrl); 289 } 290 else { 291 try { 292 url = new java.net.URL (relativeUrl); 293 } catch(java.net.MalformedURLException mfu) { 294 throw new IllegalArgumentException ("Malformed URI: " + relativeUrl); 295 } 296 } 297 HtmlRendererContext newContext = rcontext.open(url, windowName, windowFeatures, replace); 298 return getWindow(newContext); 299 } 300 else { 301 return null; 302 } 303 } 304 305 public Window open(String url, String windowName) { 306 return this.open(url, windowName, "", false); 307 } 308 309 public Window open(String url, String windowName, String windowFeatures) { 310 return this.open(url, windowName, windowFeatures, false); 311 } 312 313 public String prompt(String message) { 314 return this.prompt(message, ""); 315 } 316 317 public String prompt(String message, int inputDefault) { 318 return this.prompt(message, String.valueOf(inputDefault)); 319 } 320 321 public String prompt(String message, String inputDefault) { 322 HtmlRendererContext rcontext = this.rcontext; 323 if(rcontext != null) { 324 return rcontext.prompt(message, inputDefault); 325 } 326 else { 327 return null; 328 } 329 } 330 331 public void scroll(int x, int y) { 332 HtmlRendererContext rcontext = this.rcontext; 333 if(rcontext != null) { 334 rcontext.scroll(x, y); 335 } 336 } 337 338 public int setTimeout(final String expr, double millis) { 339 final int timeID = ID.generateInt(); 340 final Integer timeIDInt = new Integer (timeID); 341 ActionListener task = new ActionListener() { 342 public void actionPerformed(ActionEvent e) { 343 Window.this.forgetTask(timeIDInt, false); 345 Window.this.eval(expr); 346 } 347 }; 348 if(millis > Integer.MAX_VALUE || millis < 0) { 349 throw new IllegalArgumentException ("Timeout value " + millis + " is not supported."); 350 } 351 Timer timer = new Timer ((int) millis, task); 352 timer.setRepeats(false); 353 timer.start(); 354 this.putTask(timeIDInt, timer); 355 return timeID; 356 } 357 358 public int setTimeout(final Function function, double millis) { 359 final int timeID = ID.generateInt(); 360 final Integer timeIDInt = new Integer (timeID); 361 ActionListener task = new ActionListener() { 362 public void actionPerformed(ActionEvent e) { 363 Window.this.forgetTask(timeIDInt, false); 365 HTMLDocumentImpl doc = (HTMLDocumentImpl) document; 366 if(doc == null) { 367 throw new IllegalStateException ("Cannot perform operation when document is unset."); 368 } 369 Executor.executeFunction(getWindowScope(), function, doc.getDocumentURL(), uaContext); 370 } 371 }; 372 if(millis > Integer.MAX_VALUE || millis < 0) { 373 throw new IllegalArgumentException ("Timeout value " + millis + " is not supported."); 374 } 375 Timer timer = new Timer ((int) millis, task); 376 timer.setRepeats(false); 377 timer.start(); 378 this.putTask(timeIDInt, timer); 379 return timeID; 380 } 381 382 public boolean isClosed() { 383 HtmlRendererContext rcontext = this.rcontext; 384 if(rcontext != null) { 385 return rcontext.isClosed(); 386 } 387 else { 388 return false; 389 } 390 } 391 392 public String getDefaultStatus() { 393 HtmlRendererContext rcontext = this.rcontext; 394 if(rcontext != null) { 395 return rcontext.getDefaultStatus(); 396 } 397 else { 398 return null; 399 } 400 } 401 402 public HTMLCollection getFrames() { 403 Document doc = this.document; 404 if(doc instanceof HTMLDocumentImpl) { 405 return ((HTMLDocumentImpl) doc).getFrames(); 406 } 407 return null; 408 } 409 410 413 public int getLength() { 414 HTMLCollection frames = this.getFrames(); 415 return frames == null ? 0 : frames.getLength(); 416 } 417 418 public String getName() { 419 HtmlRendererContext rcontext = this.rcontext; 420 if(rcontext != null) { 421 return rcontext.getName(); 422 } 423 else { 424 return null; 425 } 426 } 427 428 public Window getParent() { 429 HtmlRendererContext rcontext = this.rcontext; 430 if(rcontext != null) { 431 return Window.getWindow(rcontext.getParent()); 432 } 433 else { 434 return null; 435 } 436 } 437 438 public Window getOpener() { 439 HtmlRendererContext rcontext = this.rcontext; 440 if(rcontext != null) { 441 return Window.getWindow(rcontext.getOpener()); 442 } 443 else { 444 return null; 445 } 446 } 447 448 public void setOpener(Window opener) { 449 HtmlRendererContext rcontext = this.rcontext; 450 if(rcontext != null) { 451 if(opener == null) { 452 rcontext.setOpener(null); 453 } 454 else { 455 rcontext.setOpener(opener.rcontext); 456 } 457 } 458 } 459 460 public Window getSelf() { 461 return this; 462 } 463 464 public String getStatus() { 465 HtmlRendererContext rcontext = this.rcontext; 466 if(rcontext != null) { 467 return rcontext.getStatus(); 468 } 469 else { 470 return null; 471 } 472 } 473 474 public void setStatus(String message) { 475 HtmlRendererContext rcontext = this.rcontext; 476 if(rcontext != null) { 477 rcontext.setStatus(message); 478 } 479 } 480 481 public Window getTop() { 482 HtmlRendererContext rcontext = this.rcontext; 483 if(rcontext != null) { 484 return Window.getWindow(rcontext.getTop()); 485 } 486 else { 487 return null; 488 } 489 } 490 491 public Window getWindow() { 492 return this; 493 } 494 495 496 public Navigator getNavigator() { 497 synchronized(this) { 498 Navigator nav = this.navigator; 499 if(nav == null) { 500 nav = new Navigator(this.uaContext); 501 this.navigator = nav; 502 } 503 return nav; 504 } 505 } 506 507 public Screen getScreen() { 508 synchronized(this) { 509 Screen nav = this.screen; 510 if(nav == null) { 511 nav = new Screen(); 512 this.screen = nav; 513 } 514 return nav; 515 } 516 } 517 518 public Location getLocation() { 519 synchronized(this) { 520 Location location = this.location; 521 if(location == null) { 522 location = new Location(this); 523 this.location = location; 524 } 525 return location; 526 } 527 } 528 529 public void setLocation(String location) { 530 this.getLocation().setHref(location); 531 } 532 533 public Function getOnload() { 534 Document doc = this.document; 535 if(doc instanceof HTMLDocumentImpl) { 536 return ((HTMLDocumentImpl) doc).getOnloadHandler(); 537 } 538 else { 539 return null; 540 } 541 } 542 543 public void setOnload(Function onload) { 544 Document doc = this.document; 547 if(doc instanceof HTMLDocumentImpl) { 548 ((HTMLDocumentImpl) doc).setOnloadHandler(onload); 549 } 550 } 551 552 private Function onunload; 553 554 public Function getOnunload() { 555 return onunload; 556 } 557 558 public void setOnunload(Function onunload) { 559 this.onunload = onunload; 560 } 561 } 562 563 | Popular Tags |