1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.support.components;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.Dimension;
18 import java.awt.Toolkit;
19 import java.awt.event.ActionEvent;
20 import java.beans.PropertyChangeListener;
21 import java.beans.PropertyChangeSupport;
22 import java.lang.reflect.InvocationTargetException;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import javax.swing.AbstractAction;
32 import javax.swing.Action;
33 import javax.swing.JEditorPane;
34 import javax.swing.JLabel;
35 import javax.swing.JPanel;
36 import javax.swing.SwingUtilities;
37
38 import org.mozilla.interfaces.nsIBinaryInputStream;
39 import org.mozilla.interfaces.nsIDOMWindow;
40 import org.mozilla.interfaces.nsIHttpChannel;
41 import org.mozilla.interfaces.nsIHttpHeaderVisitor;
42 import org.mozilla.interfaces.nsIInputStream;
43 import org.mozilla.interfaces.nsIInterfaceRequestor;
44 import org.mozilla.interfaces.nsIObserver;
45 import org.mozilla.interfaces.nsIObserverService;
46 import org.mozilla.interfaces.nsIRequest;
47 import org.mozilla.interfaces.nsISeekableStream;
48 import org.mozilla.interfaces.nsIServiceManager;
49 import org.mozilla.interfaces.nsISupports;
50 import org.mozilla.interfaces.nsIURI;
51 import org.mozilla.interfaces.nsIUploadChannel;
52 import org.mozilla.interfaces.nsIWeakReference;
53 import org.mozilla.interfaces.nsIWebProgress;
54 import org.mozilla.interfaces.nsIWebProgressListener;
55 import org.mozilla.xpcom.Mozilla;
56 import org.mozilla.xpcom.XPCOMException;
57
58 import com.eviware.soapui.SoapUI;
59 import com.eviware.soapui.impl.rest.panels.request.views.html.HttpHtmlResponseView;
60 import com.eviware.soapui.impl.rest.support.RestUtils;
61 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
62 import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequest;
63 import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequestStep;
64 import com.eviware.soapui.impl.wsdl.teststeps.registry.HttpRequestStepFactory;
65 import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
66 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
67 import com.eviware.soapui.model.settings.Settings;
68 import com.eviware.soapui.settings.ProxySettings;
69 import com.eviware.soapui.settings.WebRecordingSettings;
70 import com.eviware.soapui.support.StringUtils;
71 import com.eviware.soapui.support.Tools;
72 import com.eviware.soapui.support.UISupport;
73 import com.eviware.soapui.support.types.StringList;
74 import com.eviware.soapui.support.types.StringToStringsMap;
75 import com.eviware.soapui.support.xml.XmlUtils;
76 import com.teamdev.jxbrowser.Browser;
77 import com.teamdev.jxbrowser.BrowserFactory;
78 import com.teamdev.jxbrowser.BrowserType;
79 import com.teamdev.jxbrowser.NewWindowContainer;
80 import com.teamdev.jxbrowser.NewWindowManager;
81 import com.teamdev.jxbrowser.NewWindowParams;
82 import com.teamdev.jxbrowser.events.NavigationAdapter;
83 import com.teamdev.jxbrowser.events.NavigationEvent;
84 import com.teamdev.jxbrowser.events.NavigationFinishedEvent;
85 import com.teamdev.jxbrowser.events.NavigationListener;
86 import com.teamdev.jxbrowser.events.NavigationStatusCode;
87 import com.teamdev.jxbrowser.events.StatusChangedEvent;
88 import com.teamdev.jxbrowser.events.StatusListener;
89 import com.teamdev.jxbrowser.mozilla.MozillaBrowser;
90 import com.teamdev.jxbrowser.prompt.DefaultPromptService;
91 import com.teamdev.jxbrowser.security.HttpSecurityAction;
92 import com.teamdev.jxbrowser.security.HttpSecurityHandler;
93 import com.teamdev.jxbrowser.security.SecurityProblem;
94 import com.teamdev.jxbrowser1.mozilla.MozillaWebBrowser;
95 import com.teamdev.xpcom.PoxyAuthenticationHandler;
96 import com.teamdev.xpcom.ProxyConfiguration;
97 import com.teamdev.xpcom.ProxyServerAuthInfo;
98 import com.teamdev.xpcom.ProxyServerType;
99 import com.teamdev.xpcom.Services;
100 import com.teamdev.xpcom.Xpcom;
101 import com.teamdev.xpcom.util.XPCOMManager;
102
103 public class BrowserComponent implements nsIWebProgressListener, nsIWeakReference, StatusListener
104 {
105 private static final String CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded";
106 private MozillaBrowser browser;
107 private JPanel panel = new JPanel( new BorderLayout() );
108 private JPanel statusBar;
109 private JLabel statusLabel;
110 private String errorPage;
111 private boolean showingErrorPage;
112 public String url;
113 private Boolean possibleError = false;
114 @SuppressWarnings( "unused" )
115 private boolean disposed;
116
117 private NavigationListener internalNavigationListener;
118 private HttpHtmlResponseView httpHtmlResponseView;
119 private static Boolean initialized = false;
120 private static SoapUINewWindowManager newWindowManager;
121 private static Map<nsIDOMWindow, BrowserComponent> browserMap = new HashMap<nsIDOMWindow, BrowserComponent>();
122 private static Map<BrowserComponent, Map<String, RecordedRequest>> browserRecordingMap = new HashMap<BrowserComponent, Map<String, RecordedRequest>>();
123 private final boolean addStatusBar;
124
125 static
126 {
127 initialize();
128 }
129
130 public BrowserComponent( boolean addToolbar, boolean addStatusBar )
131 {
132 this.addStatusBar = addStatusBar;
133 }
134
135 public synchronized static void initialize()
136 {
137 if( initialized )
138 return;
139
140 try
141 {
142 if( !SoapUI.isJXBrowserDisabled() )
143 {
144 Xpcom.initialize();
145 }
146
147 initialized = true;
148 }
149 catch( Throwable t )
150 {
151 t.printStackTrace();
152 }
153 }
154
155
156
157
158
159
160 /***
161 * @deprecated
162 */
163
164 public static boolean isJXBrowserDisabled()
165 {
166 return SoapUI.isJXBrowserDisabled();
167 }
168
169 public Component getComponent()
170 {
171 if( SoapUI.isJXBrowserDisabled() )
172 {
173 JEditorPane jxbrowserDisabledPanel = new JEditorPane();
174 jxbrowserDisabledPanel.setText( "browser component disabled" );
175 panel.add( jxbrowserDisabledPanel );
176 }
177 else
178 {
179 if( browser == null )
180 {
181 if( addStatusBar )
182 {
183 statusBar = new JPanel( new BorderLayout() );
184 statusLabel = new JLabel();
185 UISupport.setFixedSize( statusBar, new Dimension( 20, 20 ) );
186 statusBar.add( statusLabel, BorderLayout.WEST );
187 panel.add( statusBar, BorderLayout.SOUTH );
188 }
189
190
191
192
193 initBrowser();
194
195 browser.navigate( "about:blank" );
196 }
197 }
198 return panel;
199 }
200
201 @SuppressWarnings( "unused" )
202 private Component buildToolbar()
203 {
204 JXToolBar toolbar = UISupport.createToolbar();
205
206 toolbar.addFixed( UISupport.createToolbarButton( new BackAction() ) );
207 toolbar.addRelatedGap();
208 toolbar.addFixed( UISupport.createToolbarButton( new ForwardAction() ) );
209
210 toolbar.addGlue();
211
212 return toolbar;
213 }
214
215 public void setRecordingHttpHtmlResponseView( HttpHtmlResponseView httpHtmlResponseView )
216 {
217 this.httpHtmlResponseView = httpHtmlResponseView;
218 if( httpHtmlResponseView != null )
219 {
220 if( !browserRecordingMap.containsKey( BrowserComponent.this ) )
221 {
222 browserRecordingMap.put( BrowserComponent.this, new HashMap<String, RecordedRequest>() );
223 }
224 }
225 else
226 {
227 browserRecordingMap.remove( BrowserComponent.this );
228 }
229 }
230
231 private static final class RecordingHttpListener implements Runnable
232 {
233 public void run()
234 {
235 final Mozilla mozilla = Mozilla.getInstance();
236 nsIServiceManager serviceManager = mozilla.getServiceManager();
237 nsIObserverService observerService = ( nsIObserverService )serviceManager.getServiceByContractID(
238 "@mozilla.org/observer-service;1", nsIObserverService.NS_IOBSERVERSERVICE_IID );
239
240 final nsIBinaryInputStream in = XPCOMManager.getInstance().newComponent( "@mozilla.org/binaryinputstream;1",
241 nsIBinaryInputStream.class );
242
243 nsIObserver httpObserver = new nsIObserver()
244 {
245 public void observe( nsISupports subject, String sTopic, String sData )
246 {
247 try
248 {
249 if( EVENT_HTTP_ON_MODIFY_REQUEST.equals( sTopic ) )
250 {
251 nsIHttpChannel httpChannel = ( nsIHttpChannel )subject
252 .queryInterface( nsIHttpChannel.NS_IHTTPCHANNEL_IID );
253
254 if( httpChannel.getNotificationCallbacks() == null )
255 return;
256
257 nsIInterfaceRequestor interfaceRequestor = ( nsIInterfaceRequestor )httpChannel
258 .getNotificationCallbacks()
259 .queryInterface( nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID );
260
261 nsIDOMWindow window = ( nsIDOMWindow )interfaceRequestor
262 .getInterface( nsIDOMWindow.NS_IDOMWINDOW_IID );
263
264 BrowserComponent browserComponent = browserMap.get( window );
265 if( browserComponent != null && browserRecordingMap.containsKey( browserComponent ) )
266 {
267 RecordedRequest rr = new RecordedRequest( dumpUri( httpChannel.getURI() ),
268 httpChannel.getRequestMethod() );
269
270 nsIUploadChannel upload = ( nsIUploadChannel )httpChannel
271 .queryInterface( nsIUploadChannel.NS_IUPLOADCHANNEL_IID );
272
273 byte[] requestData = null;
274 if( upload != null )
275 {
276 nsIInputStream uploadStream = upload.getUploadStream();
277
278 if( uploadStream != null && uploadStream.available() > 0 )
279 {
280 nsISeekableStream seekable = ( nsISeekableStream )uploadStream
281 .queryInterface( nsISeekableStream.NS_ISEEKABLESTREAM_IID );
282
283 long pos = seekable.tell();
284 long available = uploadStream.available();
285
286 if( available > 0 )
287 {
288 try
289 {
290 synchronized( mozilla )
291 {
292 in.setInputStream( uploadStream );
293 requestData = in.readByteArray( available );
294 String requestBody = getRequestBody( requestData );
295 if( requestBody != null && requestBody.length() > 0 )
296 {
297 rr.setContent( requestBody );
298 String contentType = getContentType( requestData );
299 if( StringUtils.hasContent( contentType ) )
300 rr.setContentType( contentType );
301 }
302 }
303 }
304 catch( Throwable e )
305 {
306 e.printStackTrace();
307 }
308 finally
309 {
310 seekable.seek( nsISeekableStream.NS_SEEK_SET, pos );
311 }
312 }
313 }
314 }
315
316 final StringToStringsMap headersMap = new StringToStringsMap();
317 httpChannel.visitRequestHeaders( new nsIHttpHeaderVisitor()
318 {
319
320 public void visitHeader( String header, String value )
321 {
322 if( !isHeaderExcluded( header ) )
323 {
324 headersMap.put( header, value );
325 }
326 }
327
328 public nsISupports queryInterface( String sIID )
329 {
330 return Mozilla.queryInterface( this, sIID );
331 }
332 } );
333
334 rr.setHeaders( headersMap );
335
336 browserRecordingMap.get( browserComponent ).put( rr.getUrl(), rr );
337 }
338 }
339 else
340 {
341 System.out.println( "HTTPObserver: Unknown event '" + sTopic + "'" );
342 }
343 }
344 catch( Throwable e )
345 {
346
347
348 if( e.getMessage().indexOf( "0x80004002" ) == -1 )
349 SoapUI.logError( e );
350 }
351 }
352
353 public nsISupports queryInterface( String sIID )
354 {
355 return Mozilla.queryInterface( this, sIID );
356 }
357 };
358
359 boolean blnObserverIsWeakReference = false;
360 observerService.addObserver( httpObserver, EVENT_HTTP_ON_MODIFY_REQUEST, blnObserverIsWeakReference );
361 }
362
363 }
364
365 public static boolean isHeaderExcluded( String header )
366 {
367 String excluded = SoapUI.getSettings().getString( WebRecordingSettings.EXCLUDED_HEADERS, null );
368 List<String> result = new ArrayList<String>();
369 if( excluded != null && excluded.trim().length() > 0 )
370 {
371 try
372 {
373 StringList names = StringList.fromXml( excluded );
374 for( String name : names )
375 {
376 result.add( name );
377 }
378 }
379 catch( Exception e )
380 {
381 SoapUI.logError( e );
382 }
383 }
384 return result.contains( header );
385 }
386
387 private static String getContentType( byte[] requestData )
388 {
389 String request = new String( requestData );
390 int ix = request.indexOf( "Content-Type" );
391 if( ix > 0 && ix < request.length() - 14 )
392 {
393 String contentType = request.substring( ix + 14 );
394 contentType = contentType.substring( 0, contentType.indexOf( "\n" ) - 1 );
395 return contentType.trim();
396 }
397 else
398 return null;
399 }
400
401 private static String getRequestBody( byte[] requestData )
402 {
403 String request = new String( requestData );
404 int ix = request.indexOf( "\r\n\r\n" );
405 return ix == -1 ? "" : request.substring( ix + 4 );
406 }
407
408 private static final class SoapUINewWindowManager implements NewWindowManager
409 {
410 public NewWindowContainer evaluateWindow( final NewWindowParams params )
411 {
412 return new NewWindowContainer()
413 {
414 public void insertBrowser( final Browser browser )
415 {
416 browser.addNavigationListener( new NavigationListener()
417 {
418 public void navigationStarted( final NavigationEvent arg0 )
419 {
420
421 arg0.getBrowser().removeNavigationListener( this );
422
423
424
425 BrowserComponent browserComponent = browserMap
426 .get( ( ( ( MozillaWebBrowser )( ( MozillaBrowser )params.getParent() ).getPeer() ) )
427 .getWebBrowser().getContentDOMWindow() );
428 if( browserRecordingMap.containsKey( browserComponent ) )
429 {
430 browserComponent.replaceBrowser( arg0.getBrowser() );
431 }
432 else
433 {
434 SwingUtilities.invokeLater( new Runnable()
435 {
436 public void run()
437 {
438 if( UISupport.confirm( "Open [" + arg0.getUrl() + "] with system Browser?", "Open URL" ) )
439 Tools.openURL( arg0.getUrl() );
440 }
441 } );
442
443 arg0.getBrowser().dispose();
444 }
445 }
446
447 public void navigationFinished( NavigationFinishedEvent arg0 )
448 {
449 }
450 } );
451 }
452 };
453 }
454 }
455
456 private final class InternalBrowserNavigationListener implements NavigationListener
457 {
458 public void navigationStarted( NavigationEvent arg0 )
459 {
460 }
461
462 public void navigationFinished( NavigationFinishedEvent arg0 )
463 {
464 if( browserRecordingMap.containsKey( BrowserComponent.this ) )
465 {
466 Map<String, RecordedRequest> map = browserRecordingMap.get( BrowserComponent.this );
467 RecordedRequest recordedRequest = map.get( arg0.getUrl() );
468 if( recordedRequest != null )
469 {
470 if( httpHtmlResponseView != null && httpHtmlResponseView.isRecordHttpTrafic() )
471 {
472 HttpTestRequest httpTestRequest = ( HttpTestRequest )( httpHtmlResponseView.getDocument()
473 .getRequest() );
474 WsdlTestCase testCase = httpTestRequest.getTestStep().getTestCase();
475 int count = testCase.getTestStepList().size();
476
477 String url2 = recordedRequest.getUrl();
478 try
479 {
480 url2 = new URL( recordedRequest.getUrl() ).getPath();
481 }
482 catch( MalformedURLException e )
483 {
484
485 }
486
487 HttpTestRequestStep newHttpStep = ( HttpTestRequestStep )testCase.addTestStep(
488 HttpRequestStepFactory.HTTPREQUEST_TYPE, "Http Test Step " + ++count + " [" + url2 + "]",
489 recordedRequest.getUrl(), recordedRequest.getMethod() );
490
491 newHttpStep.getTestRequest().setRequestHeaders( recordedRequest.getHeaders() );
492
493 if( recordedRequest.getContent() != null )
494 {
495 newHttpStep.getTestRequest().setMediaType( recordedRequest.getContentType() );
496 if( newHttpStep.getTestRequest().getMediaType().equals( CONTENT_TYPE_FORM_URLENCODED ) )
497 {
498 newHttpStep.getTestRequest().setPostQueryString( true );
499 newHttpStep.getTestRequest().setMediaType( CONTENT_TYPE_FORM_URLENCODED );
500 RestUtils.extractParamsFromQueryString( newHttpStep.getTestRequest().getParams(),
501 recordedRequest.getContent() );
502 }
503 else
504 {
505 newHttpStep.getTestRequest().setRequestContent( recordedRequest.getContent() );
506 }
507 }
508 }
509 }
510 }
511
512
513
514 }
515 }
516
517 private class BackAction extends AbstractAction
518 {
519 public BackAction()
520 {
521 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_left.png" ) );
522 putValue( Action.SHORT_DESCRIPTION, "Navigate to previous selection" );
523 }
524
525 public void actionPerformed( ActionEvent e )
526 {
527 if( !browser.canGoBack() )
528 Toolkit.getDefaultToolkit().beep();
529 else
530 browser.goBack();
531 }
532 }
533
534 private class ForwardAction extends AbstractAction
535 {
536 public ForwardAction()
537 {
538 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_right.png" ) );
539 putValue( Action.SHORT_DESCRIPTION, "Navigate to next selection" );
540 }
541
542 public void actionPerformed( ActionEvent e )
543 {
544 if( !browser.canGoForward() )
545 Toolkit.getDefaultToolkit().beep();
546 else
547 browser.goForward();
548 }
549 }
550
551 public synchronized boolean initBrowser()
552 {
553 if( browser != null || SoapUI.isJXBrowserDisabled() )
554 return false;
555
556 browser = ( MozillaBrowser )BrowserFactory.createBrowser( BrowserType.Mozilla );
557 browserMap.put( ( ( MozillaWebBrowser )browser.getPeer() ).getWebBrowser().getContentDOMWindow(), this );
558
559 if( newWindowManager == null )
560 {
561 registerHttpListener();
562
563 newWindowManager = new SoapUINewWindowManager();
564 browser.getServices().setNewWindowManager( newWindowManager );
565 browser.getServices().setPromptService( new DefaultPromptService() );
566 }
567
568
569 browser.setHttpSecurityHandler( new HttpSecurityHandler()
570 {
571 @Override
572 public HttpSecurityAction onSecurityProblem( Set<SecurityProblem> arg0 )
573 {
574 return HttpSecurityAction.CONTINUE;
575 }
576 } );
577
578 internalNavigationListener = new InternalBrowserNavigationListener();
579 browser.addNavigationListener( internalNavigationListener );
580 browser.addStatusListener( this );
581
582 browser.addNavigationListener( new NavigationAdapter()
583 {
584 @Override
585 public void navigationFinished( NavigationFinishedEvent evt )
586 {
587 if( evt.getUrl().equals( SoapUI.PUSH_PAGE_URL ) && !( NavigationStatusCode.OK == evt.getStatusCode() ) )
588 browser.navigate( SoapUI.PUSH_PAGE_ERROR_URL );
589 }
590 } );
591
592 panel.add( browser.getComponent(), BorderLayout.CENTER );
593 return true;
594 }
595
596 protected void replaceBrowser( Browser browser2 )
597 {
598
599 browserMap.remove( ( ( MozillaWebBrowser )browser.getPeer() ).getWebBrowser().getContentDOMWindow() );
600
601 browser.stop();
602 browser.removeNavigationListener( internalNavigationListener );
603 browser.removeStatusListener( this );
604 panel.remove( browser.getComponent() );
605 browser.dispose();
606
607
608 browser = ( MozillaBrowser )browser2;
609 browserMap.put( ( ( MozillaWebBrowser )browser.getPeer() ).getWebBrowser().getContentDOMWindow(), this );
610 browser.addNavigationListener( internalNavigationListener );
611 browser.addStatusListener( this );
612 panel.add( browser.getComponent(), BorderLayout.CENTER );
613 }
614
615
616
617
618
619
620
621 public void release()
622 {
623 if( browser != null )
624 {
625 disposed = true;
626 cleanup();
627 }
628
629 possibleError = false;
630 }
631
632 private synchronized void cleanup()
633 {
634 if( browser != null )
635 {
636 browserMap.remove( ( ( MozillaWebBrowser )browser.getPeer() ).getWebBrowser().getContentDOMWindow() );
637 browserRecordingMap.remove( this );
638 httpHtmlResponseView = null;
639
640 browser.stop();
641 browser.dispose();
642 browser.removeNavigationListener( internalNavigationListener );
643 browser.removeStatusListener( this );
644
645 panel.removeAll();
646 browser = null;
647 }
648 }
649
650 public void setContent( String contentAsString, String contextUri )
651 {
652 if( SoapUI.isJXBrowserDisabled() )
653 return;
654
655 if( browser == null )
656 {
657 initBrowser();
658 }
659
660 try
661 {
662 browser.setContent( contentAsString, contextUri );
663 pcs.firePropertyChange( "content", null, null );
664 }
665 catch( Throwable e )
666 {
667 e.printStackTrace();
668 }
669
670 }
671
672 public void setContent( String content )
673 {
674 if( SoapUI.isJXBrowserDisabled() )
675 return;
676
677 if( browser == null )
678 {
679 initBrowser();
680 }
681
682 browser.setContent( content );
683 pcs.firePropertyChange( "content", null, null );
684 }
685
686 public void navigate( String url, String errorPage )
687 {
688 navigate( url, null, errorPage );
689 }
690
691 public String getContent()
692 {
693 return browser == null ? null : XmlUtils.serialize( browser.getDocument() );
694 }
695
696 public String getUrl()
697 {
698 return url;
699 }
700
701 public void setUrl( String url ) throws InterruptedException, InvocationTargetException
702 {
703 navigate( url, null );
704 }
705
706 public nsISupports queryInterface( String uuid )
707 {
708 return Mozilla.queryInterface( this, uuid );
709 }
710
711 public nsISupports queryReferent( String uuid )
712 {
713 return Mozilla.queryInterface( this, uuid );
714 }
715
716 public void onLocationChange( nsIWebProgress arg0, nsIRequest arg1, nsIURI arg2 )
717 {
718 if( getUrl() != null && !getUrl().equals( "about:blank" ) )
719 {
720 if( !possibleError )
721 possibleError = true;
722 else
723 {
724 if( !showingErrorPage )
725 {
726 showErrorPage();
727 }
728 }
729 }
730 }
731
732 public void onProgressChange( nsIWebProgress arg0, nsIRequest arg1, int arg2, int arg3, int arg4, int arg5 )
733 {
734
735 }
736
737 public void onSecurityChange( nsIWebProgress arg0, nsIRequest arg1, long arg2 )
738 {
739 }
740
741 public void onStateChange( nsIWebProgress arg0, nsIRequest request, long arg2, long arg3 )
742 {
743 try
744 {
745 if( getUrl() != null && !getUrl().equals( "about:blank" ) )
746 {
747 nsIHttpChannel ch = null;
748
749 ch = ( nsIHttpChannel )request.queryInterface( nsIHttpChannel.NS_IHTTPCHANNEL_IID );
750
751 if( ch != null )
752 {
753 possibleError = false;
754 showingErrorPage = false;
755 }
756 }
757 }
758 catch( XPCOMException e )
759 {
760 if( possibleError && !showingErrorPage )
761 showErrorPage();
762 }
763
764 }
765
766 private void showErrorPage()
767 {
768 if( errorPage != null && !errorPage.equals( getUrl() ) )
769 {
770 try
771 {
772 showingErrorPage = true;
773 setUrl( errorPage );
774 }
775 catch( Throwable e )
776 {
777 e.printStackTrace();
778 }
779 }
780 }
781
782 public String getErrorPage()
783 {
784 return errorPage;
785 }
786
787 public void setErrorPage( String errorPage )
788 {
789 this.errorPage = errorPage;
790 }
791
792 public void onStatusChange( nsIWebProgress arg0, nsIRequest arg1, long arg2, String arg3 )
793 {
794 try
795 {
796 if( getUrl() != null && !getUrl().equals( "about:blank" ) )
797 {
798 nsIHttpChannel ch = null;
799
800 ch = ( nsIHttpChannel )arg1.queryInterface( nsIHttpChannel.NS_IHTTPCHANNEL_IID );
801
802 if( ch != null )
803 {
804 possibleError = false;
805 showingErrorPage = false;
806 }
807 }
808 }
809 catch( XPCOMException e )
810 {
811 if( possibleError && !showingErrorPage )
812 showErrorPage();
813 }
814 }
815
816 public void statusChanged( StatusChangedEvent event )
817 {
818 if( statusLabel != null )
819 {
820 statusLabel.setText( event.getStatusText() );
821 }
822 }
823
824 public boolean isBrowserInitialised()
825 {
826 return browser != null;
827 }
828
829 /***
830 * Setups proxy configuration
831 */
832
833 private static boolean proxyAuthenticationInitialized = false;
834
835 public synchronized static void updateProxy( boolean proxyEnabled )
836 {
837 if( SoapUI.isJXBrowserDisabled() )
838 return;
839
840 initialize();
841
842 ProxyConfiguration proxyConf = Services.getProxyConfiguration();
843 if( proxyConf == null )
844 return;
845
846 proxyConf.setType( ProxyConfiguration.MANUAL );
847
848 if( !proxyAuthenticationInitialized )
849 {
850 proxyConf.setPoxyAuthenticationHandler( ProxyServerType.HTTP, new PoxyAuthenticationHandler()
851 {
852 public ProxyServerAuthInfo authenticationRequired()
853 {
854 Settings settings = SoapUI.getSettings();
855 PropertyExpansionContext context = null;
856
857 String proxyUsername = PropertyExpander.expandProperties( context,
858 settings.getString( ProxySettings.USERNAME, null ) );
859 String proxyPassword = PropertyExpander.expandProperties( context,
860 settings.getString( ProxySettings.PASSWORD, null ) );
861
862 return new ProxyServerAuthInfo( proxyUsername, proxyPassword );
863 }
864 } );
865
866 proxyAuthenticationInitialized = true;
867 }
868
869 if( proxyEnabled )
870 {
871 Settings settings = SoapUI.getSettings();
872 PropertyExpansionContext context = null;
873
874
875 String proxyHost = System.getProperty( "http.proxyHost" );
876 String proxyPort = System.getProperty( "http.proxyPort" );
877
878 if( proxyHost == null )
879 proxyHost = PropertyExpander.expandProperties( context, settings.getString( ProxySettings.HOST, "" ) );
880
881 if( proxyPort == null )
882 proxyPort = PropertyExpander.expandProperties( context, settings.getString( ProxySettings.PORT, "" ) );
883
884 proxyConf.setHttpHost( proxyHost );
885 proxyConf.setHttpPort( Integer.parseInt( proxyPort ) );
886
887 String[] excludes = PropertyExpander.expandProperties( context,
888 settings.getString( ProxySettings.EXCLUDES, "" ) ).split( "," );
889 for( String url : excludes )
890 {
891 proxyConf.setSkipProxyFor( url );
892 }
893 }
894 else
895 {
896 proxyConf.setHttpHost( "" );
897 }
898
899 }
900
901 private PropertyChangeSupport pcs = new PropertyChangeSupport( this );
902
903 public void addPropertyChangeListener( PropertyChangeListener pcl )
904 {
905 pcs.addPropertyChangeListener( pcl );
906 }
907
908 public void rempvePropertyChangeListener( PropertyChangeListener pcl )
909 {
910 pcs.removePropertyChangeListener( pcl );
911 }
912
913 /***
914 * Called after a HTTP response from the server is received.
915 *
916 * @see http://developer.mozilla.org/en/Observer_Notifications
917 */
918 public static final String EVENT_HTTP_ON_MODIFY_REQUEST = "http-on-modify-request";
919
920 public void registerHttpListener()
921 {
922 Xpcom.invokeLater( new RecordingHttpListener() );
923 }
924
925 /***
926 * Converts an object implementing the nsIURI interface into a human readable
927 * URI.
928 *
929 * @param uri
930 * nsIURI object to convert
931 * @return String URI result string
932 */
933 public static String dumpUri( nsIURI uri )
934 {
935 if( uri == null )
936 {
937 return "";
938 }
939
940 return ( ( uri.getUsername() == null || "".equals( uri.getUsername() ) ) ? "" : uri.getUsername() + ":"
941 + uri.getUserPass() )
942 + uri.getScheme()
943 + "://"
944 + uri.getHost()
945 + ( ( uri.getPort() == -1 ) ? "" : ":" + uri.getPort() )
946 + uri.getPath();
947 }
948
949 private static class RecordedRequest
950 {
951 private String url;
952 private String contentType;
953 private StringToStringsMap headers;
954 private String method;
955 private String content;
956
957 public RecordedRequest( String url, String method )
958 {
959 this.url = url;
960 this.method = method;
961 }
962
963 public void setContentType( String contentType )
964 {
965 this.contentType = contentType;
966 }
967
968 public void setHeaders( StringToStringsMap headersMap )
969 {
970 headers = headersMap;
971 }
972
973 public void setContent( String requestBody )
974 {
975 content = requestBody;
976 }
977
978 public String getUrl()
979 {
980 return url;
981 }
982
983 public String getContentType()
984 {
985 return contentType;
986 }
987
988 public StringToStringsMap getHeaders()
989 {
990 return headers;
991 }
992
993 public String getMethod()
994 {
995 return method;
996 }
997
998 public String getContent()
999 {
1000 return content;
1001 }
1002 }
1003
1004 public void navigate( String url, String postData, String errorPage )
1005 {
1006 if( SoapUI.isJXBrowserDisabled() )
1007 return;
1008
1009 if( errorPage != null )
1010 setErrorPage( errorPage );
1011
1012 this.url = url;
1013
1014 if( browser == null )
1015 {
1016 initBrowser();
1017 }
1018
1019 if( postData != null && postData.length() > 0 )
1020 {
1021 browser.navigate( url, postData );
1022 }
1023 else
1024 {
1025 browser.navigate( url );
1026 }
1027
1028 if( showingErrorPage )
1029 showingErrorPage = false;
1030 }
1031
1032 }