1 /*******************************************************************************
2  * Copyright (c) 2003, 2016 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - Initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.internal.browser;
15 
16 import java.beans.PropertyChangeListener;
17 import java.net.MalformedURLException;
18 import java.net.URL;
19 
20 import org.eclipse.core.runtime.Adapters;
21 import org.eclipse.core.runtime.IPath;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.jface.action.IAction;
24 import org.eclipse.jface.resource.ImageDescriptor;
25 import org.eclipse.osgi.util.NLS;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Display;
28 import org.eclipse.ui.IActionBars;
29 import org.eclipse.ui.IEditorDescriptor;
30 import org.eclipse.ui.IEditorInput;
31 import org.eclipse.ui.IEditorPart;
32 import org.eclipse.ui.IEditorReference;
33 import org.eclipse.ui.IEditorRegistry;
34 import org.eclipse.ui.IEditorSite;
35 import org.eclipse.ui.IPathEditorInput;
36 import org.eclipse.ui.IWorkbenchPage;
37 import org.eclipse.ui.IWorkbenchWindow;
38 import org.eclipse.ui.PartInitException;
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
41 import org.eclipse.ui.part.EditorPart;
42 /**
43  * An integrated Web browser, defined as an editor to make
44  * better use of the desktop.
45  */
46 public class WebBrowserEditor extends EditorPart implements IBrowserViewerContainer {
47 	public static final String WEB_BROWSER_EDITOR_ID = "org.eclipse.ui.browser.editor"; //$NON-NLS-1$
48 
49 	protected BrowserViewer webBrowser;
50 	protected String initialURL;
51 	protected ImageDescriptor imageDescriptor;
52 
53 	protected TextAction cutAction;
54 	protected TextAction copyAction;
55 	protected TextAction pasteAction;
56 
57 	private boolean disposed;
58 	private boolean lockName;
59 
60 	/**
61 	 * WebBrowserEditor constructor comment.
62 	 */
WebBrowserEditor()63 	public WebBrowserEditor() {
64 		super();
65 	}
66 
67 	@Override
createPartControl(Composite parent)68 	public void createPartControl(Composite parent) {
69 		WebBrowserEditorInput input = getWebBrowserEditorInput();
70 
71 		int style = 0;
72 		if (input == null || input.isLocationBarLocal()) {
73 			style += BrowserViewer.LOCATION_BAR;
74 		}
75 		if (input == null || input.isToolbarLocal()) {
76 			style += BrowserViewer.BUTTON_BAR;
77 		}
78 		webBrowser = new BrowserViewer(parent, style);
79 
80 		webBrowser.setURL(initialURL);
81 		webBrowser.setContainer(this);
82 
83 		ImageResourceManager manager = new ImageResourceManager(webBrowser);
84 		setTitleImage(manager.getImage(imageDescriptor));
85 
86 		if (input == null || input.isLocationBarLocal()) {
87 			cutAction = new TextAction(webBrowser, TextAction.CUT);
88 			copyAction = new TextAction(webBrowser, TextAction.COPY);
89 			pasteAction = new TextAction(webBrowser, TextAction.PASTE);
90 		}
91 
92 		if (!lockName) {
93 			PropertyChangeListener propertyChangeListener = event -> {
94 				if (BrowserViewer.PROPERTY_TITLE.equals(event.getPropertyName())) {
95 					setPartName((String) event.getNewValue());
96 				}
97 			};
98 			webBrowser.addPropertyChangeListener(propertyChangeListener);
99 		}
100 	}
101 
102 	@Override
dispose()103 	public void dispose() {
104 		super.dispose();
105 		// mark this instance as disposed to avoid stale references
106 		disposed = true;
107 	}
108 
isDisposed()109 	public boolean isDisposed() {
110 		return disposed;
111 	}
112 
113 	@Override
doSave(IProgressMonitor monitor)114 	public void doSave(IProgressMonitor monitor) {
115 		// do nothing
116 	}
117 
118 	@Override
doSaveAs()119 	public void doSaveAs() {
120 		// do nothing
121 	}
122 
123 	/**
124 	 * Returns the copy action.
125 	 *
126 	 * @return org.eclipse.jface.action.IAction
127 	 */
getCopyAction()128 	public IAction getCopyAction() {
129 		return copyAction;
130 	}
131 
132 	/**
133 	 * Returns the cut action.
134 	 *
135 	 * @return org.eclipse.jface.action.IAction
136 	 */
getCutAction()137 	public IAction getCutAction() {
138 		return cutAction;
139 	}
140 
141 	/**
142 	 * Returns the web editor input, if available. If the input was of
143 	 * another type, <code>null</code> is returned.
144 	 *
145 	 * @return org.eclipse.ui.internal.browser.IWebBrowserEditorInput
146 	 */
getWebBrowserEditorInput()147 	protected WebBrowserEditorInput getWebBrowserEditorInput() {
148 		IEditorInput input = getEditorInput();
149 		if (input instanceof WebBrowserEditorInput)
150 			return (WebBrowserEditorInput) input;
151 		return null;
152 	}
153 
154 	/**
155 	 * Returns the paste action.
156 	 *
157 	 * @return org.eclipse.jface.action.IAction
158 	 */
getPasteAction()159 	public IAction getPasteAction() {
160 		return pasteAction;
161 	}
162 
163 	@Override
init(IEditorSite site, IEditorInput input)164 	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
165 		Trace.trace(Trace.FINEST, "Opening browser: " + input); //$NON-NLS-1$
166 		if (input instanceof IPathEditorInput) {
167 			IPathEditorInput pei = (IPathEditorInput) input;
168 			final IPath path= pei.getPath();
169 			URL url = null;
170 			try {
171 				if (path != null) {
172 					setPartName(path.lastSegment());
173 					url = path.toFile().toURI().toURL();
174 				}
175 				if (url != null)
176 					initialURL= url.toExternalForm();
177 			} catch (Exception e) {
178 				Trace.trace(Trace.SEVERE, "Error getting URL to file"); //$NON-NLS-1$
179 			}
180 			if (webBrowser != null) {
181 				if (initialURL != null)
182 					webBrowser.setURL(initialURL);
183 				site.getWorkbenchWindow().getActivePage().activate(this);
184 			}
185 
186 			if (url != null)
187 				setTitleToolTip(url.getFile());
188 
189 			imageDescriptor = ImageResourceManager.getImageDescriptor("$nl$/icons/obj16/" + "internal_browser.png"); //$NON-NLS-1$ //$NON-NLS-2$
190 			//addResourceListener(file);
191 		} else if (input instanceof WebBrowserEditorInput) {
192 			WebBrowserEditorInput wbei = (WebBrowserEditorInput) input;
193 			initialURL = null;
194 			if (wbei.getURL() != null)
195 				initialURL = wbei.getURL().toExternalForm();
196 			if (webBrowser != null) {
197 				webBrowser.setURL(initialURL);
198 				site.getWorkbenchWindow().getActivePage().activate(this);
199 			}
200 
201 			setPartName(wbei.getName());
202 			setTitleToolTip(wbei.getToolTipText());
203 			lockName = wbei.isNameLocked();
204 
205 			imageDescriptor = wbei.getImageDescriptor();
206 		} else {
207 			IPathEditorInput pinput = Adapters.adapt(input, IPathEditorInput.class);
208 			if (pinput != null) {
209 				init(site, pinput);
210 			} else {
211 				throw new PartInitException(NLS.bind(Messages.errorInvalidEditorInput, input.getName()));
212 			}
213 		}
214 
215 		setSite(site);
216 		setInput(input);
217 	}
218 
219 	@Override
isDirty()220 	public boolean isDirty() {
221 		return false;
222 	}
223 
224 	@Override
isSaveAsAllowed()225 	public boolean isSaveAsAllowed() {
226 		return false;
227 	}
228 
229 	/**
230 	 * Open the input in the internal Web browser.
231 	 */
open(WebBrowserEditorInput input)232 	public static void open(WebBrowserEditorInput input) {
233 		IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
234 		IWorkbenchPage page = workbenchWindow.getActivePage();
235 
236 		try {
237 			IEditorReference[] editors = page.getEditorReferences();
238 			int size = editors.length;
239 			for (int i = 0; i < size; i++) {
240 				if (WEB_BROWSER_EDITOR_ID.equals(editors[i].getId())) {
241 					IEditorPart editor = editors[i].getEditor(true);
242 					if (editor != null && editor instanceof WebBrowserEditor) {
243 						WebBrowserEditor webEditor = (WebBrowserEditor) editor;
244 						WebBrowserEditorInput input2 = webEditor.getWebBrowserEditorInput();
245 						if (input2 == null || input.canReplaceInput(input2)) {
246 							editor.init(editor.getEditorSite(), input);
247 							return;
248 						}
249 					}
250 				}
251 			}
252 
253 			page.openEditor(input, WebBrowserEditor.WEB_BROWSER_EDITOR_ID);
254 		} catch (Exception e) {
255 			Trace.trace(Trace.SEVERE, "Error opening Web browser", e); //$NON-NLS-1$
256 		}
257 	}
258 
259 	/*
260 	 * Asks this part to take focus within the workbench.
261 	 */
262 	@Override
setFocus()263 	public void setFocus() {
264 		if (webBrowser != null)
265 			webBrowser.setFocus();
266 	}
267 
268 	/**
269 	 * Close the editor correctly.
270 	 */
271 	@Override
close()272 	public boolean close() {
273 		final boolean [] result = new boolean[1];
274 		Display.getDefault()
275 				.asyncExec(() -> result[0] = getEditorSite().getPage().closeEditor(WebBrowserEditor.this, false));
276 		return result[0];
277 	}
278 
279 	@Override
getActionBars()280 	public IActionBars getActionBars() {
281 		return getEditorSite().getActionBars();
282 	}
283 
284 	@Override
openInExternalBrowser(String url)285 	public void openInExternalBrowser(String url) {
286 		final IEditorInput input = getEditorInput();
287 		final String id = getEditorSite().getId();
288 		Runnable runnable = () -> doOpenExternalEditor(id, input);
289 		Display display = getSite().getShell().getDisplay();
290 		close();
291 		display.asyncExec(runnable);
292 	}
293 
doOpenExternalEditor(String id, IEditorInput input)294 	protected void doOpenExternalEditor(String id, IEditorInput input) {
295 		IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry();
296 		String name = input.getName();
297 		IEditorDescriptor [] editors = registry.getEditors(name);
298 		IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
299 
300 		String editorId = null;
301 		for (IEditorDescriptor editor : editors) {
302 			if (editor.getId().equals(id))
303 				continue;
304 			editorId = editor.getId();
305 			break;
306 		}
307 
308 		IEditorDescriptor ddesc = registry.getDefaultEditor(name);
309 		if (ddesc!=null && ddesc.getId().equals(id)) {
310 			int dot = name.lastIndexOf('.');
311 			String ext = name;
312 			if (dot!= -1)
313 				ext = "*."+name.substring(dot+1); //$NON-NLS-1$
314 			registry.setDefaultEditor(ext, null);
315 		}
316 
317 		if (editorId==null) {
318 			// no editor
319 			// next check with the OS for an external editor
320 			if (registry.isSystemExternalEditorAvailable(name))
321 				editorId = IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID;
322 		}
323 
324 		if (editorId!=null) {
325 			try {
326 				page.openEditor(input, editorId);
327 				return;
328 			} catch (PartInitException e) {
329 					// ignore
330 			}
331 		}
332 
333 		// no registered editor - open using browser support
334 		try {
335 			URL theURL = new URL(webBrowser.getURL());
336 			IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
337 			support.getExternalBrowser().openURL(theURL);
338 		}
339 		catch (MalformedURLException | PartInitException e) {
340 			//TODO handle this
341 		}
342 	}
343 }