1 /*******************************************************************************
2 * Copyright (c) 2010, 2017 IBM Corporation and others.
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/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.browser;
19 import org.eclipse.swt.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.ole.win32.*;
22 import org.eclipse.swt.internal.webkit.*;
23 import org.eclipse.swt.internal.win32.*;
24 import org.eclipse.swt.layout.*;
25 import org.eclipse.swt.widgets.*;
27 class WebDownloadDelegate {
28 COMObject iWebDownloadDelegate;
36 static final int DOWNLOAD_FINISHED = 0;
37 static final int DOWNLOAD_CANCELLED = 1;
38 static final int DOWNLOAD_ERROR = 3;
40 WebDownloadDelegate (Browser browser) {
41 createCOMInterfaces ();
42 this.browser = browser;
50 void createCOMInterfaces () {
51 iWebDownloadDelegate = new COMObject (new int[] {2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 1, 1}) {
53 public long method0 (long[] args) {return QueryInterface (args[0], args[1]);}
55 public long method1 (long[] args) {return AddRef ();}
57 public long method2 (long[] args) {return Release ();}
59 public long method3 (long[] args) {return decideDestinationWithSuggestedFilename (args[0], args[1]);}
61 public long method4 (long[] args) {return COM.E_NOTIMPL;}
63 public long method5 (long[] args) {return COM.E_NOTIMPL;}
65 public long method6 (long[] args) {return didFailWithError (args[0], args[1]);}
67 public long method7 (long[] args) {return COM.E_NOTIMPL;}
69 public long method8 (long[] args) {return didReceiveDataOfLength (args[0], (int)args[1]);}
71 public long method9 (long[] args) {return didReceiveResponse (args[0], args[1]);}
73 public long method10 (long[] args) {return COM.E_NOTIMPL;}
75 public long method11 (long[] args) {return COM.E_NOTIMPL;}
77 public long method12 (long[] args) {return willSendRequest (args[0], args[1], args[2], args[3]);}
79 public long method13 (long[] args) {return didBegin (args[0]);}
81 public long method14 (long[] args) {return didFinish (args[0]);}
85 int decideDestinationWithSuggestedFilename (long download, long filename) {
86 String name = WebKit.extractBSTR (filename);
87 FileDialog dialog = new FileDialog (browser.getShell(), SWT.SAVE);
88 dialog.setText (SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
89 dialog.setFileName (name);
90 dialog.setOverwrite (true);
91 String path = dialog.open ();
92 IWebDownload iwebdownload = new IWebDownload (download);
93 iwebdownload.setDeletesFileUponFailure (0);
96 * Bug in WebKit. Failure to set a non-null destination on the IWebDownload results in
97 * a crash, even when the download is being cancelled.
99 iwebdownload.setDestination (WebKit.createBSTR (""), 1); //$NON-NLS-1$
100 iwebdownload.cancel();
101 iwebdownload.Release();
103 File file = new File (path);
104 if (file.exists ()) file.delete ();
105 iwebdownload.setDestination (WebKit.createBSTR (path), 1);
106 openDownloadWindow (iwebdownload, path);
111 int didBegin (long download) {
112 new IWebDownload (download).AddRef ();
120 int didFailWithError (long download, long error) {
121 new IWebDownload (download).Release ();
122 status = DOWNLOAD_ERROR;
126 int didFinish (long download) {
127 new IWebDownload (download).Release ();
128 status = DOWNLOAD_FINISHED;
132 int didReceiveDataOfLength (long download, int length) {
137 int didReceiveResponse (long download, long response) {
139 IWebURLResponse urlResponse = new IWebURLResponse (response);
140 long[] size = new long[1];
141 int hr = urlResponse.expectedContentLength (size);
142 if (hr == COM.S_OK) totalSize = size[0];
143 long[] result = new long[1];
144 hr = urlResponse.URL (result);
145 if (hr == COM.S_OK && result[0] != 0) {
146 url = WebKit.extractBSTR (result[0]);
147 COM.SysFreeString (result[0]);
153 void disposeCOMInterfaces () {
154 if (iWebDownloadDelegate != null) {
155 iWebDownloadDelegate.dispose ();
156 iWebDownloadDelegate = null;
161 return iWebDownloadDelegate.getAddress ();
164 void openDownloadWindow (final IWebDownload download, String name) {
165 final Shell shell = new Shell ();
166 shell.setText (Compatibility.getMessage ("SWT_FileDownload")); //$NON-NLS-1$
167 GridLayout gridLayout = new GridLayout ();
168 gridLayout.marginHeight = 15;
169 gridLayout.marginWidth = 15;
170 gridLayout.verticalSpacing = 20;
171 shell.setLayout (gridLayout);
173 Label nameLabel = new Label (shell, SWT.WRAP);
174 nameLabel.setText (Compatibility.getMessage ("SWT_Download_Location", new Object[] {name, url})); //$NON-NLS-1$
175 GridData data = new GridData ();
176 Monitor monitor = browser.getMonitor ();
177 int maxWidth = monitor.getBounds ().width / 2;
178 int width = nameLabel.computeSize (SWT.DEFAULT, SWT.DEFAULT).x;
179 data.widthHint = Math.min (width, maxWidth);
180 data.horizontalAlignment = GridData.FILL;
181 data.grabExcessHorizontalSpace = true;
182 nameLabel.setLayoutData (data);
184 final Label statusLabel = new Label (shell, SWT.NONE);
185 statusLabel.setText (Compatibility.getMessage ("SWT_Download_Started")); //$NON-NLS-1$
186 data = new GridData (GridData.FILL_BOTH);
187 statusLabel.setLayoutData (data);
189 final Button cancel = new Button (shell, SWT.PUSH);
190 cancel.setText (Compatibility.getMessage ("SWT_Cancel")); //$NON-NLS-1$
191 data = new GridData ();
192 data.horizontalAlignment = GridData.CENTER;
193 cancel.setLayoutData (data);
194 final Listener cancelListener = event -> {
196 status = DOWNLOAD_CANCELLED;
199 cancel.addListener (SWT.Selection, cancelListener);
201 final Display display = browser.getDisplay ();
202 final int INTERVAL = 500;
203 display.timerExec (INTERVAL, new Runnable () {
206 if (shell.isDisposed () || status == DOWNLOAD_FINISHED || status == DOWNLOAD_CANCELLED) {
210 if (status == DOWNLOAD_ERROR) {
211 statusLabel.setText (Compatibility.getMessage ("SWT_Download_Error")); //$NON-NLS-1$
212 cancel.removeListener (SWT.Selection, cancelListener);
213 cancel.addListener (SWT.Selection, event -> shell.dispose ());
216 long current = size / 1024L;
217 long total = totalSize / 1024L;
218 String message = Compatibility.getMessage ("SWT_Download_Status", new Object[] {current, total}); //$NON-NLS-1$
219 statusLabel.setText (message);
220 display.timerExec (INTERVAL, this);
227 int QueryInterface (long riid, long ppvObject) {
228 if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG;
229 GUID guid = new GUID ();
230 COM.MoveMemory (guid, riid, GUID.sizeof);
232 if (COM.IsEqualGUID (guid, COM.IIDIUnknown)) {
233 OS.MoveMemory (ppvObject, new long[] {iWebDownloadDelegate.getAddress ()}, C.PTR_SIZEOF);
234 new IUnknown (iWebDownloadDelegate.getAddress ()).AddRef ();
237 if (COM.IsEqualGUID (guid, WebKit_win32.IID_IWebDownloadDelegate)) {
238 OS.MoveMemory (ppvObject, new long[] {iWebDownloadDelegate.getAddress ()}, C.PTR_SIZEOF);
239 new IUnknown (iWebDownloadDelegate.getAddress ()).AddRef ();
243 OS.MoveMemory (ppvObject, new long[] {0}, C.PTR_SIZEOF);
244 return COM.E_NOINTERFACE;
250 disposeCOMInterfaces ();
255 int willSendRequest (long download, long request, long redirectResponse, long finalRequest) {
256 IWebMutableURLRequest req = new IWebMutableURLRequest (request);
258 OS.MoveMemory (finalRequest, new long[] {request}, C.PTR_SIZEOF);