Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
158 views
in Technique[技术] by (71.8m points)

java - Launch Firefox and Wait until it is Closed

Question

I want to start the Firefox web browser as process to visit a specific website, then wait until it is closed.

A special situation is that the browser may already be open and running, as the user may have visited some website already.

In that case, the browser would probably open a new tab in an existing window and the newly launched process will be terminated immediately. This should not confuse my waiting process: Either, I want a new browser window (if that can somehow be enforced, maybe via command line arguments) and wait until that is closed, or keep the existing browser window and wait until all the tabs resulting from my process are closed.

Environment

I think it doesn't matter, but my programming environment is Java and you can assume that I know the path of the browser.

Example

The only browser for which I can obtain the expected behavior is Internet Explorer (sigh.). Here, I need to basically create a new batch script in a temp folder with something like

start /WAIT "" "C:Program FilesInternet Exploreriexplore.exe" -noframemerging http://www.test.com/

I then run the batch script instead of directly the browser and delete it once I am finished with waiting.

Intended Process

To make the intended process clearer:

  1. My program starts.
  2. My program launches the Firefox browser as separate process and provides an URL to visit as argument to that process.
  3. The Firefox browser runs asynchronously, as a new process, and visits the provided URL. So far, this is easy.
  4. After launching the new process (the Firefox browser), my own program should wait for the said process to terminate. This is the hard part, as
    1. Many modern browsers start multiple processes. I would need to wait for all of them.
    2. Many modern browsers may somehow "detach" themselves from the process that I launched. Sorry, I don't know a better word, what I mean is: I start a process which then starts another process and terminates immediately while the other process keeps running. If I wait for the browser process originally started by my program, the waiting will be finished while the browser is still open.
    3. A special case of the above is tabbed browsing as realized in many browsers: If the browser is already open (in a separate process started by the user) when I launch it, my newly started browser process may simple communicate the URL to visit to the existing process and terminate. The user is still on my provided URL while my program thinks she has closed the browser. This issue can maybe be forbidden by specifying a special command line argument, like noframemerging for the IE.
  5. Once the browser has terminated or all tabs related to the URL I provide have been closed, my program will cease to wait and instead continue doing its business.

The use case is that I have a web application which can either run locally or on a server. If it is run locally, it launches a web server, then opens the browser to visit the entry page. Once the browser is closed, that web application should shut down as well. This works reliable for Internet Explorer, for all other cases, the user has to close the browser and then, explicitly, the web application. Thus, if I could wait reliably for Firefox to finish, this would make the user experience much better.

Solution Preferences:

Solutions are prefered in the following order

  1. Anything which ships with the pure Java JRE. This includes special command line arguments to the browser.
  2. Things that require me to, e.g., create a batch script (such as in the IE case.)
  3. Anything that requires 3rd party open source libraries.
  4. Anything that requires 3rth party closed source libraries.

Any platform independent answer (working both Windows and Linux) is prefered over platform-dependent ones.

Reason: In the ideal case, I would like to know what exactly is done and include it into my own code. As I want to support different browsers (see "PS" below), I would like to avoid having to include one library per browser. Finally, I cannot use commercial or closed source libraries, but if no better answer turns up, of course, I will honor any working solution with an accept. I will accept the first (reasonably nice) working answer of type "1". If answers of lower preference turn up, I will wait a few days before accepting the best one among them.

PS

I will launch a couple of similar questions for other browsers. Since I believe that browsers are quite different in the command line arguments they digest, the way the launch threads and sub-processes, I think this makes sense.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is a sample program that may somehow manages to demonstrate the capability of a selenium library to fulfill what you want. You need to download the selenium library and set it to your IDE first before you can run this program.

The program allows you to click a button. Then the firefox browser automatically opens and launch a website in a few seconds. Please wait while the website is loading. After that you may close the Firefox browser. The program shall also automatically close after 2 seconds.

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.net.ConnectException;
import javax.swing.*;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class AnotherTest extends JFrame {

    WebDriver driver;
    JLabel label;

    public AnotherTest() {
        super("Test");
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width - 400) / 2, (screenSize.height - 100) / 2, 400, 100);
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        addWindowListener(new java.awt.event.WindowAdapter() {

            public void windowClosing(java.awt.event.WindowEvent evt) {
                quitApplication();
            }
        });

        JButton jButton1 = new javax.swing.JButton();

        label = new JLabel("");
        JPanel panel = new JPanel(new FlowLayout());
        panel.add(jButton1);

        add(panel, BorderLayout.CENTER);
        add(label, BorderLayout.SOUTH);


        jButton1.setText("Open Microsoft");

        jButton1.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {

                label.setText("Loading browser. Please wait..");

                java.util.Timer t = new java.util.Timer();
                t.schedule(new java.util.TimerTask() {

                    @Override
                    public void run() {
                        openBrowserAndWait();
                    }
                }, 10);
            }
        });

    }

    private void openBrowserAndWait() {
        driver = new FirefoxDriver();
        String baseUrl = "https://www.microsoft.com";
        driver.get(baseUrl);

        java.util.Timer monitorTimer = new java.util.Timer();
        monitorTimer.schedule(new java.util.TimerTask() {

            @Override
            public void run() {
                while (true) {
                    checkDriver();
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }, 10);
    }

    private void checkDriver() {
        if (driver == null) {
            return;
        }

        boolean shouldExit = false;

        try {
            label.setText(driver.getTitle());
        } catch (NoSuchWindowException e) {
            System.out.println("Browser has been closed. Exiting Program");
            shouldExit = true;
        } catch (Exception e) {
            System.out.println("Browser has been closed. Exiting Program");
            shouldExit = true;
        }

        if (shouldExit) {
            this.quitApplication();
        }
    }

    private void quitApplication() {
        // attempt to close gracefully
        if (driver != null) {
            try {
                driver.quit();
            } catch (Exception e) {
            }
        }

        System.exit(0);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new AnotherTest().setVisible(true);
            }
        });
    }
}

Selenium is primarily used for testing automation of web applications. It can directly open browsers and read the html contents in it. See http://www.seleniumhq.org/ for additional information.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...