/******************************************************************************* * Copyright (c) 2011, 2014 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.gerrit.ui; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.mylyn.commons.net.Policy; import org.eclipse.mylyn.commons.net.UnsupportedRequestException; import org.eclipse.mylyn.commons.workbench.WorkbenchUtil; import org.eclipse.mylyn.commons.workbench.browser.WebBrowserDialog; import org.eclipse.mylyn.internal.gerrit.core.GerritConnector; import org.eclipse.mylyn.internal.gerrit.core.client.IOpenIdLocation; import org.eclipse.mylyn.internal.gerrit.core.client.OpenIdAuthenticationRequest; import org.eclipse.mylyn.internal.gerrit.core.client.OpenIdAuthenticationResponse; import org.eclipse.mylyn.internal.tasks.ui.TaskRepositoryLocationUi; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.LocationAdapter; import org.eclipse.swt.browser.LocationEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; /** * @author Steffen Pingel */ public class GerritRepositoryLocationUi extends TaskRepositoryLocationUi implements IOpenIdLocation { private static Object lock = new Object(); private static volatile int version = 1; public GerritRepositoryLocationUi(TaskRepository taskRepository) { super(taskRepository); } @Override public String getProviderUrl() { if (Boolean.parseBoolean(taskRepository.getProperty(GerritConnector.KEY_REPOSITORY_OPEN_ID_ENABLED))) { return taskRepository.getProperty(GerritConnector.KEY_REPOSITORY_OPEN_ID_PROVIDER); } return null; } @Override public OpenIdAuthenticationResponse requestAuthentication(OpenIdAuthenticationRequest request, IProgressMonitor monitor) throws UnsupportedRequestException { if (Policy.isBackgroundMonitor(monitor)) { throw new UnsupportedRequestException(); } final String repositoryUrl = taskRepository.getUrl(); int currentVersion = version; // synchronize on a static lock to ensure that only one password dialog is displayed at a time synchronized (lock) { // check if the credentials changed while the thread was waiting for the lock if (currentVersion != version) { // another password prompt was shown, exit to try again return null; } return showAuthenticationDialog(repositoryUrl, request); } } private OpenIdAuthenticationResponse showAuthenticationDialog(final String repositoryUrl, final OpenIdAuthenticationRequest request) { final StringBuilder sb = new StringBuilder(); try { for (Map.Entry<String, String> entry : request.getProviderArgs().entrySet()) { if (sb.length() > 0) { sb.append("&"); //$NON-NLS-1$ } sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")); //$NON-NLS-1$ sb.append("="); //$NON-NLS-1$ sb.append(URLEncoder.encode(entry.getValue(), "UTF-8")); //$NON-NLS-1$ } } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } final AtomicReference<OpenIdAuthenticationResponse> result = new AtomicReference<OpenIdAuthenticationResponse>(); Display.getDefault().syncExec(new Runnable() { @Override public void run() { final WebBrowserDialog dialog = new WebBrowserDialog(WorkbenchUtil.getShell(), Messages.GerritRepositoryLocationUi_Login, null, Messages.GerritRepositoryLocationUi_Login_to_OpenID_Provider, MessageDialog.NONE, new String[] { IDialogConstants.CANCEL_LABEL }, 0) { @Override protected Point getInitialSize() { return new Point(780, 580); } }; dialog.create(); dialog.getBrowser().addLocationListener(new LocationAdapter() { @Override public void changing(LocationEvent event) { if (event.location != null && event.location.startsWith(request.getReturnUrl())) { result.set(new OpenIdAuthenticationResponse(event.location, null)); } // alternatively check cookies since IE does not notify listeners of redirects String value = Browser.getCookie(request.getCookie(), request.getCookieUrl()); if (value != null) { result.set(new OpenIdAuthenticationResponse(event.location, value)); } if (result.get() != null) { event.doit = false; // delay execution to avoid IE crash dialog.getBrowser().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (dialog.getShell() != null && !dialog.getShell().isDisposed()) { dialog.close(); } } }); } } }); // navigate to login page dialog.getBrowser().setUrl(request.getRequestUrl() + "?" + sb.toString()); //$NON-NLS-1$ dialog.open(); } }); return result.get(); } }