/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
*
* 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.google.dart.tools.debug.ui.internal;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.debug.core.DartDebugCorePlugin;
import com.google.dart.tools.debug.core.IUserAgentManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
/**
* A class to let the user to choose which user agents are allowed to connect to the embedded
* server.
*/
public class DartDebugUserAgentManager implements IUserAgentManager {
private static class AgentData {
String address;
String agentName;
boolean allowed;
}
static void install() {
DartDebugCorePlugin.getPlugin().setUserAgentManager(new DartDebugUserAgentManager());
}
private List<AgentData> agents = new ArrayList<AgentData>();
private DartDebugUserAgentManager() {
loadSettings();
}
@Override
public boolean allowUserAgent(InetAddress remoteAddress, String agentName) {
// This handles things like port scanners, which can cause the editor to open a lot of popups.
if (agentName == null) {
return false;
}
// check if it's an existing agent
if (isKnownAgent(remoteAddress, agentName)) {
return agentAllowed(remoteAddress, agentName);
}
// ask the user
if (DartCore.allowConnectionDialogOpen) {
return false;
}
DartCore.allowConnectionDialogOpen = true;
boolean allowConnection = askUserAllows(remoteAddress, agentName);
addAgentData(remoteAddress, agentName, allowConnection);
DartCore.allowConnectionDialogOpen = false;
return allowConnection;
}
private void addAgentData(InetAddress remoteAddress, String agentName, boolean allowConnection) {
AgentData data = new AgentData();
data.address = remoteAddress.getHostAddress();
data.agentName = agentName;
data.allowed = allowConnection;
agents.add(data);
saveSettings();
}
private boolean agentAllowed(InetAddress remoteAddress, String agent) {
if (agent == null) {
return false;
}
String address = remoteAddress.getHostAddress();
for (AgentData data : agents) {
if (address.equals(data.address) && agent.equals(data.agentName)) {
return data.allowed;
}
}
return false;
}
private boolean askUserAllows(final InetAddress remoteAddress, final String agent) {
final boolean[] result = new boolean[1];
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
// Move the app to the foreground. Otherwise the dialog can be missed.
shell.forceActive();
// set Cancel as the default choice
MessageDialog dialog = new MessageDialog(
shell,
"Allow Remote Device Connection",
null,
"Allow a remote device from " + remoteAddress.getHostAddress()
+ " to connect to and run your Dart applications?\n\n" + agent,
MessageDialog.CONFIRM,
new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL},
1);
result[0] = dialog.open() == 0;
}
});
return result[0];
}
private File getDataFile() {
return DartDebugUIPlugin.getDefault().getStateLocation().append("agentdata.txt").toFile();
}
private boolean isKnownAgent(InetAddress remoteAddress, String agent) {
String remoteAddressString = remoteAddress.getHostAddress();
for (AgentData data : agents) {
if (remoteAddressString.equals(data.address) && agent.equals(data.agentName)) {
return true;
}
}
if (agent.equals("com.google.dart.editor.mobile.connection.service")) {
for (AgentData data : agents) {
if (remoteAddressString.equals(data.address)) {
addAgentData(remoteAddress, agent, true);
return true;
}
}
}
return false;
}
private void loadSettings() {
File file = getDataFile();
if (file.exists()) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
while (line != null) {
AgentData agent = new AgentData();
agent.address = line;
agent.agentName = reader.readLine();
agent.allowed = Boolean.valueOf(reader.readLine());
agents.add(agent);
line = reader.readLine();
}
reader.close();
} catch (IOException ioe) {
DartUtil.logError(ioe);
}
}
}
private void saveSettings() {
File file = getDataFile();
try {
PrintWriter out = new PrintWriter(new FileWriter(file));
for (AgentData data : agents) {
out.println(data.address);
out.println(data.agentName);
out.println(data.allowed);
}
out.close();
} catch (IOException ioe) {
DartUtil.logError(ioe);
}
}
}