| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed 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.intellij.ide.browsers; |
| |
| import com.intellij.openapi.components.*; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.*; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.util.SmartList; |
| import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; |
| import com.intellij.util.xmlb.XmlSerializer; |
| import org.jdom.Element; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| @State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/web-browsers.xml")}) |
| public class WebBrowserManager extends SimpleModificationTracker implements PersistentStateComponent<Element> { |
| private static final Logger LOG = Logger.getInstance(WebBrowserManager.class); |
| |
| // default standard browser ID must be constant across all IDE versions on all machines for all users |
| private static final UUID PREDEFINED_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3"); |
| // public, but only internal use |
| public static final UUID PREDEFINED_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8"); |
| private static final UUID PREDEFINED_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186"); |
| private static final UUID PREDEFINED_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776"); |
| private static final UUID PREDEFINED_YANDEX_ID = UUID.fromString("B1B2EC2C-20BD-4EE2-89C4-616DB004BCD4"); |
| private static final UUID PREDEFINED_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0"); |
| |
| private static final List<ConfigurableWebBrowser> PREDEFINED_BROWSERS = Arrays.asList( |
| new ConfigurableWebBrowser(PREDEFINED_CHROME_ID, BrowserFamily.CHROME), |
| new ConfigurableWebBrowser(PREDEFINED_FIREFOX_ID, BrowserFamily.FIREFOX), |
| new ConfigurableWebBrowser(PREDEFINED_SAFARI_ID, BrowserFamily.SAFARI), |
| new ConfigurableWebBrowser(PREDEFINED_OPERA_ID, BrowserFamily.OPERA), |
| new ConfigurableWebBrowser(PREDEFINED_YANDEX_ID, BrowserFamily.CHROME, "Yandex", SystemInfo.isWindows ? "browser" : (SystemInfo.isMac ? "Yandex" : "yandex"), false, BrowserFamily.CHROME.createBrowserSpecificSettings()), |
| new ConfigurableWebBrowser(PREDEFINED_EXPLORER_ID, BrowserFamily.EXPLORER) |
| ); |
| |
| private List<ConfigurableWebBrowser> browsers; |
| |
| DefaultBrowserPolicy defaultBrowserPolicy = DefaultBrowserPolicy.SYSTEM; |
| |
| public WebBrowserManager() { |
| browsers = new ArrayList<ConfigurableWebBrowser>(PREDEFINED_BROWSERS); |
| } |
| |
| public static WebBrowserManager getInstance() { |
| return ServiceManager.getService(WebBrowserManager.class); |
| } |
| |
| public static boolean isYandexBrowser(@NotNull WebBrowser browser) { |
| return browser.getFamily().equals(BrowserFamily.CHROME) && (browser.getId().equals(PREDEFINED_YANDEX_ID) || checkNameAndPath("Yandex", browser)); |
| } |
| |
| public static boolean isDartium(@NotNull WebBrowser browser) { |
| return browser.getFamily().equals(BrowserFamily.CHROME) && checkNameAndPath("Dartium", browser); |
| } |
| |
| static boolean checkNameAndPath(@NotNull String what, @NotNull WebBrowser browser) { |
| if (StringUtil.containsIgnoreCase(browser.getName(), what)) { |
| return true; |
| } |
| String path = browser.getPath(); |
| if (path != null) { |
| int index = path.lastIndexOf('/'); |
| return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what); |
| } |
| return false; |
| } |
| |
| boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) { |
| UUID id = browser.getId(); |
| for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) { |
| if (id.equals(predefinedBrowser.getId())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @NotNull |
| public DefaultBrowserPolicy getDefaultBrowserPolicy() { |
| return defaultBrowserPolicy; |
| } |
| |
| @Override |
| public Element getState() { |
| Element state = new Element("state"); |
| if (defaultBrowserPolicy != DefaultBrowserPolicy.SYSTEM) { |
| state.setAttribute("default", defaultBrowserPolicy.name().toLowerCase(Locale.ENGLISH)); |
| } |
| |
| for (ConfigurableWebBrowser browser : browsers) { |
| Element entry = new Element("browser"); |
| entry.setAttribute("id", browser.getId().toString()); |
| entry.setAttribute("name", browser.getName()); |
| entry.setAttribute("family", browser.getFamily().name()); |
| |
| String path = browser.getPath(); |
| if (path != null && !path.equals(browser.getFamily().getExecutionPath())) { |
| entry.setAttribute("path", path); |
| } |
| |
| if (!browser.isActive()) { |
| entry.setAttribute("active", "false"); |
| } |
| |
| BrowserSpecificSettings specificSettings = browser.getSpecificSettings(); |
| if (specificSettings != null) { |
| Element settingsElement = new Element("settings"); |
| XmlSerializer.serializeInto(specificSettings, settingsElement, new SkipDefaultValuesSerializationFilters()); |
| if (!JDOMUtil.isEmpty(settingsElement)) { |
| entry.addContent(settingsElement); |
| } |
| } |
| state.addContent(entry); |
| } |
| return state; |
| } |
| |
| @Nullable |
| private static BrowserFamily readFamily(String value) { |
| try { |
| return BrowserFamily.valueOf(value); |
| } |
| catch (RuntimeException e) { |
| LOG.warn(e); |
| |
| for (BrowserFamily family : BrowserFamily.values()) { |
| if (family.getName().equalsIgnoreCase(value)) { |
| return family; |
| } |
| } |
| |
| return null; |
| } |
| } |
| |
| @Nullable |
| private static UUID readId(String value, @NotNull BrowserFamily family, @NotNull List<ConfigurableWebBrowser> existingBrowsers) { |
| if (StringUtil.isEmpty(value)) { |
| UUID id; |
| switch (family) { |
| case CHROME: |
| id = PREDEFINED_CHROME_ID; |
| break; |
| case EXPLORER: |
| id = PREDEFINED_EXPLORER_ID; |
| break; |
| case FIREFOX: |
| id = PREDEFINED_FIREFOX_ID; |
| break; |
| case OPERA: |
| id = PREDEFINED_OPERA_ID; |
| break; |
| case SAFARI: |
| id = PREDEFINED_SAFARI_ID; |
| break; |
| |
| default: |
| return null; |
| } |
| |
| for (ConfigurableWebBrowser browser : existingBrowsers) { |
| if (browser.getId() == id) { |
| // duplicated entry, skip |
| return null; |
| } |
| } |
| return id; |
| } |
| else { |
| try { |
| return UUID.fromString(value); |
| } |
| catch (Exception e) { |
| LOG.warn(e); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public void loadState(Element element) { |
| String defaultValue = element.getAttributeValue("default"); |
| if (!StringUtil.isEmpty(defaultValue)) { |
| try { |
| defaultBrowserPolicy = DefaultBrowserPolicy.valueOf(defaultValue.toUpperCase(Locale.ENGLISH)); |
| } |
| catch (IllegalArgumentException e) { |
| LOG.warn(e); |
| } |
| } |
| |
| List<ConfigurableWebBrowser> list = new ArrayList<ConfigurableWebBrowser>(); |
| for (Element child : element.getChildren("browser")) { |
| BrowserFamily family = readFamily(child.getAttributeValue("family")); |
| if (family == null) { |
| continue; |
| } |
| |
| UUID id = readId(child.getAttributeValue("id"), family, list); |
| if (id == null) { |
| continue; |
| } |
| |
| Element settingsElement = child.getChild("settings"); |
| BrowserSpecificSettings specificSettings = family.createBrowserSpecificSettings(); |
| if (specificSettings != null && settingsElement != null) { |
| try { |
| XmlSerializer.deserializeInto(specificSettings, settingsElement); |
| } |
| catch (Exception e) { |
| LOG.warn(e); |
| } |
| } |
| |
| String activeValue = child.getAttributeValue("active"); |
| |
| String path = StringUtil.nullize(child.getAttributeValue("path"), true); |
| if (path == null) { |
| path = family.getExecutionPath(); |
| } |
| |
| list.add(new ConfigurableWebBrowser(id, |
| family, |
| StringUtil.notNullize(child.getAttributeValue("name"), family.getName()), |
| path, |
| activeValue == null || Boolean.parseBoolean(activeValue), |
| specificSettings)); |
| } |
| |
| // add removed/new predefined browsers |
| int n = list.size(); |
| pb: for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) { |
| //noinspection ForLoopReplaceableByForEach |
| for (int i = 0; i < n; i++) { |
| if (list.get(i).getId().equals(predefinedBrowser.getId())) { |
| continue pb; |
| } |
| } |
| list.add(predefinedBrowser); |
| } |
| |
| setList(list); |
| } |
| |
| @NotNull |
| public List<WebBrowser> getBrowsers() { |
| return Collections.<WebBrowser>unmodifiableList(browsers); |
| } |
| |
| @NotNull |
| List<ConfigurableWebBrowser> getList() { |
| return browsers; |
| } |
| |
| void setList(@NotNull List<ConfigurableWebBrowser> value) { |
| browsers = value; |
| incModificationCount(); |
| } |
| |
| @NotNull |
| public List<WebBrowser> getActiveBrowsers() { |
| return getBrowsers(Conditions.<WebBrowser>alwaysTrue(), true); |
| } |
| |
| @NotNull |
| public List<WebBrowser> getBrowsers(@NotNull Condition<WebBrowser> condition) { |
| return getBrowsers(condition, true); |
| } |
| |
| @NotNull |
| public List<WebBrowser> getBrowsers(@NotNull Condition<WebBrowser> condition, boolean onlyActive) { |
| List<WebBrowser> result = new SmartList<WebBrowser>(); |
| for (ConfigurableWebBrowser browser : browsers) { |
| if ((!onlyActive || browser.isActive()) && condition.value(browser)) { |
| result.add(browser); |
| } |
| } |
| return result; |
| } |
| |
| public void setBrowserSpecificSettings(@NotNull WebBrowser browser, @NotNull BrowserSpecificSettings specificSettings) { |
| ((ConfigurableWebBrowser)browser).setSpecificSettings(specificSettings); |
| } |
| |
| public void setBrowserPath(@NotNull WebBrowser browser, @Nullable String path, boolean isActive) { |
| ((ConfigurableWebBrowser)browser).setPath(path); |
| ((ConfigurableWebBrowser)browser).setActive(isActive); |
| } |
| |
| public WebBrowser addBrowser(final @NotNull UUID id, |
| final @NotNull BrowserFamily family, |
| final @NotNull String name, |
| final @Nullable String path, |
| final boolean active, |
| final BrowserSpecificSettings specificSettings) { |
| final ConfigurableWebBrowser browser = new ConfigurableWebBrowser(id, family, name, path, active, specificSettings); |
| browsers.add(browser); |
| incModificationCount(); |
| return browser; |
| } |
| |
| @Nullable |
| private static UUID parseUuid(@NotNull String id) { |
| if (id.indexOf('-') == -1) { |
| return null; |
| } |
| |
| try { |
| return UUID.fromString(id); |
| } |
| catch (IllegalArgumentException ignored) { |
| return null; |
| } |
| } |
| |
| @Nullable |
| /** |
| * @param idOrFamilyName UUID or, due to backward compatibility, browser family name or JS debugger engine ID |
| */ |
| public WebBrowser findBrowserById(@Nullable String idOrFamilyName) { |
| if (StringUtil.isEmpty(idOrFamilyName)) { |
| return null; |
| } |
| |
| UUID id = parseUuid(idOrFamilyName); |
| if (id == null) { |
| for (ConfigurableWebBrowser browser : browsers) { |
| if (browser.getFamily().name().equalsIgnoreCase(idOrFamilyName) || |
| browser.getFamily().getName().equalsIgnoreCase(idOrFamilyName)) { |
| return browser; |
| } |
| } |
| return null; |
| } |
| |
| for (ConfigurableWebBrowser browser : browsers) { |
| if (browser.getId().equals(id)) { |
| return browser; |
| } |
| } |
| return null; |
| } |
| |
| @NotNull |
| public WebBrowser getFirstBrowser(@NotNull BrowserFamily family) { |
| for (ConfigurableWebBrowser browser : browsers) { |
| if (browser.isActive() && family.equals(browser.getFamily())) { |
| return browser; |
| } |
| } |
| |
| for (ConfigurableWebBrowser browser : browsers) { |
| if (family.equals(browser.getFamily())) { |
| return browser; |
| } |
| } |
| |
| throw new IllegalStateException("Must be at least one browser per family"); |
| } |
| |
| public boolean isActive(@NotNull WebBrowser browser) { |
| return !(browser instanceof ConfigurableWebBrowser) || ((ConfigurableWebBrowser)browser).isActive(); |
| } |
| |
| @Nullable |
| public WebBrowser getFirstActiveBrowser() { |
| for (ConfigurableWebBrowser browser : browsers) { |
| if (browser.isActive() && browser.getPath() != null) { |
| return browser; |
| } |
| } |
| return null; |
| } |
| } |