com.googlecode.osde.internal.profiling.Profile.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.osde.internal.profiling.Profile.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package com.googlecode.osde.internal.profiling;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import static org.apache.commons.io.FileUtils.forceMkdir;
import static org.apache.commons.io.IOUtils.closeQuietly;
import static org.apache.commons.io.IOUtils.copy;

/**
 * A Firefox user profile. This is a simplified version of
 * <code>org.openqa.selenium.firefox.FirefoxProfile</code>.
 *
 * @author Dolphin Chi-Ngai Wan
 */
class Profile {
    private final File extensionsDir;
    private final File userPreferenceFile;
    private final File profileDir;
    final String name;

    /**
     * Constructs a firefox profile from an existing, physical profile folder.
     */
    Profile(File profileDir, String name) {
        this.name = name;
        this.profileDir = profileDir;
        this.extensionsDir = new File(profileDir, "extensions");
        this.userPreferenceFile = new File(profileDir, "user.js");

        if (!profileDir.exists()) {
            throw new ProfilingException(
                    MessageFormat.format("Profile directory does not exist: {0}", profileDir.getAbsolutePath()));
        }
    }

    /**
     * Returns true if there is an Firefox instance running with this profile.
     * See http://kb.mozillazine.org/Profile_in_use.
     */
    boolean isRunning() {
        Platform platform = Platform.getCurrent();

        switch (platform) {
        case MAC:
            return new File(profileDir, ".parentlock").exists();
        case XP:
        case VISTA:
        case WINDOWS:
            return new File(profileDir, "parent.lock").exists();
        case LINUX:
        case UNIX:
            return new File(profileDir, ".parentlock").exists() && new File(profileDir, "lock").exists();
        }

        return false;
    }

    void installPageSpeed() throws IOException {
        // TODO: collect beacons in port 8900 in the future.
        installPageSpeed(null);
    }

    void installPageSpeed(String beaconUrl) throws IOException {
        addExtension("firebug-1.4.5-fx.xpi", "firebug@software.joehewitt.com");
        addExtension("pagespeed-1.5b.xpi", "{e3f6c2cc-d8db-498c-af6c-499fb211db97}");
        deleteExtensionsCacheIfItExists();
        saveUserPrefs(beaconUrl);
    }

    /**
     * Installs a Firefox extension into this user profile.
     *
     * @param classpath The classpath of extension XPI file.
     * @param id The extension id.
     */
    private void addExtension(String classpath, String id) throws IOException {
        // Firefox looks up extensions in 
        // <profiledir>/<extensions>/<extension-id>.
        File extensionDirectory = new File(extensionsDir, id);
        if (extensionDirectory.exists() && extensionDirectory.isDirectory()) {
            // we assume the extension is already installed and will not do it
            // again.
            return;
        }

        InputStream resource = Profile.class.getResourceAsStream(classpath);
        if (resource == null && !classpath.startsWith("/")) {
            resource = Profile.class.getResourceAsStream("/" + classpath);
        }

        if (resource == null) {
            throw new FileNotFoundException("Cannot locate resource with name: " + classpath);
        }

        forceMkdir(extensionDirectory);
        unzip(resource, extensionDirectory);
    }

