Bug 831609 - Provide support for determining activaiton URI from WinRT. r=jimm
authorBrian R. Bondy <netzen@gmail.com>
Fri, 15 Mar 2013 15:26:56 -0400
changeset 135364 85952c1d69b99e58f7661c96ab57b852f00c9b67
parent 135363 0f15f3f1ec62b499d2f11b92fa5c021d06d8f05f
child 135365 84b7697121397f730d90d5eb6fec1297b5dbbaae
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs831609
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 831609 - Provide support for determining activaiton URI from WinRT. r=jimm
widget/nsIWinMetroUtils.idl
widget/windows/winrt/FrameworkView.cpp
widget/windows/winrt/FrameworkView.h
widget/windows/winrt/MetroContracts.cpp
widget/windows/winrt/nsWinMetroUtils.cpp
--- a/widget/nsIWinMetroUtils.idl
+++ b/widget/nsIWinMetroUtils.idl
@@ -7,17 +7,17 @@
 
 /**
  * Integration with the "Metro"/"Modern" UI environment in Windows 8.
  *
  * Note: browser/metro/base/content/browser-scripts.js contains a stub
  * implementation of this interface for non-Windows systems, for testing and
  * development purposes only.
  */
-[scriptable, uuid(774a4b83-27c3-4F62-8509-efa0dc923a03)]
+[scriptable, uuid(ac813696-3b0a-4259-bce1-1d078021ebbe)]
 interface nsIWinMetroUtils : nsISupports
 {
   /* Fullscreen landscape orientation */
   const long fullScreenLandscape = 0;
   /* Larger snapped state */
   const long filled = 1;
   /* Smaller snapped state */
   const long snapped = 2;
@@ -40,16 +40,21 @@ interface nsIWinMetroUtils : nsISupports
   readonly attribute boolean immersive;
 
   /**
    * Determine if the user prefers left handed or right handed input.
    */
   readonly attribute long handPreference;
 
   /**
+   * Determine the activation URI
+   */
+  readonly attribute AString activationURI;
+
+  /**
    * Attempts to unsnap the application from snapped state to filled state
    */
    void unsnap();
 
 
    /**
     * Show the settings flyout
     */
--- a/widget/windows/winrt/FrameworkView.cpp
+++ b/widget/windows/winrt/FrameworkView.cpp
@@ -101,20 +101,17 @@ FrameworkView::Load(HSTRING aEntryPoint)
 HRESULT
 FrameworkView::Run()
 {
   LogFunction();
 
   // XPCOM is initialized here. mWidget is also created.
   mMetroApp->Initialize();
 
-  if (mDeferredActivationEventArgs) {
-    RunStartupArgs(mDeferredActivationEventArgs.Get());
-    mDeferredActivationEventArgs = nullptr;
-  }
+  ProcessLaunchArguments();
 
   // Activate the window
   mWindow->Activate();
 
   UpdateWidgetSizeAndPosition();
 
   MetroUtils::GetViewState(mViewState);
 
@@ -339,23 +336,20 @@ FrameworkView::OnActivated(ICoreApplicat
                            IActivatedEventArgs* aArgs)
 {
   LogFunction();
   // If we're on startup, we want to wait for FrameworkView::Run to run because
   // XPCOM is not initialized yet and and we can't use nsICommandLineRunner
 
   ApplicationExecutionState state;
   aArgs->get_PreviousExecutionState(&state);
-  if (state != ApplicationExecutionState::ApplicationExecutionState_Terminated &&
-      state != ApplicationExecutionState::ApplicationExecutionState_ClosedByUser &&
-      state != ApplicationExecutionState::ApplicationExecutionState_NotRunning) {
-    RunStartupArgs(aArgs);
-  } else {
-    mDeferredActivationEventArgs = aArgs;
-  }
+  bool startup = state == ApplicationExecutionState::ApplicationExecutionState_Terminated ||
+                 state == ApplicationExecutionState::ApplicationExecutionState_ClosedByUser ||
+                 state == ApplicationExecutionState::ApplicationExecutionState_NotRunning;
+  ProcessActivationArgs(aArgs, startup);
   return S_OK;
 }
 
 HRESULT
 FrameworkView::OnSoftkeyboardHidden(IInputPane* aSender,
                                     IInputPaneVisibilityEventArgs* aArgs)
 {
   LogFunction();
--- a/widget/windows/winrt/FrameworkView.h
+++ b/widget/windows/winrt/FrameworkView.h
@@ -84,16 +84,17 @@ public:
   void ShutdownXPCOM();
   bool Render();
   bool Render(const nsIntRegion& aInvalidRegion);
   float GetDPI() { return mDPI; }
   ICoreWindow* GetCoreWindow() { return mWindow.Get(); }
   void SetWidget(MetroWidget* aWidget);
   MetroWidget* GetWidget() { return mWidget.Get(); }
   void GetBounds(nsIntRect &aRect);
+  void GetActivationURI(nsAString &aActivationURI) { aActivationURI = mActivationURI; }
   void SetCursor(ABI::Windows::UI::Core::CoreCursorType aCursorType, DWORD aCustomId = 0);
   void ClearCursor();
   bool IsEnabled() const;
   bool IsVisible() const;
 
   // Soft keyboard info for nsIWinMetroUtils
   static bool IsKeyboardVisible() { return sKeyboardIsVisible; }
   static ABI::Windows::Foundation::Rect KeyboardVisibleRect() { return sKeyboardRect; }
@@ -133,28 +134,29 @@ protected:
   HRESULT OnPlayToSourceRequested(IPlayToManager* aPane, IPlayToSourceRequestedEventArgs* aArgs);
   HRESULT OnSettingsCommandInvoked(IUICommand* aCommand);
   HRESULT OnPrintTaskRequested(IPrintManager* aMgr, IPrintTaskRequestedEventArgs* aArgs);
   HRESULT OnPrintTaskSourceRequested(IPrintTaskSourceRequestedArgs* aArgs);
 
 protected:
   void SetDpi(float aDpi);
   void UpdateWidgetSizeAndPosition();
-  void PerformURILoad(Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IUriRuntimeClass>& aURI);
+  void PerformURILoad(Microsoft::WRL::Wrappers::HString& aString);
   void PerformSearch(Microsoft::WRL::Wrappers::HString& aQuery);
   void PerformURILoadOrSearch(Microsoft::WRL::Wrappers::HString& aString);
   bool EnsureAutomationProviderCreated();
-  void SearchActivated(Microsoft::WRL::ComPtr<ISearchActivatedEventArgs>& aArgs);
-  void FileActivated(Microsoft::WRL::ComPtr<IFileActivatedEventArgs>& aArgs);
-  void LaunchActivated(Microsoft::WRL::ComPtr<ILaunchActivatedEventArgs>& aArgs);
-  void RunStartupArgs(IActivatedEventArgs* aArgs);
+  void SearchActivated(Microsoft::WRL::ComPtr<ISearchActivatedEventArgs>& aArgs, bool aStartup);
+  void FileActivated(Microsoft::WRL::ComPtr<IFileActivatedEventArgs>& aArgs, bool aStartup);
+  void LaunchActivated(Microsoft::WRL::ComPtr<ILaunchActivatedEventArgs>& aArgs, bool aStartup);
+  void ProcessActivationArgs(IActivatedEventArgs* aArgs, bool aStartup);
   void UpdateForWindowSizeChange();
   void SendActivationEvent();
   void UpdateLogicalDPI();
   void FireViewStateObservers();
+  void ProcessLaunchArguments();
 
   // Printing and preview
   void CreatePrintControl(IPrintDocumentPackageTarget* aDocPackageTarget, 
                           D2D1_PRINT_CONTROL_PROPERTIES* aPrintControlProperties);
   HRESULT ClosePrintControl();
   void PrintPage(uint32_t aPageNumber, D2D1_RECT_F aImageableArea,
                  D2D1_SIZE_F aPageSize, IStream* aPagePrintTicketStream);
   void AddEventHandlers();
@@ -176,18 +178,19 @@ private:
   EventRegistrationToken mPrintManager;
 
 private:
   nsRefPtr<gfxD2DSurface> mD2DWindowSurface;
   nsIntRect mWindowBounds; // in device-pixel coordinates
   float mDPI;
   bool mShuttingDown;
   bool mPainting;
+  nsAutoString mActivationURI;
+  nsAutoString mActivationCommandLine;
   Microsoft::WRL::ComPtr<IInspectable> mAutomationProvider;
-  Microsoft::WRL::ComPtr<IActivatedEventArgs> mDeferredActivationEventArgs;
   //Microsoft::WRL::ComPtr<ID2D1PrintControl> mD2DPrintControl;
   // Private critical section protects D2D device context for on-screen
   // rendering from that for print/preview in the different thread.
   //Microsoft::WRL::ComPtr<IWICImagingFactory2> mWicFactory;
   Microsoft::WRL::ComPtr<MetroApp> mMetroApp;
   Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
   Microsoft::WRL::ComPtr<ICoreDispatcher> mDispatcher;
   Microsoft::WRL::ComPtr<MetroWidget> mWidget;
--- a/widget/windows/winrt/MetroContracts.cpp
+++ b/widget/windows/winrt/MetroContracts.cpp
@@ -43,62 +43,92 @@ using namespace ABI::Windows::Graphics::
 
 namespace mozilla {
 namespace widget {
 namespace winrt {
 
 extern nsTArray<nsString>* sSettingsArray;
 
 void
-FrameworkView::SearchActivated(ComPtr<ISearchActivatedEventArgs>& aArgs)
+FrameworkView::SearchActivated(ComPtr<ISearchActivatedEventArgs>& aArgs, bool aStartup)
 {
   if (!aArgs)
     return;
 
   HString data;
   AssertHRESULT(aArgs->get_QueryText(data.GetAddressOf()));
   if (WindowsIsStringEmpty(data.Get()))
     return;
 
   unsigned int length;
   Log(L"SearchActivated text=", data.GetRawBuffer(&length));
-  PerformURILoadOrSearch(data);
+  if (aStartup) {
+    mActivationURI = data.GetRawBuffer(&length);
+  } else {
+    PerformURILoadOrSearch(data);
+  }
 }
 
 void
-FrameworkView::FileActivated(ComPtr<IFileActivatedEventArgs>& aArgs)
+FrameworkView::FileActivated(ComPtr<IFileActivatedEventArgs>& aArgs, bool aStartup)
 {
   if (!aArgs)
     return;
 
   ComPtr<IVectorView<ABI::Windows::Storage::IStorageItem*>> list;
   AssertHRESULT(aArgs->get_Files(list.GetAddressOf()));
   ComPtr<ABI::Windows::Storage::IStorageItem> item;
   AssertHRESULT(list->GetAt(0, item.GetAddressOf()));
   HString filePath;
   AssertHRESULT(item->get_Path(filePath.GetAddressOf()));
 
-  ComPtr<IUriRuntimeClass> uri;
-  AssertHRESULT(MetroUtils::CreateUri(filePath, uri));
-  PerformURILoad(uri);
+  if (aStartup) {
+    unsigned int length;
+    mActivationURI = filePath.GetRawBuffer(&length);
+  } else {
+    PerformURILoad(filePath);
+  }
 }
 
 void
-FrameworkView::LaunchActivated(ComPtr<ILaunchActivatedEventArgs>& aArgs)
+FrameworkView::LaunchActivated(ComPtr<ILaunchActivatedEventArgs>& aArgs, bool aStartup)
 {
   if (!aArgs)
     return;
   HString data;
   AssertHRESULT(aArgs->get_Arguments(data.GetAddressOf()));
   if (WindowsIsStringEmpty(data.Get()))
     return;
 
+  // If we're being launched from a secondary tile then we have a 2nd command line param of -url
+  // and a third of the secondary tile.  We want it in mActivationURI so that browser.js will
+  // load it in without showing the start UI.
   int argc;
   unsigned int length;
   LPWSTR* argv = CommandLineToArgvW(data.GetRawBuffer(&length), &argc);
+  if (aStartup && argc == 3 && !wcsicmp(argv[1], L"-url")) {
+    mActivationURI = argv[2];
+  } else {
+    // Some other command line or this is not a startup.
+    // If it is startup we process it later when XPCOM is initialilzed.
+    mActivationCommandLine = data.GetRawBuffer(&length);
+    if (!aStartup) {
+      ProcessLaunchArguments();
+    }
+  }
+}
+
+void
+FrameworkView::ProcessLaunchArguments()
+{
+  if (!mActivationCommandLine.Length())
+    return;
+
+  int argc;
+  LPWSTR* argv = CommandLineToArgvW(mActivationCommandLine.BeginReading(), &argc);
   nsCOMPtr<nsICommandLineRunner> cmdLine =
     (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
   if (!cmdLine) {
     NS_WARNING("Unable to instantiate command line runner.");
     return;
   }
 
   LPSTR *argvUTF8 = new LPSTR[argc];
@@ -121,44 +151,57 @@ FrameworkView::LaunchActivated(ComPtr<IL
 
   for (int i = 0; i < argc; ++i) {
     delete[] argvUTF8[i];
   }
   delete[] argvUTF8;
 }
 
 void
-FrameworkView::RunStartupArgs(IActivatedEventArgs* aArgs)
+FrameworkView::ProcessActivationArgs(IActivatedEventArgs* aArgs, bool aStartup)
 {
   ActivationKind kind;
   if (!aArgs || FAILED(aArgs->get_Kind(&kind)))
     return;
   ComPtr<IActivatedEventArgs> args(aArgs);
   if (kind == ActivationKind::ActivationKind_Protocol) {
     Log(L"Activation argument kind: Protocol");
     ComPtr<IProtocolActivatedEventArgs> protoArgs;
     AssertHRESULT(args.As(&protoArgs));
     ComPtr<IUriRuntimeClass> uri;
     AssertHRESULT(protoArgs->get_Uri(uri.GetAddressOf()));
-    PerformURILoad(uri);
+    if (!uri)
+      return;
+
+    HString data;
+    AssertHRESULT(uri->get_AbsoluteUri(data.GetAddressOf()));
+    if (WindowsIsStringEmpty(data.Get()))
+      return;
+
+    if (aStartup) {
+      unsigned int length;
+      mActivationURI = data.GetRawBuffer(&length);
+    } else {
+      PerformURILoad(data);
+    }
   } else if (kind == ActivationKind::ActivationKind_Search) {
     Log(L"Activation argument kind: Search");
     ComPtr<ISearchActivatedEventArgs> searchArgs;
     args.As(&searchArgs);
-    SearchActivated(searchArgs);
+    SearchActivated(searchArgs, aStartup);
   } else if (kind == ActivationKind::ActivationKind_File) {
     Log(L"Activation argument kind: File");
     ComPtr<IFileActivatedEventArgs> fileArgs;
     args.As(&fileArgs);
-    FileActivated(fileArgs);
+    FileActivated(fileArgs, aStartup);
   } else if (kind == ActivationKind::ActivationKind_Launch) {
     Log(L"Activation argument kind: Launch");
     ComPtr<ILaunchActivatedEventArgs> launchArgs;
     args.As(&launchArgs);
-    LaunchActivated(launchArgs);
+    LaunchActivated(launchArgs, aStartup);
   }
 }
 
 void
 FrameworkView::SetupContracts()
 {
   LogFunction();
   HRESULT hr;
@@ -210,38 +253,31 @@ FrameworkView::SetupContracts()
   AssertHRESULT(hr);
   ComPtr<IPrintManager> printManager;
   AssertHRESULT(printStatics->GetForCurrentView(printManager.GetAddressOf()));
   printManager->add_PrintTaskRequested(Callback<__FITypedEventHandler_2_Windows__CGraphics__CPrinting__CPrintManager_Windows__CGraphics__CPrinting__CPrintTaskRequestedEventArgs_t>(
     this, &FrameworkView::OnPrintTaskRequested).Get(), &mPrintManager);
 }
 
 void
-FrameworkView::PerformURILoad(ComPtr<IUriRuntimeClass>& aURI)
+FrameworkView::PerformURILoad(HString& aURI)
 {
   LogFunction();
-  if (!aURI)
-    return;
-
-  HString data;
-  AssertHRESULT(aURI->get_AbsoluteUri(data.GetAddressOf()));
-  if (WindowsIsStringEmpty(data.Get()))
-    return;
 
   unsigned int length;
-  Log(L"PerformURILoad uri=%s", data.GetRawBuffer(&length));
+  Log(L"PerformURILoad uri=%s", aURI.GetRawBuffer(&length));
 
   nsCOMPtr<nsICommandLineRunner> cmdLine =
     (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
   if (!cmdLine) {
     NS_WARNING("Unable to instantiate command line runner.");
     return;
   }
 
-  nsAutoCString utf8data(NS_ConvertUTF16toUTF8(data.GetRawBuffer(&length)));
+  nsAutoCString utf8data(NS_ConvertUTF16toUTF8(aURI.GetRawBuffer(&length)));
   const char *argv[] = { "metrobrowser",
                          "-url",
                          utf8data.BeginReading() };
   nsresult rv = cmdLine->Init(ArrayLength(argv),
                               const_cast<char **>(argv), nullptr,
                               nsICommandLine::STATE_REMOTE_EXPLICIT);
   if (NS_FAILED(rv)) {
     NS_WARNING("cmdLine->Init failed.");
@@ -290,17 +326,17 @@ FrameworkView::PerformURILoadOrSearch(HS
     Log(L"Emptry string passed to PerformURILoadOrSearch");
     return;
   }
 
   // If we have a URI then devert to load the URI directly
   ComPtr<IUriRuntimeClass> uri;
   MetroUtils::CreateUri(aString.Get(), uri);
   if (uri) {
-    PerformURILoad(uri);
+    PerformURILoad(aString);
   } else {
     PerformSearch(aString);
   }
 }
 
 HRESULT
 FrameworkView::OnDataShareRequested(IDataTransferManager* aDTM,
                                     IDataRequestedEventArgs* aArg)
--- a/widget/windows/winrt/nsWinMetroUtils.cpp
+++ b/widget/windows/winrt/nsWinMetroUtils.cpp
@@ -405,16 +405,23 @@ nsWinMetroUtils::GetHandPreference(int32
     *aHandPreference = nsIWinMetroUtils::handPreferenceLeft;
   else
     *aHandPreference = nsIWinMetroUtils::handPreferenceRight;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsWinMetroUtils::GetActivationURI(nsAString &aActivationURI)
+{
+  MetroApp::GetView()->GetActivationURI(aActivationURI);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsWinMetroUtils::GetKeyboardVisible(bool *aImersive)
 {
   *aImersive = mozilla::widget::winrt::FrameworkView::IsKeyboardVisible();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWinMetroUtils::GetKeyboardX(uint32_t *aX)
@@ -440,17 +447,17 @@ nsWinMetroUtils::GetKeyboardWidth(uint32
 NS_IMETHODIMP
 nsWinMetroUtils::GetKeyboardHeight(uint32_t *aHeight)
 {
   *aHeight = (uint32_t)ceil(mozilla::widget::winrt::FrameworkView::KeyboardVisibleRect().Height);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWinMetroUtils::AddSettingsPanelEntry(const nsAString& aLabel, uint32_t *aId)
+nsWinMetroUtils::AddSettingsPanelEntry(const nsAString &aLabel, uint32_t *aId)
 {
   NS_ENSURE_ARG_POINTER(aId);
   if (!sSettingsArray)
     return NS_ERROR_UNEXPECTED;
 
   *aId = sSettingsArray->Length();
   sSettingsArray->AppendElement(nsString(aLabel));
   return NS_OK;