1// Copyright 2013 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
5#ifndef CHROME_BROWSER_ANDROID_SHORTCUT_HELPER_H_
6#define CHROME_BROWSER_ANDROID_SHORTCUT_HELPER_H_
7
8#include "base/android/jni_android.h"
9#include "base/android/jni_weak_ref.h"
10#include "base/basictypes.h"
11#include "base/strings/string16.h"
12#include "base/task/cancelable_task_tracker.h"
13#include "chrome/common/web_application_info.h"
14#include "components/favicon_base/favicon_types.h"
15#include "content/public/browser/web_contents_observer.h"
16#include "content/public/common/manifest.h"
17#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
18
19namespace content {
20class WebContents;
21}  // namespace content
22
23namespace IPC {
24class Message;
25}
26
27class GURL;
28
29// ShortcutHelper is the C++ counterpart of org.chromium.chrome.browser's
30// ShortcutHelper in Java. The object is owned by the Java object. It is created
31// from there via a JNI (Initialize) call and can be destroyed from Java too
32// using TearDown. When the Java implementations calls AddShortcut, it gives up
33// the ownership of the object. The instance will then destroy itself when done.
34class ShortcutHelper : public content::WebContentsObserver {
35 public:
36  ShortcutHelper(JNIEnv* env,
37                 jobject obj,
38                 content::WebContents* web_contents);
39
40  // Initialize the helper by requesting the information about the page to the
41  // renderer process. The initialization is asynchronous and
42  // OnDidRetrieveWebappInformation is expected to be called when finished.
43  void Initialize();
44
45  // Called by the Java counter part to let the object knows that it can destroy
46  // itself.
47  void TearDown(JNIEnv* env, jobject obj);
48
49  // IPC message received when the initialization is finished.
50  void OnDidGetWebApplicationInfo(const WebApplicationInfo& web_app_info);
51
52  // Callback run when the Manifest is ready to be used.
53  void OnDidGetManifest(const content::Manifest& manifest);
54
55  // Adds a shortcut to the current URL to the Android home screen.
56  void AddShortcut(JNIEnv* env,
57                   jobject obj,
58                   jstring title,
59                   jint launcher_large_icon_size);
60
61  // Callback run when the requested Manifest icon is ready to be used.
62  void OnDidDownloadIcon(int id,
63                         int http_status_code,
64                         const GURL& url,
65                         const std::vector<SkBitmap>& bitmaps,
66                         const std::vector<gfx::Size>& sizes);
67
68  // Called after AddShortcut() and OnDidDownloadIcon() are run if
69  // OnDidDownloadIcon has a valid icon.
70  void AddShortcutUsingManifestIcon();
71
72  // Use FaviconService to get the best available favicon and create the
73  // shortcut using it. This is used when no Manifest icons are available or
74  // appropriate.
75  void AddShortcutUsingFavicon();
76
77  // Callback run when a favicon is received from GetFavicon() call.
78  void OnDidGetFavicon(
79      const favicon_base::FaviconRawBitmapResult& bitmap_result);
80
81  // WebContentsObserver
82  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
83  virtual void WebContentsDestroyed() OVERRIDE;
84
85  // Adds a shortcut to the launcher using a FaviconRawBitmapResult.
86  // Must be called from a WorkerPool task.
87  static void AddShortcutInBackgroundWithRawBitmap(
88      const GURL& url,
89      const base::string16& title,
90      content::Manifest::DisplayMode display,
91      const favicon_base::FaviconRawBitmapResult& bitmap_result,
92      blink::WebScreenOrientationLockType orientation);
93
94  // Adds a shortcut to the launcher using a SkBitmap.
95  // Must be called from a WorkerPool task.
96  static void AddShortcutInBackgroundWithSkBitmap(
97      const GURL& url,
98      const base::string16& title,
99      content::Manifest::DisplayMode display,
100      const SkBitmap& icon_bitmap,
101      blink::WebScreenOrientationLockType orientation);
102
103  // Registers JNI hooks.
104  static bool RegisterShortcutHelper(JNIEnv* env);
105
106 private:
107  enum ManifestIconStatus {
108    MANIFEST_ICON_STATUS_NONE,
109    MANIFEST_ICON_STATUS_FETCHING,
110    MANIFEST_ICON_STATUS_DONE
111  };
112
113  virtual ~ShortcutHelper();
114
115  void Destroy();
116
117  // Runs the algorithm to find the best matching icon in the icons listed in
118  // the Manifest.
119  // Returns the icon url if a suitable icon is found. An empty URL otherwise.
120  GURL FindBestMatchingIcon(
121      const std::vector<content::Manifest::Icon>& icons) const;
122
123  // Runs an algorithm only based on icon declared sizes. It will try to find
124  // size that is the closest to preferred_icon_size_in_px_ but bigger than
125  // preferred_icon_size_in_px_ if possible.
126  // Returns the icon url if a suitable icon is found. An empty URL otherwise.
127  GURL FindBestMatchingIcon(const std::vector<content::Manifest::Icon>& icons,
128                            float density) const;
129
130  // Returns an array containing the items in |icons| without the unsupported
131  // image MIME types.
132  static std::vector<content::Manifest::Icon> FilterIconsByType(
133      const std::vector<content::Manifest::Icon>& icons);
134
135  // Returns whether the preferred_icon_size_in_px_ is in the given |sizes|.
136  bool IconSizesContainsPreferredSize(
137      const std::vector<gfx::Size>& sizes) const;
138
139  // Returns whether the 'any' (ie. gfx::Size(0,0)) is in the given |sizes|.
140  bool IconSizesContainsAny(const std::vector<gfx::Size>& sizes) const;
141
142  JavaObjectWeakGlobalRef java_ref_;
143
144  GURL url_;
145  base::string16 title_;
146  content::Manifest::DisplayMode display_;
147  SkBitmap manifest_icon_;
148  base::CancelableTaskTracker cancelable_task_tracker_;
149  blink::WebScreenOrientationLockType orientation_;
150
151  bool add_shortcut_requested_;
152
153  ManifestIconStatus manifest_icon_status_;
154  const int preferred_icon_size_in_px_;
155  static const int kPreferredIconSizeInDp;
156
157  base::WeakPtrFactory<ShortcutHelper> weak_ptr_factory_;
158
159  friend class ShortcutHelperTest;
160  DISALLOW_COPY_AND_ASSIGN(ShortcutHelper);
161};
162
163#endif  // CHROME_BROWSER_ANDROID_SHORTCUT_HELPER_H_
164