1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.chromoting;
6
7import android.app.Activity;
8import android.content.ComponentName;
9import android.content.Intent;
10import android.content.ServiceConnection;
11import android.content.pm.PackageInfo;
12import android.content.pm.PackageManager;
13import android.graphics.Bitmap;
14import android.net.Uri;
15import android.os.Binder;
16import android.os.Bundle;
17import android.os.IBinder;
18import android.os.Parcel;
19import android.os.RemoteException;
20import android.text.TextUtils;
21import android.util.Log;
22import android.view.Menu;
23import android.view.MenuItem;
24import android.view.View;
25import android.webkit.WebView;
26import android.webkit.WebViewClient;
27
28import org.chromium.ui.UiUtils;
29
30/**
31 * The Activity for showing the Help screen.
32 */
33public class HelpActivity extends Activity {
34    private static final String PLAY_STORE_URL = "market://details?id=";
35
36    private static final String FEEDBACK_PACKAGE = "com.google.android.gms";
37
38    private static final String FEEDBACK_CLASS =
39            "com.google.android.gms.feedback.LegacyBugReportService";
40
41    /**
42     * Maximum dimension for the screenshot to be sent to the Send Feedback handler.  This size
43     * ensures the size of bitmap < 1MB, which is a requirement of the handler.
44     */
45    private static final int MAX_FEEDBACK_SCREENSHOT_DIMENSION = 600;
46
47    /**
48     * This global variable is used for passing the screenshot from the originating Activity to the
49     * HelpActivity. There seems to be no better way of doing this.
50     */
51    private static Bitmap sScreenshot;
52
53    /** Constant used to send the feedback parcel to the system feedback service. */
54    private static final int SEND_FEEDBACK_INFO = Binder.FIRST_CALL_TRANSACTION;
55
56    /** Launches an external web browser or application. */
57    private void openUrl(String url) {
58        Uri uri = Uri.parse(url);
59        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
60
61        // Verify that the device can launch an application for this intent, otherwise
62        // startActivity() may crash the application.
63        if (intent.resolveActivity(getPackageManager()) != null) {
64            startActivity(intent);
65        }
66    }
67
68    private void sendFeedback() {
69        Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
70        intent.setComponent(new ComponentName(FEEDBACK_PACKAGE, FEEDBACK_CLASS));
71        if (getPackageManager().resolveService(intent, 0) == null) {
72            Log.e("help", "Unable to resolve Feedback service.");
73            return;
74        }
75
76        ServiceConnection conn = new ServiceConnection() {
77            @Override
78            public void onServiceConnected(ComponentName name, IBinder service) {
79                try {
80                    Parcel parcel = Parcel.obtain();
81                    if (sScreenshot != null) {
82                        sScreenshot.writeToParcel(parcel, 0);
83                    }
84                    service.transact(SEND_FEEDBACK_INFO, parcel, null, 0);
85                    parcel.recycle();
86                } catch (RemoteException ex) {
87                    Log.e("help", "Unexpected error sending feedback: ", ex);
88                }
89            }
90
91            @Override
92            public void onServiceDisconnected(ComponentName name) {}
93        };
94
95        bindService(intent, conn, BIND_AUTO_CREATE);
96    }
97
98    /** Launches the Help activity. */
99    public static void launch(Activity activity, String helpUrl) {
100        View rootView = activity.getWindow().getDecorView().getRootView();
101        sScreenshot = UiUtils.generateScaledScreenshot(rootView, MAX_FEEDBACK_SCREENSHOT_DIMENSION,
102                Bitmap.Config.ARGB_8888);
103
104        Intent intent = new Intent(activity, HelpActivity.class);
105        intent.setData(Uri.parse(helpUrl));
106        activity.startActivity(intent);
107    }
108
109    @Override
110    public void onCreate(Bundle savedInstanceState) {
111        super.onCreate(savedInstanceState);
112
113        WebView webView = new WebView(this);
114        setContentView(webView);
115
116        getActionBar().setTitle(getString(R.string.actionbar_help_title));
117
118        CharSequence appName = getTitle();
119        CharSequence versionName = null;
120        try {
121            PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
122            versionName = info.versionName;
123        } catch (PackageManager.NameNotFoundException ex) {
124            throw new RuntimeException("Unable to get version: " + ex);
125        }
126
127        CharSequence subtitle = TextUtils.concat(appName, " ", versionName);
128        getActionBar().setSubtitle(subtitle);
129
130        // This line ensures the WebView remains embedded in this activity and doesn't launch an
131        // external Chrome browser.
132        webView.setWebViewClient(new WebViewClient());
133        webView.getSettings().setJavaScriptEnabled(true);
134        String url = getIntent().getDataString();
135        webView.loadUrl(url);
136    }
137
138    @Override
139    public boolean onCreateOptionsMenu(Menu menu) {
140        getMenuInflater().inflate(R.menu.help_actionbar, menu);
141        return super.onCreateOptionsMenu(menu);
142    }
143
144    @Override
145    public boolean onOptionsItemSelected(MenuItem item) {
146        int id = item.getItemId();
147        if (id == R.id.actionbar_feedback) {
148            sendFeedback();
149            return true;
150        }
151        if (id == R.id.actionbar_play_store) {
152            openUrl(PLAY_STORE_URL + getPackageName());
153            return true;
154        }
155        return super.onOptionsItemSelected(item);
156    }
157}
158