Home | History | Annotate | Download | only in metro_driver
      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   };
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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