    private Map<String, String> readExistingPrefs(File userPrefs) {
        Map<String, String> prefs = new HashMap<String, String>();

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(userPrefs));
            String line = reader.readLine();
            while (line != null) {
                if (!line.startsWith("user_pref(\"")) {
                    line = reader.readLine();
                    continue;
                }
                line = line.substring("user_pref(\"".length());
                line = line.substring(0, line.length() - ");".length());
                String[] parts = line.split(",");
                parts[0] = parts[0].substring(0, parts[0].length() - 1);
                prefs.put(parts[0].trim(), parts[1].trim());

                line = reader.readLine();
            }
        } catch (IOException e) {
            throw new ProfilingException(e);
        } finally {
            closeQuietly(reader);
        }

        return prefs;
    }

    private void saveUserPrefs(String beaconUrl) {
        Map<String, String> prefs = new HashMap<String, String>();

        if (userPreferenceFile.exists()) {
            prefs = readExistingPrefs(userPreferenceFile);
            if (!userPreferenceFile.delete()) {
                throw new ProfilingException("Cannot delete existing user preferences");
            }
        }

        // Normal settings to facilitate testing
        prefs.put("app.update.auto", "false");
        prefs.put("app.update.enabled", "false");
        prefs.put("browser.download.manager.showWhenStarting", "false");
        prefs.put("browser.EULA.override", "true");
        prefs.put("browser.EULA.3.accepted", "true");
        prefs.put("browser.link.open_external", "2");
        prefs.put("browser.link.open_newwindow", "2");
        prefs.put("browser.safebrowsing.enabled", "false");
        prefs.put("browser.search.update", "false");
        prefs.put("browser.search.suggest.enabled", "false");
        prefs.put("browser.sessionstore.resume_from_crash", "false");
        prefs.put("browser.shell.checkDefaultBrowser", "false");
        prefs.put("browser.startup.page", "0");
        prefs.put("browser.tabs.warnOnClose", "false");
        prefs.put("browser.tabs.warnOnOpen", "false");
        prefs.put("dom.disable_open_during_load", "false");
        prefs.put("extensions.update.enabled", "false");
        prefs.put("extensions.update.notifyUser", "false");
        prefs.put("security.fileuri.origin_policy", "3");
        prefs.put("security.fileuri.strict_origin_policy", "false");
        prefs.put("security.warn_entering_secure", "false");
        prefs.put("security.warn_submit_insecure", "false");
        prefs.put("security.warn_entering_secure.show_once", "false");
        prefs.put("security.warn_entering_weak", "false");
        prefs.put("security.warn_entering_weak.show_once", "false");
        prefs.put("security.warn_leaving_secure", "false");
        prefs.put("security.warn_leaving_secure.show_once", "false");
        prefs.put("security.warn_submit_insecure", "false");
        prefs.put("security.warn_viewing_mixed", "false");
        prefs.put("security.warn_viewing_mixed.show_once", "false");
        prefs.put("signon.rememberSignons", "false");
        prefs.put("startup.homepage_welcome_url", "\"about:blank\"");

        prefs.put("extensions.firebug.allPagesActivation", "\"on\"");
        prefs.put("extensions.firebug.defaultPanelName", "\"pagespeed\"");
        prefs.put("extensions.PageSpeed.autorun", "true");

        if (beaconUrl != null) {
            prefs.put("extensions.PageSpeed.beacon.full_results.url", "\"" + beaconUrl + "\"");
            prefs.put("extensions.PageSpeed.beacon.full_results.enabled", "true");
            prefs.put("extensions.PageSpeed.beacon.full_results.autorun", "true");
            prefs.put("extensions.PageSpeed.quit_after_scoring", "true");
        }

        writeNewPrefs(prefs);
    }

    private void deleteExtensionsCacheIfItExists() {
        File cacheFile = new File(extensionsDir, "../extensions.cache");
        if (cacheFile.exists()) {
            cacheFile.delete();
        }
    }

    private void writeNewPrefs(Map<String, String> prefs) {
        Writer writer = null;
        try {
            writer = new FileWriter(userPreferenceFile);
            for (Map.Entry<String, String> entry : prefs.entrySet()) {
                writer.append(String.format("user_pref(\"%s\", %s);\n", entry.getKey(), entry.getValue()));
            }
        } catch (IOException e) {
            throw new ProfilingException(e);
        } finally {
            closeQuietly(writer);
        }
    }

    /**
     * Unzips a zip content into a physical folder.
     *
     * @return The newly-created folder with the unzipped content.
     */
    private static File unzip(InputStream resource, File output) throws IOException {
        // Allocate a 16K buffer to read the XPI file faster.
        ZipInputStream zipStream = new ZipInputStream(new BufferedInputStream(resource, 16 * 1024));
        ZipEntry entry = zipStream.getNextEntry();
        while (entry != null) {
            final File target = new File(output, entry.getName());
            if (entry.isDirectory()) {
                forceMkdir(target);
            } else {
                unzipFile(target, zipStream);
            }
            entry = zipStream.getNextEntry();
        }

        return output;
    }

    private static void unzipFile(File target, InputStream zipStream) throws IOException {
        FileOutputStream out = null;
        try {
            forceMkdir(target.getParentFile());
            out = new FileOutputStream(target);
            copy(zipStream, out);
        } finally {
            closeQuietly(out);
        }
    }
}