• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "stdafx.h"
6 #include "secondary_tile.h"
7 
8 #include <windows.ui.startscreen.h>
9 
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "url/gurl.h"
14 #include "win8/metro_driver/chrome_app_view.h"
15 #include "win8/metro_driver/winrt_utils.h"
16 
17 namespace {
18 
19 using base::win::MetroPinUmaResultCallback;
20 
21 // Callback for asynchronous pin requests.
22 class TileRequestCompleter {
23  public:
24   enum PinType {
25     PIN,
26     UNPIN
27   };
TileRequestCompleter(PinType type,const MetroPinUmaResultCallback & callback)28   TileRequestCompleter(PinType type, const MetroPinUmaResultCallback& callback)
29       : type_(type), callback_(callback) {}
30 
31   void Complete(mswr::ComPtr<winfoundtn::IAsyncOperation<bool>>& completion);
32 
33  private:
34   // Callback that responds to user input on the pin request pop-up. This will
35   // run |callback_|, then delete |this| before returning.
36   HRESULT Respond(winfoundtn::IAsyncOperation<bool>* async,
37                   AsyncStatus status);
38 
39   PinType type_;
40   MetroPinUmaResultCallback callback_;
41 };
42 
Complete(mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> & completion)43 void TileRequestCompleter::Complete(
44     mswr::ComPtr<winfoundtn::IAsyncOperation<bool>>& completion) {
45   typedef winfoundtn::IAsyncOperationCompletedHandler<bool> RequestDoneType;
46   mswr::ComPtr<RequestDoneType> handler(mswr::Callback<RequestDoneType>(
47       this, &TileRequestCompleter::Respond));
48   DCHECK(handler.Get() != NULL);
49   HRESULT hr = completion->put_Completed(handler.Get());
50   CheckHR(hr, "Failed to put_Completed");
51 }
52 
Respond(winfoundtn::IAsyncOperation<bool> * async,AsyncStatus status)53 HRESULT TileRequestCompleter::Respond(winfoundtn::IAsyncOperation<bool>* async,
54                                  AsyncStatus status) {
55   base::win::MetroSecondaryTilePinUmaResult pin_state =
56       base::win::METRO_PIN_STATE_NONE;
57 
58   if (status == Completed) {
59     unsigned char result;
60     CheckHR(async->GetResults(&result));
61     LOG(INFO) << __FUNCTION__ << " result " << static_cast<int>(result);
62     switch (result) {
63       case 0:
64         pin_state = type_ == PIN ?
65             base::win::METRO_PIN_RESULT_CANCEL :
66             base::win::METRO_UNPIN_RESULT_CANCEL;
67         break;
68       case 1:
69         pin_state = type_ == PIN ?
70             base::win::METRO_PIN_RESULT_OK :
71             base::win::METRO_UNPIN_RESULT_OK;
72         break;
73       default:
74         pin_state = type_ == PIN ?
75             base::win::METRO_PIN_RESULT_OTHER :
76             base::win::METRO_UNPIN_RESULT_OTHER;
77         break;
78     }
79   } else {
80     LOG(ERROR) << __FUNCTION__ << " Unexpected async status "
81                << static_cast<int>(status);
82     pin_state = type_ == PIN ?
83         base::win::METRO_PIN_RESULT_ERROR :
84         base::win::METRO_UNPIN_RESULT_ERROR;
85   }
86   callback_.Run(pin_state);
87 
88   delete this;
89   return S_OK;
90 }
91 
DeleteTileFromStartScreen(const base::string16 & tile_id,const MetroPinUmaResultCallback & callback)92 void DeleteTileFromStartScreen(const base::string16& tile_id,
93                                const MetroPinUmaResultCallback& callback) {
94   DVLOG(1) << __FUNCTION__;
95   mswr::ComPtr<winui::StartScreen::ISecondaryTileFactory> tile_factory;
96   HRESULT hr = winrt_utils::CreateActivationFactory(
97       RuntimeClass_Windows_UI_StartScreen_SecondaryTile,
98       tile_factory.GetAddressOf());
99   CheckHR(hr, "Failed to create instance of ISecondaryTileFactory");
100 
101   mswrw::HString id;
102   id.Attach(MakeHString(tile_id));
103 
104   mswr::ComPtr<winui::StartScreen::ISecondaryTile> tile;
105   hr = tile_factory->CreateWithId(id.Get(), tile.GetAddressOf());
106   CheckHR(hr, "Failed to create tile");
107 
108   mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> completion;
109   hr = tile->RequestDeleteAsync(completion.GetAddressOf());
110   CheckHR(hr, "RequestDeleteAsync failed");
111 
112   if (FAILED(hr)) {
113     callback.Run(base::win::METRO_UNPIN_REQUEST_SHOW_ERROR);
114     return;
115   }
116 
117   // Deleted in TileRequestCompleter::Respond when the async operation
118   // completes.
119   TileRequestCompleter* completer =
120       new TileRequestCompleter(TileRequestCompleter::UNPIN, callback);
121   completer->Complete(completion);
122 }
123 
CreateTileOnStartScreen(const base::string16 & tile_id,const base::string16 & title_str,const base::string16 & url_str,const base::FilePath & logo_path,const MetroPinUmaResultCallback & callback)124 void CreateTileOnStartScreen(const base::string16& tile_id,
125                              const base::string16& title_str,
126                              const base::string16& url_str,
127                              const base::FilePath& logo_path,
128                              const MetroPinUmaResultCallback& callback) {
129   VLOG(1) << __FUNCTION__;
130 
131   mswr::ComPtr<winui::StartScreen::ISecondaryTileFactory> tile_factory;
132   HRESULT hr = winrt_utils::CreateActivationFactory(
133       RuntimeClass_Windows_UI_StartScreen_SecondaryTile,
134       tile_factory.GetAddressOf());
135   CheckHR(hr, "Failed to create instance of ISecondaryTileFactory");
136 
137   winui::StartScreen::TileOptions options =
138       winui::StartScreen::TileOptions_ShowNameOnLogo;
139   mswrw::HString title;
140   title.Attach(MakeHString(title_str));
141 
142   mswrw::HString id;
143   id.Attach(MakeHString(tile_id));
144 
145   mswrw::HString args;
146   // The url is just passed into the tile agruments as is. Metro and desktop
147   // chrome will see the arguments as command line parameters.
148   // A GURL is used to ensure any spaces are properly escaped.
149   GURL url(url_str);
150   args.Attach(MakeHString(base::UTF8ToUTF16(url.spec())));
151 
152   mswr::ComPtr<winfoundtn::IUriRuntimeClassFactory> uri_factory;
153   hr = winrt_utils::CreateActivationFactory(
154       RuntimeClass_Windows_Foundation_Uri,
155       uri_factory.GetAddressOf());
156   CheckHR(hr, "Failed to create URIFactory");
157 
158   mswrw::HString logo_url;
159   logo_url.Attach(
160       MakeHString(base::string16(L"file:///").append(logo_path.value())));
161   mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri;
162   hr = uri_factory->CreateUri(logo_url.Get(), &uri);
163   CheckHR(hr, "Failed to create URI");
164 
165   mswr::ComPtr<winui::StartScreen::ISecondaryTile> tile;
166   hr = tile_factory->CreateTile(id.Get(),
167                                 title.Get(),
168                                 title.Get(),
169                                 args.Get(),
170                                 options,
171                                 uri.Get(),
172                                 tile.GetAddressOf());
173   CheckHR(hr, "Failed to create tile");
174 
175   hr = tile->put_ForegroundText(winui::StartScreen::ForegroundText_Light);
176   CheckHR(hr, "Failed to change foreground text color");
177 
178   mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> completion;
179   hr = tile->RequestCreateAsync(completion.GetAddressOf());
180   CheckHR(hr, "RequestCreateAsync failed");
181 
182   if (FAILED(hr)) {
183     callback.Run(base::win::METRO_PIN_REQUEST_SHOW_ERROR);
184     return;
185   }
186 
187   // Deleted in TileRequestCompleter::Respond when the async operation
188   // completes.
189   TileRequestCompleter* completer =
190       new TileRequestCompleter(TileRequestCompleter::PIN, callback);
191   completer->Complete(completion);
192 }
193 
194 }  // namespace
195 
MetroIsPinnedToStartScreen(const base::string16 & tile_id)196 BOOL MetroIsPinnedToStartScreen(const base::string16& tile_id) {
197   mswr::ComPtr<winui::StartScreen::ISecondaryTileStatics> tile_statics;
198   HRESULT hr = winrt_utils::CreateActivationFactory(
199       RuntimeClass_Windows_UI_StartScreen_SecondaryTile,
200       tile_statics.GetAddressOf());
201   CheckHR(hr, "Failed to create instance of ISecondaryTileStatics");
202 
203   boolean exists;
204   hr = tile_statics->Exists(MakeHString(tile_id), &exists);
205   CheckHR(hr, "ISecondaryTileStatics.Exists failed");
206   return exists;
207 }
208 
MetroUnPinFromStartScreen(const base::string16 & tile_id,const MetroPinUmaResultCallback & callback)209 void MetroUnPinFromStartScreen(const base::string16& tile_id,
210                                const MetroPinUmaResultCallback& callback) {
211   globals.appview_msg_loop->PostTask(
212       FROM_HERE, base::Bind(&DeleteTileFromStartScreen,
213                             tile_id,
214                             callback));
215 }
216 
MetroPinToStartScreen(const base::string16 & tile_id,const base::string16 & title,const base::string16 & url,const base::FilePath & logo_path,const MetroPinUmaResultCallback & callback)217 void MetroPinToStartScreen(const base::string16& tile_id,
218                            const base::string16& title,
219                            const base::string16& url,
220                            const base::FilePath& logo_path,
221                            const MetroPinUmaResultCallback& callback) {
222   globals.appview_msg_loop->PostTask(
223     FROM_HERE, base::Bind(&CreateTileOnStartScreen,
224                           tile_id,
225                           title,
226                           url,
227                           logo_path,
228                           callback));
229 }
230