1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.sdkstats; 17 18 import org.eclipse.jface.dialogs.Dialog; 19 import org.eclipse.jface.window.Window; 20 import org.eclipse.swt.SWT; 21 import org.eclipse.swt.events.SelectionAdapter; 22 import org.eclipse.swt.events.SelectionEvent; 23 import org.eclipse.swt.graphics.Color; 24 import org.eclipse.swt.graphics.Font; 25 import org.eclipse.swt.graphics.FontData; 26 import org.eclipse.swt.layout.GridData; 27 import org.eclipse.swt.layout.GridLayout; 28 import org.eclipse.swt.program.Program; 29 import org.eclipse.swt.widgets.Button; 30 import org.eclipse.swt.widgets.Composite; 31 import org.eclipse.swt.widgets.Control; 32 import org.eclipse.swt.widgets.Label; 33 import org.eclipse.swt.widgets.Link; 34 import org.eclipse.swt.widgets.Shell; 35 36 import java.io.IOException; 37 38 /** 39 * Dialog to get user permission for ping service. 40 */ 41 public class SdkStatsPermissionDialog extends Dialog { 42 /* Text strings displayed in the opt-out dialog. */ 43 private static final String HEADER_TEXT = 44 "Thanks for using the Android SDK!"; 45 46 /** Used in the ADT welcome wizard as well. */ 47 public static final String NOTICE_TEXT = 48 "We know you just want to get started but please read this first."; 49 50 /** Used in the preference pane (PrefsDialog) as well. */ 51 public static final String BODY_TEXT = 52 "By choosing to send certain usage statistics to Google, you can " + 53 "help us improve the Android SDK. These usage statistics lets us " + 54 "measure things like active usage of the SDK, and let us know things " + 55 "like which versions of the SDK are in use and which tools are the " + 56 "most popular with developers. This limited data is not associated " + 57 "with personal information about you, and is examined on an aggregate " + 58 "basis, and is maintained in accordance with the Google Privacy Policy."; 59 60 /** Used in the ADT welcome wizard as well. */ 61 public static final String PRIVACY_POLICY_LINK_TEXT = 62 "<a href=\"http://www.google.com/intl/en/privacy.html\">Google " + 63 "Privacy Policy</a>"; 64 65 /** Used in the preference pane (PrefsDialog) as well. */ 66 public static final String CHECKBOX_TEXT = 67 "Send usage statistics to Google."; 68 69 /** Used in the ADT welcome wizard as well. */ 70 public static final String FOOTER_TEXT = 71 "If you later decide to change this setting, you can do so in the" + 72 "\"ddms\" tool under \"File\" > \"Preferences\" > \"Usage Stats\"."; 73 74 private static final String BUTTON_TEXT = "Proceed"; 75 76 /** List of Linux browser commands to try, in order (see openUrl). */ 77 private static final String[] LINUX_BROWSERS = new String[] { 78 "firefox -remote openurl(%URL%,new-window)", //$NON-NLS-1$ running FF 79 "mozilla -remote openurl(%URL%,new-window)", //$NON-NLS-1$ running Moz 80 "firefox %URL%", //$NON-NLS-1$ new FF 81 "mozilla %URL%", //$NON-NLS-1$ new Moz 82 "kfmclient openURL %URL%", //$NON-NLS-1$ Konqueror 83 "opera -newwindow %URL%", //$NON-NLS-1$ Opera 84 }; 85 86 private static final boolean ALLOW_PING_DEFAULT = true; 87 private boolean mAllowPing = ALLOW_PING_DEFAULT; 88 SdkStatsPermissionDialog(Shell parentShell)89 public SdkStatsPermissionDialog(Shell parentShell) { 90 super(parentShell); 91 setBlockOnOpen(true); 92 } 93 94 @Override createButtonsForButtonBar(Composite parent)95 protected void createButtonsForButtonBar(Composite parent) { 96 createButton(parent, Window.OK, BUTTON_TEXT, true); 97 } 98 99 @Override createDialogArea(Composite parent)100 protected Control createDialogArea(Composite parent) { 101 Composite composite = (Composite) super.createDialogArea(parent); 102 composite.setLayout(new GridLayout(1, false)); 103 104 final Label title = new Label(composite, SWT.CENTER | SWT.WRAP); 105 final FontData[] fontdata = title.getFont().getFontData(); 106 for (int i = 0; i < fontdata.length; i++) { 107 fontdata[i].setHeight(fontdata[i].getHeight() * 4 / 3); 108 } 109 title.setFont(new Font(getShell().getDisplay(), fontdata)); 110 title.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 111 title.setText(HEADER_TEXT); 112 113 final Label notice = new Label(composite, SWT.WRAP); 114 notice.setFont(title.getFont()); 115 notice.setForeground(new Color(getShell().getDisplay(), 255, 0, 0)); 116 notice.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 117 notice.setText(NOTICE_TEXT); 118 notice.pack(); 119 120 final Label bodyText = new Label(composite, SWT.WRAP); 121 GridData gd = new GridData(); 122 gd.widthHint = notice.getSize().x; // do not extend beyond the NOTICE text's width 123 gd.grabExcessHorizontalSpace = true; 124 bodyText.setLayoutData(gd); 125 bodyText.setText(BODY_TEXT); 126 127 final Link privacyLink = new Link(composite, SWT.NONE); 128 privacyLink.setText(PRIVACY_POLICY_LINK_TEXT); 129 privacyLink.addSelectionListener(new SelectionAdapter() { 130 @Override 131 public void widgetSelected(SelectionEvent event) { 132 openUrl(event.text); 133 } 134 }); 135 136 final Button checkbox = new Button(composite, SWT.CHECK); 137 checkbox.setSelection(ALLOW_PING_DEFAULT); 138 checkbox.setText(CHECKBOX_TEXT); 139 checkbox.addSelectionListener(new SelectionAdapter() { 140 @Override 141 public void widgetSelected(SelectionEvent event) { 142 mAllowPing = checkbox.getSelection(); 143 } 144 }); 145 146 final Label footer = new Label(composite, SWT.WRAP); 147 gd = new GridData(); 148 gd.widthHint = notice.getSize().x; 149 gd.grabExcessHorizontalSpace = true; 150 footer.setLayoutData(gd); 151 footer.setText(FOOTER_TEXT); 152 153 return composite; 154 } 155 156 /** 157 * Open a URL in an external browser. 158 * @param url to open - MUST be sanitized and properly formed! 159 */ openUrl(final String url)160 public static void openUrl(final String url) { 161 // TODO: consider using something like BrowserLauncher2 162 // (http://browserlaunch2.sourceforge.net/) instead of these hacks. 163 164 // SWT's Program.launch() should work on Mac, Windows, and GNOME 165 // (because the OS shell knows how to launch a default browser). 166 if (!Program.launch(url)) { 167 // Must be Linux non-GNOME (or something else broke). 168 // Try a few Linux browser commands in the background. 169 new Thread() { 170 @Override 171 public void run() { 172 for (String cmd : LINUX_BROWSERS) { 173 cmd = cmd.replaceAll("%URL%", url); //$NON-NLS-1$ 174 try { 175 Process proc = Runtime.getRuntime().exec(cmd); 176 if (proc.waitFor() == 0) break; // Success! 177 } catch (InterruptedException e) { 178 // Should never happen! 179 throw new RuntimeException(e); 180 } catch (IOException e) { 181 // Swallow the exception and try the next browser. 182 } 183 } 184 185 // TODO: Pop up some sort of error here? 186 // (We're in a new thread; can't use the existing Display.) 187 } 188 }.start(); 189 } 190 } 191 getPingUserPreference()192 public boolean getPingUserPreference() { 193 return mAllowPing; 194 } 195 } 196