Commit 2a1d9fff authored by Tanya Gupta's avatar Tanya Gupta Committed by Commit Bot

[SendTabToSelf] Added logic to display an infobar for the feature.

This CL is one of many to come. It covers:
* Creation of the infobar from the SendTabToSelfInfoBarController
* Plumbed the call to create the infobar to the native code.
* Open the link when user taps on the link

In follow-up CLs, the following will be done:
* Instantiate the InfobarController in the ChromeActivity
* Listen for Model changes in the Controller


Bug: 949233,963193
Change-Id: I5df1359debb5f0f35c32c2df3b691bf9129cdeb8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1604406Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarMikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarsebsg <sebsg@chromium.org>
Reviewed-by: default avatarJeffrey Cohen <jeffreycohen@chromium.org>
Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Commit-Queue: Tanya Gupta <tgupta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660854}
parent 0652ee0d
...@@ -1347,6 +1347,7 @@ chrome_java_sources = [ ...@@ -1347,6 +1347,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java",
"java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java",
"java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java",
"java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java",
"java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java",
"java/src/org/chromium/chrome/browser/services/AccountsChangedReceiver.java", "java/src/org/chromium/chrome/browser/services/AccountsChangedReceiver.java",
"java/src/org/chromium/chrome/browser/services/AndroidEduAndChildAccountHelper.java", "java/src/org/chromium/chrome/browser/services/AndroidEduAndChildAccountHelper.java",
......
...@@ -48,7 +48,9 @@ public class SendTabToSelfAndroidBridge { ...@@ -48,7 +48,9 @@ public class SendTabToSelfAndroidBridge {
allGuids.add(newGuid); allGuids.add(newGuid);
} }
/** Deletes all SendTabToSelf entries. This is called when the user disables sync. */ /**
* Deletes all SendTabToSelf entries. This is called when the user disables sync.
*/
public static void deleteAllEntries(Profile profile) { public static void deleteAllEntries(Profile profile) {
// TODO(https://crbug.com/942549): Add this assertion back in once the code to load is in // TODO(https://crbug.com/942549): Add this assertion back in once the code to load is in
// place. assert mIsNativeSendTabToSelfModelLoaded; // place. assert mIsNativeSendTabToSelfModelLoaded;
...@@ -117,6 +119,16 @@ public class SendTabToSelfAndroidBridge { ...@@ -117,6 +119,16 @@ public class SendTabToSelfAndroidBridge {
return SendTabToSelfAndroidBridgeJni.get().isFeatureAvailable(webContents); return SendTabToSelfAndroidBridgeJni.get().isFeatureAvailable(webContents);
} }
/**
* Shows an infobar for the webcontents passed in.
* @param entry Contains the URL to open when the user taps on the infobar.
* @param webContents Where to create the infobar.
*/
public static void showInfoBar(SendTabToSelfEntry entry, WebContents webContents) {
SendTabToSelfAndroidBridgeJni.get().showInfoBar(
webContents, entry.guid, entry.url, entry.targetDeviceSyncCacheGuid);
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
SendTabToSelfEntry addEntry(Profile profile, String url, String title, long navigationTime, SendTabToSelfEntry addEntry(Profile profile, String url, String title, long navigationTime,
...@@ -133,5 +145,8 @@ public class SendTabToSelfAndroidBridge { ...@@ -133,5 +145,8 @@ public class SendTabToSelfAndroidBridge {
SendTabToSelfEntry getEntryByGUID(Profile profile, String guid); SendTabToSelfEntry getEntryByGUID(Profile profile, String guid);
boolean isFeatureAvailable(WebContents webContents); boolean isFeatureAvailable(WebContents webContents);
void showInfoBar(
WebContents webContents, String guid, String url, String targetDeviceSyncCacheGuid);
} }
} }
...@@ -27,9 +27,8 @@ public class SendTabToSelfInfoBar extends InfoBar { ...@@ -27,9 +27,8 @@ public class SendTabToSelfInfoBar extends InfoBar {
@Override @Override
protected void createCompactLayoutContent(InfoBarCompactLayout layout) { protected void createCompactLayoutContent(InfoBarCompactLayout layout) {
new InfoBarCompactLayout.MessageBuilder(layout) new InfoBarCompactLayout.MessageBuilder(layout)
.withText("Tab shared") .withText(R.string.send_tab_to_self_infobar_message)
// TODO(crbug.com/949233): Add the link in .withLink(R.string.send_tab_to_self_infobar_message_url, view -> onLinkClicked())
// .withLink(textResId, onTapCallback)
.buildAndInsert(); .buildAndInsert();
} }
...@@ -37,4 +36,10 @@ public class SendTabToSelfInfoBar extends InfoBar { ...@@ -37,4 +36,10 @@ public class SendTabToSelfInfoBar extends InfoBar {
private static SendTabToSelfInfoBar create() { private static SendTabToSelfInfoBar create() {
return new SendTabToSelfInfoBar(); return new SendTabToSelfInfoBar();
} }
@Override
public void onLinkClicked() {
// TODO(crbug.com/944602): Add support for opening the link. Figure out
// whether the logic should live here or in the delegate.
}
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.send_tab_to_self;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.tab.Tab;
/**
* This class is responsible for listening for new SendTabToSelfEntries and showing an infobar
* to the user if the user does not have notifications enabled.
*/
public class SendTabToSelfInfoBarController implements Destroyable {
private ChromeActivity mActivity;
/**
* Creates a SendTabToSelfInfoBarController for the activity passed in.
*
* TODO(crbug.com/949233):
* - Add observers to listen for SendTabToSelfModel changes. When a new entry is observed,
* check to see if notifications are enabled. If not, display an infobar.
* - If a new entry comes in and the user is not on a tab, listen for a new tab and show
* an infobar then.
* - If an infobar is already being displayed and the user pushes another tab, replace
* the existing infobar with a new one.
*
* @param activity A {@link ChromeActivity} instance the infobars will be
* shown in.
* @return A new instance of {@link SendTabToSelfInfoBarController}.
*/
public SendTabToSelfInfoBarController(ChromeActivity activity) {
mActivity = activity;
mActivity.getLifecycleDispatcher().register(this);
}
// Destroyable implementation.
@Override
public void destroy() {
mActivity.getLifecycleDispatcher().unregister(this);
mActivity = null;
}
/**
* Shows an infobar corresponding to the entry passed in if the user is on a tab.
* @param entry The entry to display the infobar for.
*/
public void showInfobarForEntry(SendTabToSelfEntry entry) {
if (mActivity == null) {
return;
}
Tab tab = mActivity.getActivityTabProvider().get();
// TODO(crbug.com/949233): Listen for when the user opens a tab next and show
// an infobar then.
if (tab == null) {
return;
}
SendTabToSelfAndroidBridge.showInfoBar(entry, tab.getWebContents());
}
}
...@@ -3940,6 +3940,12 @@ The site does NOT gain access to the camera. The camera images are only visible ...@@ -3940,6 +3940,12 @@ The site does NOT gain access to the camera. The camera images are only visible
<message name="IDS_SEND_TAB_TO_SELF_NOTIFICATION_CONTEXT_TEXT" desc="Text displayed as the second line of a notification indicating the domain and the device the tab is shared from."> <message name="IDS_SEND_TAB_TO_SELF_NOTIFICATION_CONTEXT_TEXT" desc="Text displayed as the second line of a notification indicating the domain and the device the tab is shared from.">
<ph name="DOMAIN">%1$s<ex>www.google.com</ex></ph> - Sent from <ph name="DEVICE_NAME">%2$s<ex>Tanya's Pixel 2XL</ex></ph> <ph name="DOMAIN">%1$s<ex>www.google.com</ex></ph> - Sent from <ph name="DEVICE_NAME">%2$s<ex>Tanya's Pixel 2XL</ex></ph>
</message> </message>
<message name="IDS_SEND_TAB_TO_SELF_INFOBAR_MESSAGE" desc="The message text for the infobar when a user receives a shared tab from another device.">
Tab received
</message>
<message name="IDS_SEND_TAB_TO_SELF_INFOBAR_MESSAGE_URL" desc="Clickable text displayed as part of a URL in the inforbar displayed when a user receives a shared tab from another device.">
Open
</message>
<!-- Chrome Duet --> <!-- Chrome Duet -->
<message name="IDS_IPH_DUET_TITLE" desc="This string appears in an overlay that explains a new UI to users. 'Search' refers to searching the web, and 'explore' refers to Chrome's suggested content."> <message name="IDS_IPH_DUET_TITLE" desc="This string appears in an overlay that explains a new UI to users. 'Search' refers to searching the web, and 'explore' refers to Chrome's suggested content.">
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/profiles/profile_android.h"
#include "chrome/browser/send_tab_to_self/send_tab_to_self_client_service.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_client_service.h"
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
#include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h"
#include "components/send_tab_to_self/send_tab_to_self_entry.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h"
#include "components/send_tab_to_self/send_tab_to_self_infobar_delegate.h"
#include "components/send_tab_to_self/send_tab_to_self_model.h" #include "components/send_tab_to_self/send_tab_to_self_model.h"
#include "components/send_tab_to_self/send_tab_to_self_sync_service.h" #include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
...@@ -178,4 +180,32 @@ static jboolean JNI_SendTabToSelfAndroidBridge_IsFeatureAvailable( ...@@ -178,4 +180,32 @@ static jboolean JNI_SendTabToSelfAndroidBridge_IsFeatureAvailable(
return ShouldOfferFeature(web_contents); return ShouldOfferFeature(web_contents);
} }
static void JNI_SendTabToSelfAndroidBridge_ShowInfoBar(
JNIEnv* env,
const JavaParamRef<jobject>& j_web_contents,
const JavaParamRef<jstring>& j_guid,
const JavaParamRef<jstring>& j_url,
const JavaParamRef<jstring>& j_target_device_sync_cache_guid) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(j_web_contents);
const std::string guid = ConvertJavaStringToUTF8(env, j_guid);
const std::string url = ConvertJavaStringToUTF8(env, j_url);
const std::string target_device_sync_cache_guid =
ConvertJavaStringToUTF8(env, j_target_device_sync_cache_guid);
std::unique_ptr<SendTabToSelfEntry> entry =
SendTabToSelfEntry::FromRequiredFields(guid, GURL(url),
target_device_sync_cache_guid);
// The entry fields were malformed so don't show an infobar. Theoretically,
// this should never happen because a malformed entry can not be synced
// to the server but it doesn't hurt to check.
if (!entry) {
return;
}
std::unique_ptr<SendTabToSelfInfoBarDelegate> delegate =
SendTabToSelfInfoBarDelegate::Create(web_contents, entry.release());
SendTabToSelfInfoBar::ShowInfoBar(web_contents, std::move(delegate));
}
} // namespace send_tab_to_self } // namespace send_tab_to_self
...@@ -43,9 +43,12 @@ void SendTabToSelfInfoBar::OnLinkClicked( ...@@ -43,9 +43,12 @@ void SendTabToSelfInfoBar::OnLinkClicked(
} }
// static // static
void SendTabToSelfInfoBar::ShowInfoBar(content::WebContents* web_contents, void SendTabToSelfInfoBar::ShowInfoBar(
SendTabToSelfInfoBarDelegate* delegate) { content::WebContents* web_contents,
NOTIMPLEMENTED(); std::unique_ptr<SendTabToSelfInfoBarDelegate> delegate) {
InfoBarService* service = InfoBarService::FromWebContents(web_contents);
service->AddInfoBar(
base::WrapUnique(new SendTabToSelfInfoBar(std::move(delegate))));
} }
} // namespace send_tab_to_self } // namespace send_tab_to_self
...@@ -23,8 +23,9 @@ class SendTabToSelfInfoBar : public InfoBarAndroid { ...@@ -23,8 +23,9 @@ class SendTabToSelfInfoBar : public InfoBarAndroid {
public: public:
~SendTabToSelfInfoBar() override; ~SendTabToSelfInfoBar() override;
// |delegate| must remain alive while showing this info bar. // |delegate| must remain alive while showing this info bar.
static void ShowInfoBar(content::WebContents* web_contents, static void ShowInfoBar(
SendTabToSelfInfoBarDelegate* delegate); content::WebContents* web_contents,
std::unique_ptr<SendTabToSelfInfoBarDelegate> delegate);
private: private:
explicit SendTabToSelfInfoBar( explicit SendTabToSelfInfoBar(
......
...@@ -36,12 +36,15 @@ static_library("send_tab_to_self") { ...@@ -36,12 +36,15 @@ static_library("send_tab_to_self") {
public_deps = [ public_deps = [
"//components/send_tab_to_self/proto:send_tab_to_self_proto", "//components/send_tab_to_self/proto:send_tab_to_self_proto",
] ]
if (is_ios || is_android) { if (is_android) {
sources += [ sources += [
"send_tab_to_self_infobar_delegate.cc", "send_tab_to_self_infobar_delegate.cc",
"send_tab_to_self_infobar_delegate.h", "send_tab_to_self_infobar_delegate.h",
] ]
deps += [ "//components/infobars/core" ] deps += [
"//components/infobars/core",
"//content/public/browser",
]
} }
} }
......
...@@ -5,5 +5,6 @@ include_rules = [ ...@@ -5,5 +5,6 @@ include_rules = [
"+components/sync_device_info", "+components/sync_device_info",
"+components/version_info", "+components/version_info",
"+components/history", "+components/history",
"+content/public/browser",
"+google_apis", "+google_apis",
] ]
...@@ -156,4 +156,16 @@ bool SendTabToSelfEntry::IsExpired(base::Time current_time) const { ...@@ -156,4 +156,16 @@ bool SendTabToSelfEntry::IsExpired(base::Time current_time) const {
kExpiryTime); kExpiryTime);
} }
std::unique_ptr<SendTabToSelfEntry> SendTabToSelfEntry::FromRequiredFields(
const std::string& guid,
const GURL& url,
const std::string& target_device_sync_cache_guid) {
if (guid.empty() || !url.is_valid()) {
return nullptr;
}
return std::make_unique<SendTabToSelfEntry>(guid, url, "", base::Time(),
base::Time(), "",
target_device_sync_cache_guid);
}
} // namespace send_tab_to_self } // namespace send_tab_to_self
...@@ -78,6 +78,12 @@ class SendTabToSelfEntry { ...@@ -78,6 +78,12 @@ class SendTabToSelfEntry {
// Returns if the Entry has expired based on the |current_time|. // Returns if the Entry has expired based on the |current_time|.
bool IsExpired(base::Time current_time) const; bool IsExpired(base::Time current_time) const;
// Creates a SendTabToSelfEntry consisting of only the required fields.
static std::unique_ptr<SendTabToSelfEntry> FromRequiredFields(
const std::string& guid,
const GURL& url,
const std::string& target_device_sync_cache_guid);
private: private:
std::string guid_; std::string guid_;
GURL url_; GURL url_;
......
...@@ -78,6 +78,17 @@ TEST(SendTabToSelfEntry, AsProto) { ...@@ -78,6 +78,17 @@ TEST(SendTabToSelfEntry, AsProto) {
EXPECT_TRUE(IsEqualForTesting(entry, pb_entry.specifics())); EXPECT_TRUE(IsEqualForTesting(entry, pb_entry.specifics()));
} }
// Tests that the send tab to self entry is correctly created from the required
// fields
TEST(SendTabToSelfEntry, FromRequiredFields) {
SendTabToSelfEntry expected("1", GURL("http://example.com"), "", base::Time(),
base::Time(), "", "target_device");
std::unique_ptr<SendTabToSelfEntry> actual =
SendTabToSelfEntry::FromRequiredFields("1", GURL("http://example.com"),
"target_device");
EXPECT_TRUE(IsEqualForTesting(expected, *actual));
}
// Tests that the send tab to self entry is correctly parsed from // Tests that the send tab to self entry is correctly parsed from
// sync_pb::SendTabToSelfSpecifics. // sync_pb::SendTabToSelfSpecifics.
TEST(SendTabToSelfEntry, FromProto) { TEST(SendTabToSelfEntry, FromProto) {
......
...@@ -7,14 +7,17 @@ ...@@ -7,14 +7,17 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/send_tab_to_self/send_tab_to_self_entry.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace send_tab_to_self { namespace send_tab_to_self {
// static // static
std::unique_ptr<SendTabToSelfInfoBarDelegate> std::unique_ptr<SendTabToSelfInfoBarDelegate>
SendTabToSelfInfoBarDelegate::Create(const SendTabToSelfEntry* entry) { SendTabToSelfInfoBarDelegate::Create(content::WebContents* web_contents,
return base::WrapUnique(new SendTabToSelfInfoBarDelegate(entry)); const SendTabToSelfEntry* entry) {
return base::WrapUnique(
new SendTabToSelfInfoBarDelegate(web_contents, entry));
} }
SendTabToSelfInfoBarDelegate::~SendTabToSelfInfoBarDelegate() {} SendTabToSelfInfoBarDelegate::~SendTabToSelfInfoBarDelegate() {}
...@@ -26,7 +29,15 @@ base::string16 SendTabToSelfInfoBarDelegate::GetInfobarMessage() const { ...@@ -26,7 +29,15 @@ base::string16 SendTabToSelfInfoBarDelegate::GetInfobarMessage() const {
} }
void SendTabToSelfInfoBarDelegate::OpenTab() { void SendTabToSelfInfoBarDelegate::OpenTab() {
NOTIMPLEMENTED(); content::OpenURLParams open_url_params(
entry_->GetURL(), content::Referrer(),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PageTransition::PAGE_TRANSITION_LINK,
false /* is_renderer_initiated */);
web_contents_->OpenURL(open_url_params);
// TODO(crbug.com/944602): Update the model to reflect that an infobar is
// shown.
} }
void SendTabToSelfInfoBarDelegate::InfoBarDismissed() { void SendTabToSelfInfoBarDelegate::InfoBarDismissed() {
...@@ -39,7 +50,9 @@ SendTabToSelfInfoBarDelegate::GetIdentifier() const { ...@@ -39,7 +50,9 @@ SendTabToSelfInfoBarDelegate::GetIdentifier() const {
} }
SendTabToSelfInfoBarDelegate::SendTabToSelfInfoBarDelegate( SendTabToSelfInfoBarDelegate::SendTabToSelfInfoBarDelegate(
content::WebContents* web_contents,
const SendTabToSelfEntry* entry) { const SendTabToSelfEntry* entry) {
web_contents_ = web_contents;
entry_ = entry; entry_ = entry;
} }
......
...@@ -11,15 +11,21 @@ ...@@ -11,15 +11,21 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "components/infobars/core/infobar_delegate.h" #include "components/infobars/core/infobar_delegate.h"
namespace content {
class WebContents;
}
namespace send_tab_to_self { namespace send_tab_to_self {
class SendTabToSelfEntry; class SendTabToSelfEntry;
// Delegate containing logic about what to display and how to behave // Delegate containing logic about what to display and how to behave
// in the SendTabToSelf infobar. Used across Android and iOS. // in the SendTabToSelf infobar. Used on Android.
// TODO(crbug.com/964112): Rename this class to be Android specific.
class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate { class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate {
public: public:
static std::unique_ptr<SendTabToSelfInfoBarDelegate> Create( static std::unique_ptr<SendTabToSelfInfoBarDelegate> Create(
content::WebContents* web_contents,
const SendTabToSelfEntry* entry); const SendTabToSelfEntry* entry);
~SendTabToSelfInfoBarDelegate() override; ~SendTabToSelfInfoBarDelegate() override;
...@@ -34,8 +40,11 @@ class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate { ...@@ -34,8 +40,11 @@ class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate {
infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
private: private:
explicit SendTabToSelfInfoBarDelegate(const SendTabToSelfEntry* entry); explicit SendTabToSelfInfoBarDelegate(content::WebContents* web_contents,
const SendTabToSelfEntry* entry);
// The web_content the infobar is attached to. Must outlive this class.
content::WebContents* web_contents_ = nullptr;
// The entry that was share to this device. Must outlive this instance. // The entry that was share to this device. Must outlive this instance.
const SendTabToSelfEntry* entry_ = nullptr; const SendTabToSelfEntry* entry_ = nullptr;
...@@ -44,4 +53,4 @@ class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate { ...@@ -44,4 +53,4 @@ class SendTabToSelfInfoBarDelegate : public infobars::InfoBarDelegate {
} // namespace send_tab_to_self } // namespace send_tab_to_self
#endif // COMPONENTS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_INFOBAR_DELEGATE_H_ #endif // COMPONENTS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_INFOBAR_DELEGATE_H_
\ No newline at end of file
...@@ -17,23 +17,22 @@ package sync_pb; ...@@ -17,23 +17,22 @@ package sync_pb;
// a url across devices. // a url across devices.
message SendTabToSelfSpecifics { message SendTabToSelfSpecifics {
// A random unique identifier for each shared tab. // A random unique identifier for each shared tab.
// Required // Required.
optional string guid = 5; optional string guid = 5;
// The name of the tab being shared. // The name of the tab being shared.
optional string title = 1; optional string title = 1;
// The URL of the tab being shared. // The URL of the tab being shared.
// Required // Required.
optional string url = 2; optional string url = 2;
// The time the tab was shared as measured by the client in microseconds since // The time the tab was shared as measured by the client in microseconds since
// the windows epoch. // the windows epoch.
// Required
optional int64 shared_time_usec = 3; optional int64 shared_time_usec = 3;
// The time the tab was navigated to as measured by the client in microseconds // The time the tab was navigated to as measured by the client in microseconds
// since the windows epoch. // since the windows epoch.
// Required
optional int64 navigation_time_usec = 6; optional int64 navigation_time_usec = 6;
// A non-unique but human readable name to describe this client, used in UI. // A non-unique but human readable name to describe this client, used in UI.
optional string device_name = 4; optional string device_name = 4;
// The stable Device_id of the device that this tab was shared with. // The stable Device_id of the device that this tab was shared with.
// Required.
optional string target_device_sync_cache_guid = 7; optional string target_device_sync_cache_guid = 7;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment