1 38 package com.gargoylesoftware.htmlunit.javascript.host; 39 40 import java.io.IOException ; 41 import java.net.MalformedURLException ; 42 import java.net.URL ; 43 import java.util.Arrays ; 44 import java.util.HashMap ; 45 import java.util.List ; 46 import java.util.Map ; 47 48 import org.apache.commons.collections.Transformer; 49 import org.jaxen.JaxenException; 50 import org.jaxen.XPath; 51 import org.mozilla.javascript.Context; 52 import org.mozilla.javascript.Function; 53 import org.mozilla.javascript.NativeArray; 54 import org.mozilla.javascript.Scriptable; 55 56 import com.gargoylesoftware.htmlunit.AlertHandler; 57 import com.gargoylesoftware.htmlunit.ConfirmHandler; 58 import com.gargoylesoftware.htmlunit.ElementNotFoundException; 59 import com.gargoylesoftware.htmlunit.Page; 60 import com.gargoylesoftware.htmlunit.PromptHandler; 61 import com.gargoylesoftware.htmlunit.StatusHandler; 62 import com.gargoylesoftware.htmlunit.TopLevelWindow; 63 import com.gargoylesoftware.htmlunit.WebClient; 64 import com.gargoylesoftware.htmlunit.WebRequestSettings; 65 import com.gargoylesoftware.htmlunit.WebWindow; 66 import com.gargoylesoftware.htmlunit.html.BaseFrame; 67 import com.gargoylesoftware.htmlunit.html.DomNode; 68 import com.gargoylesoftware.htmlunit.html.HtmlElement; 69 import com.gargoylesoftware.htmlunit.html.HtmlPage; 70 import com.gargoylesoftware.htmlunit.html.xpath.HtmlUnitXPath; 71 import com.gargoylesoftware.htmlunit.javascript.ElementArray; 72 import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; 73 74 91 public class Window extends SimpleScriptable { 92 93 private static final long serialVersionUID = -7730298149962810325L; 94 private Document document_; 95 private Navigator navigator_; 96 private WebWindow webWindow_; 97 private Screen screen_; 98 private History history_; 99 private Location location_; 100 private Function onload_; 101 private final Map timeoutThreads_ = new HashMap (); 102 private int nextTimeoutId_; 103 private String status_ = ""; 104 private ElementArray frames_; 106 110 public Window() { 111 } 112 113 114 118 public void jsConstructor() { 119 } 120 121 122 126 public void jsxFunction_alert( final String message ) { 127 final AlertHandler handler = getWebWindow().getWebClient().getAlertHandler(); 128 if( handler == null ) { 129 getLog().warn("window.alert(\""+message+"\") no alert handler installed"); 130 } 131 else { 132 handler.handleAlert(document_.getHtmlPage(), message); 133 } 134 } 135 136 137 142 public boolean jsxFunction_confirm( final String message ) { 143 final ConfirmHandler handler = getWebWindow().getWebClient().getConfirmHandler(); 144 if( handler == null ) { 145 getLog().warn("window.confirm(\""+message+"\") no confirm handler installed"); 146 return false; 147 } 148 else { 149 return handler.handleConfirm(document_.getHtmlPage(), message); 150 } 151 } 152 153 154 159 public String jsxFunction_prompt( final String message ) { 160 final PromptHandler handler = getWebWindow().getWebClient().getPromptHandler(); 161 if( handler == null ) { 162 getLog().warn("window.prompt(\""+message+"\") no prompt handler installed"); 163 return null; 164 } 165 else { 166 return handler.handlePrompt(document_.getHtmlPage(), message); 167 } 168 } 169 170 171 175 public Document jsxGet_document() { 176 return document_; 177 } 178 179 180 189 public static Object jsxFunction_open( 190 final Context context, final Scriptable scriptable, final Object [] args, final Function function ) { 191 192 final String url = getStringArg(0, args, null); 193 final String windowName = getStringArg(1, args, ""); 194 final String features = getStringArg(2, args, null); 195 final boolean replaceCurrentEntryInBrowsingHistory = getBooleanArg(3, args, false); 196 final Window thisWindow = (Window)scriptable; 197 198 if( features != null 199 || replaceCurrentEntryInBrowsingHistory == true ) { 200 201 thisWindow.getLog().debug( 202 "Window.open: features and replaceCurrentEntryInBrowsingHistory " 203 + "not implemented: url=["+url 204 + "] windowName=["+windowName 205 + "] features=["+features 206 + "] replaceCurrentEntry=["+replaceCurrentEntryInBrowsingHistory 207 + "]"); 208 } 209 210 final URL newUrl = thisWindow.makeUrlForOpenWindow(url); 211 final WebWindow newWebWindow= thisWindow.webWindow_.getWebClient().openWindow( 212 newUrl, windowName, thisWindow.webWindow_ ); 213 return (Window)newWebWindow.getScriptObject(); 214 } 215 216 217 private URL makeUrlForOpenWindow(final String urlString) { 218 if (urlString.length() == 0) { 219 if (getWebWindow().getWebClient().getBrowserVersion().isIE()) { 221 return WebClient.URL_ABOUT_BLANK; 222 } 223 else { 224 return null; 225 } 226 } 227 228 try { 229 final Page page = webWindow_.getEnclosedPage(); 230 if( page != null && page instanceof HtmlPage ) { 231 return ((HtmlPage)page).getFullyQualifiedUrl(urlString); 232 } 233 else { 234 return new URL (urlString); 235 } 236 } 237 catch( final MalformedURLException e ) { 238 getLog().error("Unable to create url for openWindow: relativeUrl=["+urlString+"]", e); 239 return null; 240 } 241 } 242 243 244 253 public int jsxFunction_setTimeout(final String script, final int timeout) { 254 final Runnable runnable = new Runnable () { 255 public void run() { 256 final Window window = Window.this; 257 final Page page = window.getWebWindow().getEnclosedPage(); 258 boolean contextEntered = false; 259 try { 260 Thread.sleep(timeout); 261 window.getLog().debug("Executing timeout: " + script); 262 263 final WebWindow webWindow = window.getWebWindow(); 264 if (!webWindow.getWebClient().getWebWindows().contains(webWindow) 266 || webWindow.getEnclosedPage() != page) { 267 268 window.getLog().debug("the page that originated the setTimeout doesnt exist anymore. " 269 + "Execution cancelled."); 270 return; 271 } 272 273 Context.enter(); 275 contextEntered = true; 276 final HtmlPage htmlPage = window.document_.getHtmlPage(); 277 htmlPage.executeJavaScriptIfPossible( 278 script, "Window.setTimeout()", true, htmlPage.getDocumentElement()); 279 } 280 catch( final InterruptedException e ) { 281 window.getLog().debug("JavaScript timeout thread interrupted; clearTimeout() probably called."); 282 } 283 catch( final Exception e ) { 284 window.getLog().error("Caught exception in Window.setTimeout()", e); 285 } 286 finally { 287 if (contextEntered) { 288 Context.exit(); 290 } 291 } 292 } 293 }; 294 final int id = nextTimeoutId_++; 295 final String threadName = "HtmlUnit setTimeout() Thread " + id; 296 final Thread setTimeoutThread = new Thread (runnable, threadName); 297 timeoutThreads_.put(new Integer (id), setTimeoutThread); 298 setTimeoutThread.setPriority(Thread.currentThread().getPriority() + 1); 299 setTimeoutThread.start(); 300 return id; 301 } 302 303 304 309 public void jsxFunction_clearTimeout(final int timeoutId) { 310 final Thread setTimeoutThread = (Thread ) timeoutThreads_.get(new Integer (timeoutId)); 311 if(setTimeoutThread != null) { 312 setTimeoutThread.interrupt(); 313 } 314 } 315 316 317 321 public Navigator jsxGet_navigator() { 322 return navigator_; 323 } 324 325 326 330 public Window jsxGet_window() { 331 return this; 332 } 333 334 335 339 public Window jsxGet_self() { 340 return this; 341 } 342 343 344 348 public Location jsxGet_location() { 349 return location_; 350 } 351 352 353 358 public void jsxSet_location( final String newLocation ) throws IOException { 359 try { 360 final HtmlPage page = (HtmlPage)webWindow_.getEnclosedPage(); 361 final URL url = page.getFullyQualifiedUrl(newLocation); 362 363 getLog().debug( 364 "window.location=" + newLocation + " (" + url.toExternalForm() 365 + "), for window named '" + webWindow_.getName() + "'"); 366 367 webWindow_.getWebClient().getPage(webWindow_, new WebRequestSettings(url)); 368 } 369 catch( final MalformedURLException e ) { 370 getLog().error("jsxSet_location(\""+newLocation+"\") Got MalformedURLException", e); 371 throw e; 372 } 373 catch( final IOException e ) { 374 getLog().error("jsxSet_location(\""+newLocation+"\") Got IOException", e); 375 throw e; 376 } 377 } 378 379 380 384 public Screen jsxGet_screen() { 385 return screen_; 386 } 387 388 389 393 public History jsxGet_history() { 394 return history_; 395 } 396 397 398 403 public void initialize( final HtmlPage htmlPage ) throws Exception { 404 405 webWindow_ = htmlPage.getEnclosingWindow(); 406 webWindow_.setScriptObject(this); 407 setDomNode(htmlPage); 411 412 document_ = (Document) makeJavaScriptObject("Document"); 413 document_.setDomNode(htmlPage); 414 415 navigator_ = (Navigator)makeJavaScriptObject("Navigator"); 416 navigator_.setParentScope(this); 417 screen_ = (Screen)makeJavaScriptObject("Screen"); 418 history_ = (History)makeJavaScriptObject("History"); 419 420 location_ = (Location)makeJavaScriptObject("Location"); 421 location_.initialize(this); 422 } 423 424 425 429 public SimpleScriptable jsxGet_top() { 430 final WebWindow topWebWindow = webWindow_.getTopWindow(); 431 return (SimpleScriptable)topWebWindow.getScriptObject(); 432 } 433 434 435 439 public SimpleScriptable jsxGet_parent() { 440 final WebWindow parentWebWindow = webWindow_.getParentWindow(); 441 return (SimpleScriptable)parentWebWindow.getScriptObject(); 442 } 443 444 445 449 public Object jsxGet_opener() { 450 if( webWindow_ instanceof TopLevelWindow ) { 451 final WebWindow opener = ((TopLevelWindow)webWindow_).getOpener(); 452 if( opener != null ) { 453 return (Window)opener.getScriptObject(); 454 } 455 } 456 457 return null; 458 } 459 460 461 465 public ElementArray jsxGet_frames() { 466 if (frames_ == null) { 467 final XPath xpath; 468 try { 469 xpath = new HtmlUnitXPath("//*[(name() = 'frame' or name() = 'iframe')]"); 470 } 471 catch (final JaxenException e) { 472 throw Context.reportRuntimeError("Failed initializing frame collections: " + e.getMessage()); 474 } 475 final HtmlPage page = (HtmlPage) getWebWindow().getEnclosedPage(); 476 frames_ = (ElementArray) makeJavaScriptObject(ElementArray.JS_OBJECT_NAME); 477 Transformer toEnclosedWindow = new Transformer() { 478 public Object transform(final Object obj) { 479 return ((BaseFrame) obj).getEnclosedWindow(); 480 } 481 }; 482 frames_.init(page, xpath, toEnclosedWindow); 483 } 484 485 return frames_; 486 } 487 488 492 public WebWindow getWebWindow() { 493 return webWindow_; 494 } 495 496 497 500 public void jsxFunction_focus() { 501 webWindow_.getWebClient().setCurrentWindow(webWindow_); 502 } 503 504 505 508 public void jsxFunction_blur() { 509 getLog().debug( "Window.blur() not implemented" ); 510 } 511 512 513 516 public void jsxFunction_close() { 517 final WebWindow window = ((HtmlPage) getDomNodeOrDie()).getEnclosingWindow(); 518 getWebWindow().getWebClient().deregisterWebWindow(window); 519 } 520 521 522 527 public void jsxFunction_moveTo(final int x, final int y) { 528 getLog().debug( "Window.moveTo() not implemented" ); 529 } 530 531 536 public void jsxFunction_moveBy(final int x, final int y) { 537 getLog().debug( "Window.moveBy() not implemented" ); 538 } 539 540 545 public void jsxFunction_resizeTo(final int width, final int height) { 546 getLog().debug( "Window.resizeTo() not implemented" ); 547 } 548 549 554 public void jsxFunction_scroll(final int x, final int y) { 555 getLog().debug( "Window.scroll() not implemented" ); 556 } 557 558 563 public void jsxFunction_scrollBy(final int x, final int y) { 564 getLog().debug( "Window.scrollBy() not implemented" ); 565 } 566 567 571 public void jsxFunction_scrollByLines(final int lines) { 572 getLog().debug( "Window.scrollByLines() not implemented" ); 573 } 574 575 579 public void jsxFunction_scrollByPages(final int pages) { 580 getLog().debug( "Window.scrollByPages() not implemented" ); 581 } 582 583 588 public void jsxFunction_scrollTo(final int x, final int y) { 589 getLog().debug( "Window.scrollTo() not implemented" ); 590 } 591 592 596 public void jsxSet_onload(final Function newOnload) { 597 onload_ = newOnload; 598 } 599 600 604 public Function jsxGet_onload() { 605 if (onload_ == null) { 606 final HtmlPage page = (HtmlPage) webWindow_.getEnclosedPage(); 608 final List listTagNames = Arrays.asList(new String [] {"body", "frameset"}); 609 final List listElements = page.getDocumentElement().getHtmlElementsByTagNames(listTagNames); 610 if (!listElements.isEmpty()) { 611 return ((HtmlElement) listElements.get(0)).getEventHandler("onload"); 612 } 613 else { 614 return null; 615 } 616 } 617 else { 618 return onload_; 619 } 620 } 621 622 626 public String jsxGet_name() { 627 return webWindow_.getName(); 628 } 629 630 634 public void jsxSet_name( final String newName ) { 635 webWindow_.setName(newName); 636 } 637 638 642 public String jsxGet_onerror() { 643 getLog().debug("Window.onerror not implemented"); 644 return ""; 645 } 646 647 651 public void jsxSet_onerror( final String newValue) { 652 getLog().debug("Window.onerror not implemented"); 653 } 654 655 661 public Object get( final String name, final Scriptable start ) { 662 if( getDomNodeOrNull() == null && document_ != null ) { 664 setDomNode( document_.getHtmlPage() ); 665 } 666 667 Object result = super.get(name, start); 668 669 final Window thisWindow = (Window) start; 670 if( result == NOT_FOUND ) { 672 final DomNode domNode = thisWindow.getDomNodeOrNull(); 673 result = getFrameByName( domNode.getPage(), name ); 674 } 675 676 if( result == NOT_FOUND ) { 678 result = getParentScope().get(name, start); 679 if ("Function".equals(name)) { 682 result = new ScoperFunctionObject((Function) result, start); 683 } 684 } 685 686 if (result == NOT_FOUND) { 688 final DomNode domNode = thisWindow.getDomNodeOrNull(); 691 if (domNode != null 692 && domNode.getPage().getWebClient().getBrowserVersion().isIE()) { 693 final NativeArray array = (NativeArray) thisWindow.document_.jsxFunction_getElementsByName( name ); 694 if (array.getLength() == 1) { 695 result = array.get(0, this); 696 } 697 else if (array.getLength() > 1) { 698 result = array; 699 } 700 else { 701 result = thisWindow.document_.jsxFunction_getElementById(name); 702 } 703 } 704 } 705 return result; 706 } 707 708 private Object getFrameByName( final HtmlPage page, final String name ) { 709 try { 710 return page.getFrameByName(name).getScriptObject(); 711 } 712 catch (final ElementNotFoundException e) { 713 return NOT_FOUND; 714 } 715 } 716 717 726 public Object jsxFunction_execScript(final String script, final String language) { 727 if ("javascript".equalsIgnoreCase(language) || "jscript".equalsIgnoreCase(language)) { 728 final HtmlPage htmlPage = document_.getHtmlPage(); 729 final HtmlElement doc = htmlPage.getDocumentElement(); 730 htmlPage.executeJavaScriptIfPossible(script, "Window.execScript()", true, doc); 731 } 732 else if ("vbscript".equalsIgnoreCase(language)) { 733 getLog().warn("VBScript not supported in Window.execScript()."); 734 } 735 else { 736 throw Context.reportRuntimeError("Invalid class string"); 738 } 739 return null; 740 } 741 742 746 public String jsxGet_status() { 747 return status_; 748 } 749 750 754 public void jsxSet_status( final String message ) { 755 status_ = message; 756 757 final StatusHandler statusHandler = webWindow_.getWebClient().getStatusHandler(); 758 if( statusHandler != null ) { 759 statusHandler.statusMessageChanged(webWindow_.getEnclosedPage(), message); 760 } 761 } 762 763 775 public static int jsxFunction_setInterval(final Context context, final Scriptable scriptable, 776 final Object [] args, final Function function ) { 777 778 final Window thisWindow = (Window)scriptable; 779 780 thisWindow.getLog().warn("Current implementation of setInterval does nothing."); 781 return 0; 782 } 783 784 791 public void jsxFunction_clearInterval(final int iIntervalId) { 792 getLog().warn("Current implementation of clearInterval does nothing."); 793 } 794 795 796 801 public int jsxGet_innerWidth() { 802 return 1276; } 804 805 810 public int jsxGet_outerWidth() { 811 return 1276; } 813 814 819 public int jsxGet_innerHeight() { 820 return 778; } 822 823 828 public int jsxGet_outerHeight() { 829 return 936; } 831 } 832 | Popular Tags |