• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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