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
5#include "chrome/browser/chromeos/login/signin/merge_session_load_page.h"
6
7#include "ash/shell.h"
8#include "ash/shell_delegate.h"
9#include "ash/system/tray/system_tray_delegate.h"
10#include "base/i18n/rtl.h"
11#include "base/metrics/histogram.h"
12#include "base/strings/string_piece.h"
13#include "base/strings/stringprintf.h"
14#include "base/strings/utf_string_conversions.h"
15#include "base/values.h"
16#include "chrome/browser/chrome_notification_types.h"
17#include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
18#include "chrome/browser/extensions/extension_service.h"
19#include "chrome/browser/profiles/profile.h"
20#include "chrome/browser/renderer_preferences_util.h"
21#include "chrome/browser/tab_contents/tab_util.h"
22#include "chrome/common/extensions/extension_constants.h"
23#include "chrome/common/url_constants.h"
24#include "content/public/browser/browser_thread.h"
25#include "content/public/browser/interstitial_page.h"
26#include "content/public/browser/notification_types.h"
27#include "content/public/browser/web_contents.h"
28#include "extensions/browser/extension_system.h"
29#include "extensions/common/extension.h"
30#include "extensions/common/extension_icon_set.h"
31#include "grit/browser_resources.h"
32#include "grit/generated_resources.h"
33#include "net/base/escape.h"
34#include "ui/base/l10n/l10n_util.h"
35#include "ui/base/resource/resource_bundle.h"
36#include "ui/base/webui/jstemplate_builder.h"
37
38using content::BrowserThread;
39using content::InterstitialPage;
40using content::WebContents;
41
42namespace {
43
44// Delay time for showing interstitial page.
45const int kShowDelayTimeMS = 1000;
46
47// Maximum time for showing interstitial page.
48const int kTotalWaitTimeMS = 10000;
49
50}  // namespace
51
52namespace chromeos {
53
54MergeSessionLoadPage::MergeSessionLoadPage(
55    WebContents* web_contents,
56    const GURL& url,
57    const MergeSessionThrottle::CompletionCallback& callback)
58    : callback_(callback),
59      proceeded_(false),
60      web_contents_(web_contents),
61      url_(url) {
62  interstitial_page_ = InterstitialPage::Create(web_contents, true, url, this);
63}
64
65MergeSessionLoadPage::~MergeSessionLoadPage() {
66  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67}
68
69void MergeSessionLoadPage::Show() {
70  OAuth2LoginManager* manager = GetOAuth2LoginManager();
71  if (manager && manager->ShouldBlockTabLoading()) {
72    manager->AddObserver(this);
73    interstitial_page_->Show();
74  } else {
75    interstitial_page_->Proceed();
76  }
77}
78
79std::string MergeSessionLoadPage::GetHTMLContents() {
80  base::DictionaryValue strings;
81  strings.SetString("title", web_contents_->GetTitle());
82  // Set the timeout to show the page.
83  strings.SetInteger("show_delay_time", kShowDelayTimeMS);
84  strings.SetInteger("total_wait_time", kTotalWaitTimeMS);
85  // TODO(zelidrag): Flip the message to IDS_MERGE_SESSION_LOAD_HEADLINE
86  // after merge.
87  strings.SetString("heading",
88                    l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE));
89
90  bool rtl = base::i18n::IsRTL();
91  strings.SetString("textdirection", rtl ? "rtl" : "ltr");
92
93  base::StringPiece html(
94      ResourceBundle::GetSharedInstance().GetRawDataResource(
95          IDR_MERGE_SESSION_LOAD_HTML));
96  return webui::GetI18nTemplateHtml(html, &strings);
97}
98
99void MergeSessionLoadPage::OverrideRendererPrefs(
100      content::RendererPreferences* prefs) {
101  Profile* profile = Profile::FromBrowserContext(
102      web_contents_->GetBrowserContext());
103  renderer_preferences_util::UpdateFromSystemSettings(prefs, profile);
104}
105
106void MergeSessionLoadPage::OnProceed() {
107  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
108  proceeded_ = true;
109  NotifyBlockingPageComplete();
110}
111
112void MergeSessionLoadPage::OnDontProceed() {
113  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
114  // Ignore if it's already proceeded.
115  if (proceeded_)
116    return;
117  NotifyBlockingPageComplete();
118}
119
120void MergeSessionLoadPage::CommandReceived(const std::string& cmd) {
121  std::string command(cmd);
122  // The Jasonified response has quotes, remove them.
123  if (command.length() > 1 && command[0] == '"')
124    command = command.substr(1, command.length() - 2);
125
126  if (command == "proceed") {
127    interstitial_page_->Proceed();
128  } else {
129    DVLOG(1) << "Unknown command:" << cmd;
130  }
131}
132
133void MergeSessionLoadPage::NotifyBlockingPageComplete() {
134  OAuth2LoginManager* manager = GetOAuth2LoginManager();
135  if (manager)
136    manager->RemoveObserver(this);
137
138  if (!callback_.is_null()) {
139    BrowserThread::PostTask(
140        BrowserThread::IO, FROM_HERE, callback_);
141  }
142}
143
144OAuth2LoginManager* MergeSessionLoadPage::GetOAuth2LoginManager() {
145  content::BrowserContext* browser_context = web_contents_->GetBrowserContext();
146  if (!browser_context)
147    return NULL;
148
149  Profile* profile = Profile::FromBrowserContext(browser_context);
150  if (!profile)
151    return NULL;
152
153  return OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile);
154}
155
156void MergeSessionLoadPage::OnSessionRestoreStateChanged(
157    Profile* user_profile, OAuth2LoginManager::SessionRestoreState state) {
158  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159
160  OAuth2LoginManager* manager = GetOAuth2LoginManager();
161  DVLOG(1) << "Merge session should "
162           << (!manager->ShouldBlockTabLoading() ?
163                  " NOT " : "")
164           << " be blocking now, "
165           << state;
166  if (!manager->ShouldBlockTabLoading()) {
167    manager->RemoveObserver(this);
168    interstitial_page_->Proceed();
169  }
170}
171
172}  // namespace chromeos
173