1// Copyright (c) 2012 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/dbus/printer_service_provider.h"
6
7#include "ash/session/session_state_delegate.h"
8#include "ash/shell.h"
9#include "ash/wm/window_util.h"
10#include "base/bind.h"
11#include "base/bind_helpers.h"
12#include "base/metrics/histogram.h"
13#include "base/strings/stringprintf.h"
14#include "chrome/browser/profiles/profile_manager.h"
15#include "chrome/browser/ui/browser.h"
16#include "chrome/browser/ui/browser_tabstrip.h"
17#include "chrome/browser/ui/browser_window.h"
18#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
19#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
20#include "chrome/browser/ui/tabs/tab_strip_model.h"
21#include "content/public/browser/browser_thread.h"
22#include "content/public/browser/web_contents.h"
23#include "dbus/bus.h"
24#include "dbus/exported_object.h"
25#include "dbus/message.h"
26#include "net/base/escape.h"
27#include "third_party/cros_system_api/dbus/service_constants.h"
28#include "ui/aura/window.h"
29
30namespace {
31
32const char kPrinterAdded[] = "PrinterAdded";
33
34enum PrinterServiceEvent {
35  PRINTER_ADDED,
36  PAGE_DISPLAYED,
37  PRINTER_SERVICE_EVENT_MAX,
38};
39
40// TODO(vitalybuka): update URL with more relevant information.
41const char kCloudPrintLearnUrl[] =
42    "https://www.google.com/landing/cloudprint/index.html";
43
44void ActivateContents(Browser* browser, content::WebContents* contents) {
45  browser->tab_strip_model()->ActivateTabAt(
46      browser->tab_strip_model()->GetIndexOfWebContents(contents), false);
47}
48
49Browser* ActivateAndGetBrowserForUrl(GURL url) {
50  for (TabContentsIterator it; !it.done(); it.Next()) {
51    if (it->GetLastCommittedURL() == url) {
52      ActivateContents(it.browser(), *it);
53      return it.browser();
54    }
55  }
56  return NULL;
57}
58
59void FindOrOpenCloudPrintPage(const std::string& /* vendor */,
60                              const std::string& /* product */) {
61  UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent", PRINTER_ADDED,
62                            PRINTER_SERVICE_EVENT_MAX);
63  if (!ash::Shell::GetInstance()->session_state_delegate()->
64          IsActiveUserSessionStarted() ||
65      ash::Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) {
66    return;
67  }
68
69  Profile* profile = ProfileManager::GetLastUsedProfile();
70  if (!profile)
71    return;
72
73  GURL url(kCloudPrintLearnUrl);
74
75  if (!ActivateAndGetBrowserForUrl(url)) {
76    chrome::ScopedTabbedBrowserDisplayer displayer(
77        profile, chrome::HOST_DESKTOP_TYPE_ASH);
78    UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent",
79                              PAGE_DISPLAYED, PRINTER_SERVICE_EVENT_MAX);
80    chrome::AddSelectedTabWithURL(displayer.browser(), url,
81                                  ui::PAGE_TRANSITION_LINK);
82  }
83}
84
85}  // namespace
86
87namespace chromeos {
88
89PrinterServiceProvider::PrinterServiceProvider()
90    : weak_ptr_factory_(this) {
91}
92
93PrinterServiceProvider::~PrinterServiceProvider() {
94}
95
96void PrinterServiceProvider::Start(
97    scoped_refptr<dbus::ExportedObject> exported_object) {
98
99  exported_object_ = exported_object;
100  DVLOG(1) << "PrinterServiceProvider started";
101  exported_object_->ExportMethod(
102      kLibCrosServiceInterface,
103      kPrinterAdded,
104      base::Bind(&PrinterServiceProvider::PrinterAdded,
105                 weak_ptr_factory_.GetWeakPtr()),
106      base::Bind(&PrinterServiceProvider::OnExported,
107                 weak_ptr_factory_.GetWeakPtr()));
108}
109
110void PrinterServiceProvider::OnExported(
111    const std::string& interface_name,
112    const std::string& method_name,
113    bool success) {
114  if (!success) {
115    LOG(ERROR) << "Failed to export " << interface_name << "."
116               << method_name;
117  }
118  DVLOG(1) << "Method exported: " << interface_name << "." << method_name;
119}
120
121void PrinterServiceProvider::ShowCloudPrintHelp(const std::string& vendor,
122                                                const std::string& product) {
123  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
124                                   base::Bind(&FindOrOpenCloudPrintPage, vendor,
125                                              product));
126}
127
128void PrinterServiceProvider::PrinterAdded(
129    dbus::MethodCall* method_call,
130    dbus::ExportedObject::ResponseSender response_sender) {
131  DVLOG(1) << "PrinterAdded " << method_call->ToString();
132
133  dbus::MessageReader reader(method_call);
134  std::string vendor;
135  std::string product;
136  // Don't check for error, parameters are optional. If some string is empty
137  // web server will show generic help page.
138  reader.PopString(&vendor);
139  reader.PopString(&product);
140  ShowCloudPrintHelp(vendor, product);
141
142  // Send an empty response.
143  response_sender.Run(dbus::Response::FromMethodCall(method_call));
144}
145
146}  // namespace chromeos
147
148