From 8c721c855ad9a24ce4141a6156cb8454f2f55387 Mon Sep 17 00:00:00 2001 From: dljames Date: Tue, 11 Jul 2023 17:15:20 +0000 Subject: [PATCH 1/5] Add ReadingList API proposal --- proposals/reading_list.md | 178 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 proposals/reading_list.md diff --git a/proposals/reading_list.md b/proposals/reading_list.md new file mode 100644 index 00000000..d942100a --- /dev/null +++ b/proposals/reading_list.md @@ -0,0 +1,178 @@ +# New API: browser.readingList() + +## Background + +Chromium has a reading list feature which allows users to store websites / media they would like to consume or keep reference to in the future. + +On Chromium this feature supports the following operations: +- Adding an entry to the ReadingList +- Remove an entry from the ReadingList +- Marking an entry as read / unread + +At present, extensions developers are unable to read from and modify the reading list feature in the browser. + +## Problem + +The reading list feature on Chromium does not have an existing API which allows extensions developers the ability to read from or modify this feature. Additionally, the UI allotted to extensions within the browser is much smaller compared to that of the reading list and similar features housed in the browsers side panel. + +## Solution + +Considering the above situation, we'd like to propose a new extension API, `browser.readingList`, which will allow developers to read from and modify the reading list in any supported browser. + +# API Proposal + +The `browser.readingList` will introduce a few new types and functions. Below is the schema in the IDL format: + +## Types +A ReadingListEntry is the extensions representation of a Reading List object. Where every URL stored in the Reading List must be unique. +```js + dictionary ReadingListEntry { + // The url of the entry. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + }; +``` + +A QueryInfo is the object used to query for ReadingListEntries in the Reading List. +```js +dictionary QueryInfo { + // The url to query for. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; +} +``` + +An UpdateEntryOptions is the object used to update a specific ReadingListEntry in the Reading List. A URL must be supplied. +```js +dictionary UpdateEntryOptions { + // The url that will be updated. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; +} +``` + +These callbacks are invoked when the appropriate action they are tied to are performed in the Reading List. +```js + callback AddEntryCallback = void (); + callback RemoveEntryCallback = void (); + callback UpdateEntryCallback = void(); + callback QueryCallback = void(ReadingListEntry[] entries); +``` + +## Functions +The initially supported functions of the API. + +### addEntry() +> Adds an entry to the reading list if it does not exist. +> +> | entry |: The entry to add to the reading list. +> +> | callback |: Invoked once the entry has been added. +```js +[supportsPromises] static void addEntry(ReadingListEntry entry, AddEntryCallback callback); +``` + +### removeEntry() +> Removes an entry from the reading list if it exists. +> +> | info |: The properties of the entry we would like to remove. +> +> | callback |: Invoked once the entry has been removed. + +```js +[supportsPromises] static void removeEntry(QueryInfo info, RemoveEntryCallback callback); +``` + +### query() + +> Retrieves all entries which match the QueryInfo properties. Properties which are not provided will not be matched. If no properties are provided, all entries are retrieved. +> +> | info |: The properties of the types of entries we are looking for. +> +> | callback |: Invoked once all entries matching the query are found. + +```js +[supportsPromises] static void query(QueryInfo info, QueryCallback callback); +``` + +### updateEntry() + +> Updates a reading list entries title and hasBeenRead status if it exists. +> +> | info |: The new properties of the entry we would like to update. +> +> | callback |: Invoked once the entry has been updated. + +```js +[supportsPromises] static void updateEntry(UpdateEntryOptions info, UpdateEntryCallback callback); + +``` + +### Additional Considerations + +#### Incognito mode + +The `browser.readingList` API can be available in incognito mode assuming the user explicitly allows the extension in incognito mode. + +### Full Schema + +```js +namespace readingList { + dictionary ReadingListEntry { + // The url of the entry. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + }; + +dictionary QueryInfo { + // The url to query for. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; +} + +dictionary UpdateEntryOptions { + // The url that will be updated. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; +} + + callback AddEntryCallback = void (); + callback RemoveEntryCallback = void (); + callback UpdateEntryCallback = void(); + callback QueryCallback = void(ReadingListEntry[] entries); + + interface Functions { + // Adds an entry to the reading list if it does not exist. + [supportsPromises] static void addEntry(ReadingListEntry entry, AddEntryCallback callback); + + // Removes an entry from the reading list if it exists. + [supportsPromises] static void removeEntry(QueryInfo info, RemoveEntryCallback callback); + + // Retrieves all entries which match the QueryInfo properties. + // Properties which are not provided will not be matched. + [supportsPromises] static void query(QueryInfo info, QueryCallback callback); + + // Updates a reading list entries title and hasBeenRead status if it exists. + [supportsPromises] static void updateEntry(UpdateEntryOptions info, UpdateEntryCallback callback); + }; +}; +``` + From ee5562d0a667e478ca204921ad56b1d0768ee3cf Mon Sep 17 00:00:00 2001 From: Darryl James <51972606+dlbjames@users.noreply.github.com> Date: Wed, 12 Jul 2023 10:16:34 -0700 Subject: [PATCH 2/5] Update URL parameter description in all dictionaries --- proposals/reading_list.md | 75 +++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/proposals/reading_list.md b/proposals/reading_list.md index d942100a..a3f9fb3a 100644 --- a/proposals/reading_list.md +++ b/proposals/reading_list.md @@ -26,37 +26,41 @@ The `browser.readingList` will introduce a few new types and functions. Below is ## Types A ReadingListEntry is the extensions representation of a Reading List object. Where every URL stored in the Reading List must be unique. ```js - dictionary ReadingListEntry { - // The url of the entry. + +dictionary ReadingListEntry { + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. DOMString url; // The title of the entry. DOMString title; // True if the entry has been read. boolean hasBeenRead; - }; +} ``` A QueryInfo is the object used to query for ReadingListEntries in the Reading List. ```js dictionary QueryInfo { - // The url to query for. - DOMString? url; - // The title to query for. - DOMString? title; - // The read status to query for. - boolean? hasBeenRead; + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; } ``` An UpdateEntryOptions is the object used to update a specific ReadingListEntry in the Reading List. A URL must be supplied. ```js dictionary UpdateEntryOptions { - // The url that will be updated. - DOMString url; - // The updated title. - DOMString? title; - // The updated read status. - boolean? hasBeenRead; + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; } ``` @@ -128,30 +132,33 @@ The `browser.readingList` API can be available in incognito mode assuming the us ```js namespace readingList { dictionary ReadingListEntry { - // The url of the entry. - DOMString url; - // The title of the entry. - DOMString title; - // True if the entry has been read. - boolean hasBeenRead; - }; + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + } dictionary QueryInfo { - // The url to query for. - DOMString? url; - // The title to query for. - DOMString? title; - // The read status to query for. - boolean? hasBeenRead; + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; } dictionary UpdateEntryOptions { - // The url that will be updated. - DOMString url; - // The updated title. - DOMString? title; - // The updated read status. - boolean? hasBeenRead; + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; } callback AddEntryCallback = void (); From 73b2e389e75d903b7e8e26f314fa39aedef10441 Mon Sep 17 00:00:00 2001 From: Darryl James <51972606+dlbjames@users.noreply.github.com> Date: Fri, 18 Aug 2023 15:09:09 -0700 Subject: [PATCH 3/5] Update reading_list.md Updates the schema to reflect the current state of implementation on the readingList api --- proposals/reading_list.md | 134 ++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 40 deletions(-) diff --git a/proposals/reading_list.md b/proposals/reading_list.md index a3f9fb3a..68b3c6fe 100644 --- a/proposals/reading_list.md +++ b/proposals/reading_list.md @@ -1,4 +1,5 @@ # New API: browser.readingList() +Contributors: dljames@chromium.org ## Background @@ -26,41 +27,56 @@ The `browser.readingList` will introduce a few new types and functions. Below is ## Types A ReadingListEntry is the extensions representation of a Reading List object. Where every URL stored in the Reading List must be unique. ```js + dictionary ReadingListEntry { + // The url of the entry. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + // The last update time of the entry. + // Recorded in microseconds since Jan 1st 1970. + double lastUpdateTime; + // The creation time of the entry. + // Recorded in microseconds since Jan 1st 1970. + double creationTime; + }; +``` -dictionary ReadingListEntry { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. +AddEntryOptions are the objects used to add entries into the Reading List. +```js +dictionary AddEntryOptions { + // The url of the entry. DOMString url; // The title of the entry. DOMString title; // True if the entry has been read. boolean hasBeenRead; -} +}; + ``` A QueryInfo is the object used to query for ReadingListEntries in the Reading List. ```js dictionary QueryInfo { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. - DOMString? url; - // The title to query for. - DOMString? title; - // The read status to query for. - boolean? hasBeenRead; + // The url to query for. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; } ``` An UpdateEntryOptions is the object used to update a specific ReadingListEntry in the Reading List. A URL must be supplied. ```js dictionary UpdateEntryOptions { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. - DOMString url; - // The updated title. - DOMString? title; - // The updated read status. - boolean? hasBeenRead; + // The url that will be updated. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; } ``` @@ -121,6 +137,32 @@ The initially supported functions of the API. ``` +## Events +The initially supported events this api will emit. + +### onEntryAdded() +> Triggered when a ReadingListEntry was added to the reading list. +> +> |entry|: The entry that was added. +```js +static void onEntryAdded(ReadingListEntry entry); +``` +### onEntryWillBeRemoved() +> Triggered when a ReadingListEntry is about to be removed from the +> reading list. +> +> |entry|: The entry that will be removed. +```js +static void onEntryWillBeRemoved(ReadingListEntry entry); +``` + +### onEntryUpdated() +> Triggered when a ReadingListEntry was updated in the reading list. +> +> |entry|: The entry that was updated. +```js +static void onEntryUpdated(ReadingListEntry entry); +``` ### Additional Considerations #### Incognito mode @@ -132,33 +174,30 @@ The `browser.readingList` API can be available in incognito mode assuming the us ```js namespace readingList { dictionary ReadingListEntry { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. - DOMString url; - // The title of the entry. - DOMString title; - // True if the entry has been read. - boolean hasBeenRead; - } + // The url of the entry. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + }; dictionary QueryInfo { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. - DOMString? url; - // The title to query for. - DOMString? title; - // The read status to query for. - boolean? hasBeenRead; + // The url to query for. + DOMString? url; + // The title to query for. + DOMString? title; + // The read status to query for. + boolean? hasBeenRead; } dictionary UpdateEntryOptions { - // The url of the entry. Must have a valid protocol (Ex: http, https) - // and hostname (Ex: www.google.com). Can contain query parameters. - DOMString url; - // The updated title. - DOMString? title; - // The updated read status. - boolean? hasBeenRead; + // The url that will be updated. + DOMString url; + // The updated title. + DOMString? title; + // The updated read status. + boolean? hasBeenRead; } callback AddEntryCallback = void (); @@ -180,6 +219,21 @@ dictionary UpdateEntryOptions { // Updates a reading list entries title and hasBeenRead status if it exists. [supportsPromises] static void updateEntry(UpdateEntryOptions info, UpdateEntryCallback callback); }; + + interface Events { + // Triggered when a ReadingListEntry was added to the reading list. + // |entry|: The entry that was added. + static void onEntryAdded(ReadingListEntry entry); + + // Triggered when a ReadingListEntry is about to be removed from the + // reading list. + // |entry|: The entry that will be removed. + static void onEntryWillBeRemoved(ReadingListEntry entry); + + // Triggered when a ReadingListEntry was updated in the reading list. + // |entry|: The entry that was updated. + static void onEntryUpdated(ReadingListEntry entry); + }; }; ``` From 50e0a08ae5a31facb977abc1f37c043255647907 Mon Sep 17 00:00:00 2001 From: Darryl James <51972606+dlbjames@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:04:38 -0700 Subject: [PATCH 4/5] Update reading_list.md Updated description for url properties with a brief description with what urls are allowed in the reading list. Changes OnEntryWillBeRemoved -> OnEntryRemoved --- proposals/reading_list.md | 77 +++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/proposals/reading_list.md b/proposals/reading_list.md index 68b3c6fe..25b5b4fe 100644 --- a/proposals/reading_list.md +++ b/proposals/reading_list.md @@ -28,7 +28,8 @@ The `browser.readingList` will introduce a few new types and functions. Below is A ReadingListEntry is the extensions representation of a Reading List object. Where every URL stored in the Reading List must be unique. ```js dictionary ReadingListEntry { - // The url of the entry. + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString url; // The title of the entry. DOMString title; @@ -46,7 +47,8 @@ A ReadingListEntry is the extensions representation of a Reading List object. Wh AddEntryOptions are the objects used to add entries into the Reading List. ```js dictionary AddEntryOptions { - // The url of the entry. + // The url of the entry to add. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString url; // The title of the entry. DOMString title; @@ -59,7 +61,8 @@ dictionary AddEntryOptions { A QueryInfo is the object used to query for ReadingListEntries in the Reading List. ```js dictionary QueryInfo { - // The url to query for. + // The url of the entry to query for. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString? url; // The title to query for. DOMString? title; @@ -71,7 +74,8 @@ dictionary QueryInfo { An UpdateEntryOptions is the object used to update a specific ReadingListEntry in the Reading List. A URL must be supplied. ```js dictionary UpdateEntryOptions { - // The url that will be updated. + // The url of then entry that will be updated. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString url; // The updated title. DOMString? title; @@ -147,13 +151,13 @@ The initially supported events this api will emit. ```js static void onEntryAdded(ReadingListEntry entry); ``` -### onEntryWillBeRemoved() -> Triggered when a ReadingListEntry is about to be removed from the +### onEntryRemoved() +> Triggered when a ReadingListEntry is removed from the > reading list. > -> |entry|: The entry that will be removed. +> |entry|: The entry that was removed. ```js -static void onEntryWillBeRemoved(ReadingListEntry entry); +static void onEntryRemoved(ReadingListEntry entry); ``` ### onEntryUpdated() @@ -174,7 +178,24 @@ The `browser.readingList` API can be available in incognito mode assuming the us ```js namespace readingList { dictionary ReadingListEntry { - // The url of the entry. + // The url of the entry. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. + DOMString url; + // The title of the entry. + DOMString title; + // True if the entry has been read. + boolean hasBeenRead; + // The last update time of the entry. + // Recorded in milliseconds since Jan 1st 1970. + double lastUpdateTime; + // The creation time of the entry. + // Recorded in milliseconds since Jan 1st 1970. + double creationTime; + }; + + dictionary AddEntryOptions { + // The url of the entry to add. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString url; // The title of the entry. DOMString title; @@ -183,57 +204,59 @@ namespace readingList { }; dictionary QueryInfo { - // The url to query for. + // The url of the entry to query for. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.example.com). Can contain query parameters. DOMString? url; // The title to query for. DOMString? title; // The read status to query for. boolean? hasBeenRead; -} +}; dictionary UpdateEntryOptions { - // The url that will be updated. + // The url of the entry to be updated. Must have a valid protocol (Ex: http, https) + // and hostname (Ex: www.google.com). Can contain query parameters. DOMString url; // The updated title. DOMString? title; // The updated read status. boolean? hasBeenRead; -} +}; callback AddEntryCallback = void (); callback RemoveEntryCallback = void (); - callback UpdateEntryCallback = void(); + callback UpdateEntryCallback = void(); callback QueryCallback = void(ReadingListEntry[] entries); - interface Functions { + interface Functions { // Adds an entry to the reading list if it does not exist. [supportsPromises] static void addEntry(ReadingListEntry entry, AddEntryCallback callback); - + // Removes an entry from the reading list if it exists. [supportsPromises] static void removeEntry(QueryInfo info, RemoveEntryCallback callback); - // Retrieves all entries which match the QueryInfo properties. - // Properties which are not provided will not be matched. + // Retrieves all entries which match the QueryInfo properties. Properties which are not provided will not be matched. [supportsPromises] static void query(QueryInfo info, QueryCallback callback); // Updates a reading list entries title and hasBeenRead status if it exists. [supportsPromises] static void updateEntry(UpdateEntryOptions info, UpdateEntryCallback callback); }; - interface Events { - // Triggered when a ReadingListEntry was added to the reading list. + interface Events { + // Triggered when a ReadingListEntry is added to the reading list. // |entry|: The entry that was added. - static void onEntryAdded(ReadingListEntry entry); - - // Triggered when a ReadingListEntry is about to be removed from the - // reading list. - // |entry|: The entry that will be removed. - static void onEntryWillBeRemoved(ReadingListEntry entry); + [supportsPromises] static void onEntryAdded(ReadingListEntry entry); + + // Triggered when a ReadingListEntry is removed from the reading list. + // |entry|: The entry that was removed. + [supportsPromises] static void onEntryRemoved(ReadingListEntry entry); // Triggered when a ReadingListEntry was updated in the reading list. // |entry|: The entry that was updated. - static void onEntryUpdated(ReadingListEntry entry); + [supportsPromises] static void onEntryUpdated(ReadingListEntry entry); }; }; + + ``` From 865afe7fd2f88e73c75b4ad2418ce30d55eaf244 Mon Sep 17 00:00:00 2001 From: Darryl James <51972606+dlbjames@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:16:12 -0700 Subject: [PATCH 5/5] Remove supportsPromises from the events --- proposals/reading_list.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/reading_list.md b/proposals/reading_list.md index 25b5b4fe..009dab73 100644 --- a/proposals/reading_list.md +++ b/proposals/reading_list.md @@ -245,15 +245,15 @@ dictionary UpdateEntryOptions { interface Events { // Triggered when a ReadingListEntry is added to the reading list. // |entry|: The entry that was added. - [supportsPromises] static void onEntryAdded(ReadingListEntry entry); + static void onEntryAdded(ReadingListEntry entry); // Triggered when a ReadingListEntry is removed from the reading list. // |entry|: The entry that was removed. - [supportsPromises] static void onEntryRemoved(ReadingListEntry entry); + static void onEntryRemoved(ReadingListEntry entry); // Triggered when a ReadingListEntry was updated in the reading list. // |entry|: The entry that was updated. - [supportsPromises] static void onEntryUpdated(ReadingListEntry entry); + static void onEntryUpdated(ReadingListEntry entry); }; };