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

Side by Side Diff: chrome/browser/chromeos/first_run/drive_opt_in_controller.cc

Issue 55423004: Enable Google Drive offline mode automatically on first run. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/browser/chromeos/first_run/drive_opt_in_controller.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/background/background_contents_service.h"
10 #include "chrome/browser/background/background_contents_service_factory.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/login/user_manager.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_system.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/tab_contents/background_contents.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/site_instance.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_contents_observer.h"
28 #include "url/gurl.h"
29
30 namespace chromeos {
31
32 namespace {
33
34 // The initial time to wait in seconds before starting the opt-in.
35 const int kInitialDelaySeconds = 180;
36
37 // Time to wait for Drive app background page to come up before giving up.
38 const int kWebContentsTimeoutSeconds = 15;
39
40 // Google Drive offline opt-in endpoint.
41 const char kDriveOfflineOptInUrl[] = "http://drive.google.com";
42
43 // Google Drive app id.
44 const char kDriveHostedAppId[] = "apdfllckaahabafndbhieahigkjlhalf";
45
46 } // namespace
47
48 ////////////////////////////////////////////////////////////////////////////////
49 // DriveOptInWebContentsManager
50
51 // Manages web contents that does Google Drive offline opt-in. We create
52 // a background WebContents that loads a Drive endpoint to initialize offline
53 // mode. If successful, a background page will be opened to do sync the user's
achuithb 2013/11/01 19:25:15 "do" unnecessary
Tim Song 2013/11/02 00:13:14 Done.
54 // files for offline use.
55 class DriveOptInWebContentsManager : public content::WebContentsObserver,
56 public content::WebContentsDelegate,
57 public content::NotificationObserver {
58 public:
59 DriveOptInWebContentsManager(Profile* profile,
60 DriveOptInController* controller);
61 ~DriveOptInWebContentsManager();
achuithb 2013/11/01 19:25:15 virtual
Tim Song 2013/11/02 00:13:14 Done.
62
63 void StartLoad();
64 void StopLoad();
65
66 private:
67 void OnOptInSuccess();
68 void OnOptInFailure();
69
70 // content::WebContentsObserver overrides:
71 virtual void DidFailProvisionalLoad(
72 int64 frame_id,
73 const string16& frame_unique_name,
74 bool is_main_frame,
75 const GURL& validated_url,
76 int error_code,
77 const string16& error_description,
78 content::RenderViewHost* render_view_host) OVERRIDE;
79
80 virtual void DidFailLoad(int64 frame_id,
81 const GURL& validated_url,
82 bool is_main_frame,
83 int error_code,
84 const string16& error_description,
85 content::RenderViewHost* render_view_host);
achuithb 2013/11/01 19:25:15 OVERRIDE
Tim Song 2013/11/02 00:13:14 Done.
86
87 // content::WebContentsDelegate overrides:
88 virtual bool ShouldCreateWebContents(
89 content::WebContents* web_contents,
90 int route_id,
91 WindowContainerType window_container_type,
92 const string16& frame_name,
93 const GURL& target_url,
94 const std::string& partition_id,
95 content::SessionStorageNamespace* session_storage_namespace) OVERRIDE;
96
97 // content::NotificationObserver overrides:
98 virtual void Observe(int type,
99 const content::NotificationSource& source,
100 const content::NotificationDetails& details) OVERRIDE;
101
102 Profile* profile_;
103 DriveOptInController* controller_;
104 scoped_ptr<content::WebContents> web_contents_;
105 content::NotificationRegistrar registrar_;
106 bool started_;
107
108 DISALLOW_COPY_AND_ASSIGN(DriveOptInWebContentsManager);
109 };
110
111 DriveOptInWebContentsManager::DriveOptInWebContentsManager(
112 Profile* profile, DriveOptInController* controller)
113 : profile_(profile),
114 controller_(controller),
115 started_(false) {
116 registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
117 content::Source<Profile>(profile_));
118 }
119
120 DriveOptInWebContentsManager::~DriveOptInWebContentsManager() {
121 }
122
123 void DriveOptInWebContentsManager::StartLoad() {
124 started_ = true;
125 GURL url(kDriveOfflineOptInUrl);
achuithb 2013/11/01 19:25:15 const?
Tim Song 2013/11/02 00:13:14 Done.
126 content::WebContents::CreateParams create_params(
127 profile_, content::SiteInstance::CreateForURL(profile_, url));
128
129 web_contents_.reset(content::WebContents::Create(create_params));
130 web_contents_->SetDelegate(this);
131
132 content::NavigationController::LoadURLParams load_params(url);
133 load_params.transition_type = content::PAGE_TRANSITION_GENERATED;
134 web_contents_->GetController().LoadURLWithParams(load_params);
135
136 content::WebContentsObserver::Observe(web_contents_.get());
137 }
138
139 void DriveOptInWebContentsManager::StopLoad() {
140 started_ = false;
141 }
142
143 void DriveOptInWebContentsManager::OnOptInSuccess() {
144 if (started_) {
145 base::MessageLoop::current()->PostTask(
146 FROM_HERE,
147 base::Bind(&DriveOptInController::OnOptInSuccess,
148 base::Unretained(controller_)));
149 StopLoad();
150 }
151 }
152
153 void DriveOptInWebContentsManager::OnOptInFailure() {
154 if (started_) {
155 base::MessageLoop::current()->PostTask(
156 FROM_HERE,
157 base::Bind(&DriveOptInController::OnOptInFailure,
158 base::Unretained(controller_)));
159 StopLoad();
160 }
161 }
162
163 void DriveOptInWebContentsManager::DidFailProvisionalLoad(
164 int64 frame_id,
165 const string16& frame_unique_name,
166 bool is_main_frame,
167 const GURL& validated_url,
168 int error_code,
169 const string16& error_description,
170 content::RenderViewHost* render_view_host) {
171 OnOptInFailure();
172 }
173
174 void DriveOptInWebContentsManager::DidFailLoad(
175 int64 frame_id,
176 const GURL& validated_url,
177 bool is_main_frame,
178 int error_code,
179 const string16& error_description,
180 content::RenderViewHost* render_view_host) OVERRIDE {
181 OnOptInFailure();
182 }
183
184 // content::WebContentsDelegate overrides:
achuithb 2013/11/01 19:25:15 don't think you need this
Tim Song 2013/11/02 00:13:14 Done.
185 bool DriveOptInWebContentsManager::ShouldCreateWebContents(
186 content::WebContents* web_contents,
187 int route_id,
188 WindowContainerType window_container_type,
189 const string16& frame_name,
190 const GURL& target_url,
191 const std::string& partition_id,
192 content::SessionStorageNamespace* session_storage_namespace) OVERRIDE {
achuithb 2013/11/01 19:25:15 don't think you need OVERRIDE here
Tim Song 2013/11/02 00:13:14 Done.
193
194 if (window_container_type == WINDOW_CONTAINER_TYPE_NORMAL)
195 return true;
196
197 // Check that the target URL is for the Drive app.
198 ExtensionService* service =
199 extensions::ExtensionSystem::Get(profile_)->extension_service();
200 const extensions::Extension *extension =
201 service->GetInstalledApp(target_url);
202 if (!extension || extension->id() != kDriveHostedAppId)
203 return true;
204
205 // The background contents creation is normally done in Browser, but
206 // because we're using a detached WebContents, we need to do it ourselves.
207 BackgroundContentsService* background_contents_service =
208 BackgroundContentsServiceFactory::GetForProfile(profile_);
209
210 // Prevent redirection if background contents already exists.
211 if (background_contents_service->GetAppBackgroundContents(
212 UTF8ToUTF16(kDriveHostedAppId))) {
213 return false;
214 }
215 BackgroundContents* contents = background_contents_service
216 ->CreateBackgroundContents(content::SiteInstance::Create(profile_),
217 route_id,
218 profile_,
219 frame_name,
220 ASCIIToUTF16(kDriveHostedAppId),
221 partition_id,
222 session_storage_namespace);
223
224 contents->web_contents()->GetController().LoadURL(
225 target_url,
226 content::Referrer(),
227 content::PAGE_TRANSITION_LINK,
228 std::string());
229
230 // Return false as we already created the WebContents here.
231 return false;
232 }
233
234 // content::NotificationObserver overrides:
achuithb 2013/11/01 19:25:15 don't think you need this
Tim Song 2013/11/02 00:13:14 Done.
235 void DriveOptInWebContentsManager::Observe(
236 int type,
237 const content::NotificationSource& source,
238 const content::NotificationDetails& details) OVERRIDE {
239 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED) {
240 std::string app_id = UTF16ToUTF8(
achuithb 2013/11/01 19:25:15 const?
Tim Song 2013/11/02 00:13:14 Done.
241 content::Details<BackgroundContentsOpenedDetails>(details)
242 ->application_id);
243 if (app_id == kDriveHostedAppId) {
achuithb 2013/11/01 19:25:15 don't need {}
Tim Song 2013/11/02 00:13:14 Done.
244 OnOptInSuccess();
245 }
246 }
247 }
248
249 ////////////////////////////////////////////////////////////////////////////////
250 // DriveOptInController
251
252 DriveOptInController::DriveOptInController()
253 : profile_(ProfileManager::GetDefaultProfile()),
254 initial_delay_done_(false) {
255 }
256
257 DriveOptInController::~DriveOptInController() {
258 }
259
260 void DriveOptInController::StartOfflineOptIn() {
261 if (!initial_delay_done_) {
262 initial_delay_done_ = true;
263 initial_delay_timer_.Start(
264 FROM_HERE,
265 base::TimeDelta::FromSeconds(kInitialDelaySeconds),
266 this,
267 &DriveOptInController::StartOfflineOptIn);
268 }
269
270 if (!UserManager::Get()->IsLoggedInAsRegularUser()) {
271 LOG(ERROR) << "Attempting to opt-in but not logged in a regular user.";
272 OnOptInFailure();
273 return;
274 }
275
276 ExtensionService* extension_service =
277 extensions::ExtensionSystem::Get(profile_)->extension_service();
278 if (!extension_service->GetExtensionById(kDriveHostedAppId, false)) {
279 LOG(WARNING) << "Drive app not is not installed.";
280 OnOptInFailure();
281 return;
282 }
283
284 BackgroundContentsService* background_contents_service =
285 BackgroundContentsServiceFactory::GetForProfile(profile_);
286 if (background_contents_service->GetAppBackgroundContents(
287 UTF8ToUTF16(kDriveHostedAppId))) {
288 LOG(WARNING) << "Background page for Drive app already exists";
289 OnOptInFailure();
290 return;
291 }
292
293 web_contents_manager_.reset(
294 new DriveOptInWebContentsManager(profile_, this));
295 web_contents_manager_->StartLoad();
296 web_contents_timer_.Start(
297 FROM_HERE,
298 base::TimeDelta::FromSeconds(kWebContentsTimeoutSeconds),
299 this,
300 &DriveOptInController::OnWebContentsTimedOut);
301 }
302
303 void DriveOptInController::OnWebContentsTimedOut() {
304 LOG(WARNING) << "Timed out waiting for web contents to opt-in";
305 OnOptInFailure();
306 }
307
308 void DriveOptInController::CleanUp() {
309 if (web_contents_manager_)
310 web_contents_manager_->StopLoad();
311 web_contents_timer_.Stop();
312 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
313 }
314
315 void DriveOptInController::OnOptInSuccess() {
316 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
317 // TODO(tengs): Notify ash system tray to display notice that Drive
318 // offline opt-in has occurred. See crbug.com/311452.
319 CleanUp();
320 }
321
322 void DriveOptInController::OnOptInFailure() {
323 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
324 CleanUp();
325 }
326
327 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698