Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: chrome/browser/android/webapk/webapk_builder.cc

Issue 2138973002: Initial CL for talking to the WebAPK server to generate WebAPK (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge branch 'webapk_builder_impl0' into webapk_builder_impl2 Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "chrome/browser/android/webapk/webapk_builder.h"
6
7 #include "base/android/build_info.h"
8 #include "base/android/jni_android.h"
9 #include "base/android/jni_string.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/md5.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/android/webapk/webapk.pb.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "components/version_info/version_info.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "jni/WebApkBuilder_jni.h"
22 #include "net/http/http_status_code.h"
23 #include "net/url_request/url_fetcher.h"
24 #include "ui/gfx/codec/png_codec.h"
25 #include "url/gurl.h"
26
27 namespace {
28
29 // The default WebAPK server URL.
30 const char kDefaultWebApkServerUrl[] = "http://www.awesomeserver.appspot.com";
ScottK 2016/07/22 15:24:27 this is going to be "https://webapk.googleapis.com
31
32 // The MIME type of the POST data sent to the server.
33 const char kProtoMimeType[] = "application/octet-stream";
ScottK 2016/07/22 15:24:27 Turns out this needs to be: "application/x-protobu
34
35 // The number of milliseconds to wait for a response from the server.
36 const int kTimeoutMs = 4000;
37
38 // Returns the scope from |info| if it is specified. Otherwise, returns the
39 // default scope.
40 GURL GetScope(const ShortcutInfo& info) {
41 return (info.scope.is_valid()) ? info.scope : info.url.GetOrigin();
42 }
43
44 // Computes a MD5 hash of |bitmap|'s PNG encoded bytes.
45 std::string ComputeBitmapHash(const SkBitmap& bitmap) {
46 std::vector<unsigned char> png_bytes;
47 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_bytes);
48 base::MD5Digest digest;
49 base::MD5Sum(&png_bytes.front(), png_bytes.size(), &digest);
50 return base::MD5DigestToBase16(digest);
51 }
52
53 } // anonymous namespace
54
55 WebApkBuilder::WebApkBuilder(content::BrowserContext* browser_context,
56 const ShortcutInfo& shortcut_info,
57 const SkBitmap& shortcut_icon)
58 : browser_context_(browser_context),
59 shortcut_info_(shortcut_info),
60 shortcut_icon_(shortcut_icon),
61 weak_ptr_factory_(this) {
62 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
63 server_url_ =
64 GURL(command_line->HasSwitch(switches::kWebApkServerUrl)
65 ? command_line->GetSwitchValueASCII(switches::kWebApkServerUrl)
66 : kDefaultWebApkServerUrl);
67 }
68
69 WebApkBuilder::~WebApkBuilder() {}
70
71 // static
72 bool WebApkBuilder::Register(JNIEnv* env) {
73 return RegisterNativesImpl(env);
74 }
75
76 // static
77 std::string WebApkBuilder::DisplayToString(blink::WebDisplayMode display) {
78 switch (display) {
79 case blink::WebDisplayModeUndefined:
80 return "";
81 case blink::WebDisplayModeBrowser:
82 return "browser";
83 case blink::WebDisplayModeMinimalUi:
84 return "minimal-ui";
85 case blink::WebDisplayModeStandalone:
86 return "standalone";
87 case blink::WebDisplayModeFullscreen:
88 return "fullscreen";
89 }
90 }
91
92 // static
93 std::string WebApkBuilder::OrientationToString(
94 blink::WebScreenOrientationLockType orientation) {
95 switch (orientation) {
96 case blink::WebScreenOrientationLockDefault:
97 return "";
98 case blink::WebScreenOrientationLockPortraitPrimary:
99 return "portrait-primary";
100 case blink::WebScreenOrientationLockPortraitSecondary:
101 return "portrait-secondary";
102 case blink::WebScreenOrientationLockLandscapePrimary:
103 return "landscape-primary";
104 case blink::WebScreenOrientationLockLandscapeSecondary:
105 return "landscape-secondary";
106 case blink::WebScreenOrientationLockAny:
107 return "any";
108 case blink::WebScreenOrientationLockLandscape:
109 return "landscape";
110 case blink::WebScreenOrientationLockPortrait:
111 return "portrait";
112 case blink::WebScreenOrientationLockNatural:
113 return "natural";
114 }
115 }
116
117 // static
118 std::string WebApkBuilder::ColorToString(int64_t color) {
119 if (color == content::Manifest::kInvalidOrMissingColor)
120 return "";
121
122 SkColor sk_color = reinterpret_cast<uint32_t&>(color);
123 int r = SkColorGetR(sk_color);
124 int g = SkColorGetG(sk_color);
125 int b = SkColorGetB(sk_color);
126 double a = SkColorGetA(sk_color) / 255.0;
127 return base::StringPrintf("rgba(%d,%d,%d,%.2f)", r, g, b, a);
128 }
129
130 void WebApkBuilder::BuildAsync(const FinishCallback& finish_callback) {
131 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
132 finish_callback_ = finish_callback;
133 content::BrowserThread::PostTask(
134 content::BrowserThread::UI, FROM_HERE,
135 base::Bind(&WebApkBuilder::InitializeRequestContextGetterOnUIThread,
136 weak_ptr_factory_.GetWeakPtr()));
137 }
138
139 void WebApkBuilder::OnURLFetchComplete(const net::URLFetcher* source) {
140 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
141 timer_.Stop();
142
143 if (!source->GetStatus().is_success() ||
144 source->GetResponseCode() != net::HTTP_OK) {
145 OnFailure();
146 return;
147 }
148
149 std::string response_string;
150 source->GetResponseAsString(&response_string);
151
152 std::unique_ptr<webapk::CreateWebApkResponse> response(
153 new webapk::CreateWebApkResponse);
154 if (!response->ParseFromString(response_string)) {
155 OnFailure();
156 return;
157 }
158
159 if (response->signed_market_url().empty()) {
160 OnFailure();
161 return;
162 }
163 OnGotMarketUrl(response->signed_market_url());
164 }
165
166 void WebApkBuilder::InitializeRequestContextGetterOnUIThread() {
167 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
168 // Must be called on UI thread.
169 request_context_getter_ =
170 Profile::FromBrowserContext(browser_context_)->GetRequestContext();
171
172 content::BrowserThread::PostTask(
173 content::BrowserThread::IO, FROM_HERE,
174 base::Bind(&WebApkBuilder::SendCreateWebApkRequest,
175 weak_ptr_factory_.GetWeakPtr()));
176 }
177
178 void WebApkBuilder::SendCreateWebApkRequest() {
179 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
180 std::unique_ptr<webapk::CreateWebApkRequest> request =
181 BuildCreateWebApkRequest();
182
183 timer_.Start(
184 FROM_HERE, base::TimeDelta::FromMilliseconds(kTimeoutMs),
185 base::Bind(&WebApkBuilder::OnFailure, weak_ptr_factory_.GetWeakPtr()));
186
187 url_fetcher_ =
188 net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this);
189 url_fetcher_->SetRequestContext(request_context_getter_);
190 std::string serialized_request;
191 request->SerializeToString(&serialized_request);
192 url_fetcher_->SetUploadData(kProtoMimeType, serialized_request);
193 url_fetcher_->Start();
194 }
195
196 void WebApkBuilder::OnGotMarketUrl(const std::string& signed_market_url) {
197 JNIEnv* env = base::android::AttachCurrentThread();
198 base::android::ScopedJavaLocalRef<jstring> java_signed_market_url =
199 base::android::ConvertUTF8ToJavaString(env, signed_market_url);
200 bool success = Java_WebApkBuilder_downloadAndInstallAsync(
201 env, java_signed_market_url.obj());
202 if (success)
203 OnSuccess();
204 else
205 OnFailure();
206 }
207
208 std::unique_ptr<webapk::CreateWebApkRequest>
209 WebApkBuilder::BuildCreateWebApkRequest() {
210 std::unique_ptr<webapk::CreateWebApkRequest> request(
211 new webapk::CreateWebApkRequest);
212
213 webapk::WebApk* webapk = request->mutable_webapk();
214 webapk->set_manifest_url(shortcut_info_.manifest_url.spec());
215 webapk->set_requester_application_package(
216 base::android::BuildInfo::GetInstance()->package_name());
217 webapk->set_requester_application_version(version_info::GetVersionNumber());
218
219 webapk::WebAppManifest* web_app_manifest = webapk->mutable_manifest();
220 web_app_manifest->set_name(base::UTF16ToUTF8(shortcut_info_.name));
221 web_app_manifest->set_short_name(
222 base::UTF16ToUTF8(shortcut_info_.short_name));
223 web_app_manifest->set_start_url(shortcut_info_.url.spec());
224 web_app_manifest->set_orientation(
225 OrientationToString(shortcut_info_.orientation));
226 web_app_manifest->set_display_mode(DisplayToString(shortcut_info_.display));
227 web_app_manifest->set_background_color(
228 ColorToString(shortcut_info_.background_color));
229 web_app_manifest->set_theme_color(ColorToString(shortcut_info_.theme_color));
230
231 std::string* scope = web_app_manifest->add_scopes();
232 scope->assign(GetScope(shortcut_info_).spec());
233 webapk::Image* image = web_app_manifest->add_icons();
234 image->set_src(shortcut_info_.icon_url.spec());
235 // TODO(pkotwicz): Get MD5 hash of untransformed icon's bytes (with no
236 // encoding/decoding).
237 image->set_hash(ComputeBitmapHash(shortcut_icon_));
238 std::vector<unsigned char> png_bytes;
239 gfx::PNGCodec::EncodeBGRASkBitmap(shortcut_icon_, false, &png_bytes);
240 image->set_image_data(&png_bytes.front(), png_bytes.size());
241
242 return request;
243 }
244
245 void WebApkBuilder::OnTimeout() {
246 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
247 OnFailure();
Yaron 2016/07/20 13:13:50 should this be posted to ui thread? I thought succ
pkotwicz 2016/07/23 00:11:04 WebApkBuilder is created and started on the IO thr
248 }
249
250 void WebApkBuilder::OnSuccess() {
251 finish_callback_.Run(true);
252 delete this;
253 }
254
255 void WebApkBuilder::OnFailure() {
256 finish_callback_.Run(false);
257 delete this;
258 }
OLDNEW
« no previous file with comments | « chrome/browser/android/webapk/webapk_builder.h ('k') | chrome/browser/android/webapk/webapk_builder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698