diff --git a/addons/board/static/tests/board_test.js b/addons/board/static/tests/board_test.js index 68e5082ee0e..06f5859de60 100644 --- a/addons/board/static/tests/board_test.js +++ b/addons/board/static/tests/board_test.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { BoardAction } from "@board/board_action"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; import { click, dragAndDrop, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { registry } from "@web/core/registry"; @@ -726,8 +725,6 @@ QUnit.module("Board", (hooks) => { }); QUnit.test("graphs in dashboard aren't squashed", async function (assert) { - registry.category("services").add("cookie", fakeCookieService); - serverData.views["partner,4,graph"] = ''; diff --git a/addons/crm/static/tests/forecast_view_tests.js b/addons/crm/static/tests/forecast_view_tests.js index 8250974ac3d..8593ca52092 100644 --- a/addons/crm/static/tests/forecast_view_tests.js +++ b/addons/crm/static/tests/forecast_view_tests.js @@ -11,7 +11,6 @@ import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { registry } from "@web/core/registry"; import { mock } from "@web/../tests/legacy/helpers/test_utils"; import { browser } from "@web/core/browser/browser"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; const patchDate = mock.patchDate; @@ -73,7 +72,6 @@ QUnit.module("Views", (hooks) => { }; setupViewRegistries(); serviceRegistry.add("menu", menuService); - serviceRegistry.add("cookie", fakeCookieService); target = getFixture(); }); diff --git a/addons/im_livechat/static/src/embed/core/autopopup_service.js b/addons/im_livechat/static/src/embed/core/autopopup_service.js index 29bd5f89d51..fba82368cd8 100644 --- a/addons/im_livechat/static/src/embed/core/autopopup_service.js +++ b/addons/im_livechat/static/src/embed/core/autopopup_service.js @@ -1,6 +1,7 @@ /* @odoo-module */ import { browser } from "@web/core/browser/browser"; +import { cookie } from "@web/core/browser/cookie"; import { registry } from "@web/core/registry"; export class AutopopupService { @@ -13,7 +14,6 @@ export class AutopopupService { * "im_livechat.livechat": import("@im_livechat/embed/core/livechat_service").LivechatService, * "mail.thread": import("@mail/core/common/thread_service").ThreadService, * "mail.store": import("@mail/core/common/store_service").Store, - * cookie: typeof import("@web/core/browser/cookie_service").cookieService.start, * ui: typeof import("@web/core/ui/ui_service").uiService.start, * }} services */ @@ -25,14 +25,12 @@ export class AutopopupService { "mail.thread": threadService, "mail.store": storeService, ui, - cookie, } ) { this.threadService = threadService; this.storeService = storeService; this.livechatService = livechatService; this.chatbotService = chatbotService; - this.cookie = cookie; this.ui = ui; livechatService.initializedDeferred.then(() => { @@ -41,7 +39,7 @@ export class AutopopupService { } else if (this.allowAutoPopup) { browser.setTimeout(async () => { if (await this.shouldOpenChatWindow()) { - this.cookie.setCookie(AutopopupService.COOKIE, JSON.stringify(false)); + cookie.set(AutopopupService.COOKIE, JSON.stringify(false)); threadService.openChat(); } }, livechatService.rule.auto_popup_timer * 1000); @@ -63,7 +61,7 @@ export class AutopopupService { get allowAutoPopup() { return Boolean( - JSON.parse(this.cookie.current[AutopopupService.COOKIE] ?? "true") !== false && + JSON.parse(cookie.get(AutopopupService.COOKIE) ?? "true") !== false && !this.ui.isSmall && this.livechatService.rule?.action === "auto_popup" && (this.livechatService.available || this.chatbotService.available) @@ -77,7 +75,6 @@ export const autoPopupService = { "im_livechat.chatbot", "mail.thread", "mail.store", - "cookie", "ui", ], diff --git a/addons/im_livechat/static/src/embed/core/history_service.js b/addons/im_livechat/static/src/embed/core/history_service.js index 88d9299474e..d80eaf18e37 100644 --- a/addons/im_livechat/static/src/embed/core/history_service.js +++ b/addons/im_livechat/static/src/embed/core/history_service.js @@ -1,6 +1,7 @@ /* @odoo-module */ import { browser } from "@web/core/browser/browser"; +import { cookie as cookieManager } from "@web/core/browser/cookie"; import { registry } from "@web/core/registry"; export class HistoryService { @@ -14,50 +15,45 @@ export class HistoryService { this.busService = services.bus_service; /** @type {import("@im_livechat/embed/core/livechat_service").LivechatService} */ this.livechatService = services["im_livechat.livechat"]; - /** @type {ReturnType} */ - this.cookieService = services.cookie; } setup() { this.updateHistory(); - this.busService.subscribe( - "im_livechat.history_command", - (payload) => { - if (payload.id !== this.livechatService.thread?.id) { - return; - } - const cookie = this.cookieService.current[HistoryService.HISTORY_COOKIE]; - const history = cookie ? JSON.parse(cookie) : []; - this.rpc('/im_livechat/history', { - pid: this.livechatService.thread.operator.id, - channel_uuid: this.livechatService.thread.uuid, - page_history: history, - }); + this.busService.subscribe("im_livechat.history_command", (payload) => { + if (payload.id !== this.livechatService.thread?.id) { + return; } - ); + const cookie = cookieManager.get(HistoryService.HISTORY_COOKIE); + const history = cookie ? JSON.parse(cookie) : []; + this.rpc("/im_livechat/history", { + pid: this.livechatService.thread.operator.id, + channel_uuid: this.livechatService.thread.uuid, + page_history: history, + }); + }); } updateHistory() { - const page = browser.location.href.replace(/^.*\/\/[^/]+/, ''); - const pageHistory = this.cookieService.current[HistoryService.HISTORY_COOKIE]; + const page = browser.location.href.replace(/^.*\/\/[^/]+/, ""); + const pageHistory = cookieManager.get(HistoryService.HISTORY_COOKIE); const urlHistory = pageHistory ? JSON.parse(pageHistory) : []; if (!urlHistory.includes(page)) { urlHistory.push(page); if (urlHistory.length > HistoryService.HISTORY_LIMIT) { urlHistory.shift(); } - this.cookieService.setCookie(HistoryService.HISTORY_COOKIE, JSON.stringify(urlHistory), 60 * 60 * 24, 'optional'); // 1 day cookie + cookieManager.set( + HistoryService.HISTORY_COOKIE, + JSON.stringify(urlHistory), + 60 * 60 * 24, + "optional" + ); // 1 day cookie } } } export const historyService = { - dependencies: [ - "im_livechat.livechat", - "bus_service", - "rpc", - "cookie", - ], + dependencies: ["im_livechat.livechat", "bus_service", "rpc"], start(env, services) { const history = new HistoryService(env, services); history.setup(); diff --git a/addons/im_livechat/static/src/embed/core/livechat_service.js b/addons/im_livechat/static/src/embed/core/livechat_service.js index 0742f8af975..5103e42354a 100644 --- a/addons/im_livechat/static/src/embed/core/livechat_service.js +++ b/addons/im_livechat/static/src/embed/core/livechat_service.js @@ -3,6 +3,7 @@ import { reactive } from "@odoo/owl"; import { browser } from "@web/core/browser/browser"; +import { cookie } from "@web/core/browser/cookie"; import { _t } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; import { Deferred } from "@web/core/utils/concurrency"; @@ -55,7 +56,6 @@ export class LivechatService { /** * @param {import("@web/env").OdooEnv} env * @param {{ - * cookie: ReturnType, * bus_service: ReturnType, * rpc: ReturnType, * "mail.chat_window": import("@mail/core/common/chat_window_service").ChatWindowService>, @@ -64,7 +64,6 @@ export class LivechatService { */ setup(env, services) { this.env = env; - this.cookie = services.cookie; this.busService = services.bus_service; this.chatWindowService = services["mail.chat_window"]; this.rpc = services.rpc; @@ -106,16 +105,16 @@ export class LivechatService { * @param {Object} values */ updateSession(values) { - const session = JSON.parse(this.cookie.current[this.SESSION_COOKIE] ?? "{}"); + const session = JSON.parse(cookie.get(this.SESSION_COOKIE) ?? "{}"); Object.assign(session, { visitor_uid: this.visitorUid, ...values, }); - this.cookie.deleteCookie(this.SESSION_COOKIE); - this.cookie.deleteCookie(this.OPERATOR_COOKIE); - this.cookie.setCookie(this.SESSION_COOKIE, JSON.stringify(session), 60 * 60 * 24); // 1 day cookie. + cookie.delete(this.SESSION_COOKIE); + cookie.delete(this.OPERATOR_COOKIE); + cookie.set(this.SESSION_COOKIE, JSON.stringify(session), 60 * 60 * 24); // 1 day cookie. if (session?.operator_pid) { - this.cookie.setCookie(this.OPERATOR_COOKIE, session.operator_pid[0], 7 * 24 * 60 * 60); // 1 week cookie. + cookie.set(this.OPERATOR_COOKIE, session.operator_pid[0], 7 * 24 * 60 * 60); // 1 week cookie. } } @@ -126,12 +125,12 @@ export class LivechatService { * never be called if the session was not persisted. */ async leaveSession({ notifyServer = true } = {}) { - const session = JSON.parse(this.cookie.current[this.SESSION_COOKIE] ?? "{}"); + const session = JSON.parse(cookie.get(this.SESSION_COOKIE) ?? "{}"); if (this.state === SESSION_STATE.PERSISTED && notifyServer) { this.busService.deleteChannel(session.uuid); await this.rpc("/im_livechat/visitor_leave_session", { uuid: session.uuid }); } - this.cookie.deleteCookie(this.SESSION_COOKIE); + cookie.delete(this.SESSION_COOKIE); this.state = SESSION_STATE.NONE; this.sessionInitialized = false; } @@ -187,7 +186,7 @@ export class LivechatService { channel_id: this.options.channel_id, anonymous_name: this.userName, chatbot_script_id: chatbotScriptId, - previous_operator_id: this.cookie.current[this.OPERATOR_COOKIE], + previous_operator_id: cookie.get(this.OPERATOR_COOKIE), persisted: persist, }, { shadow: true } @@ -196,7 +195,7 @@ export class LivechatService { if (!threadData?.operator_pid) { this.notificationService.add(_t("No available collaborator, please try again later.")); this.state = SESSION_STATE.NONE; - this.cookie.deleteCookie(this.SESSION_COOKIE); + cookie.delete(this.SESSION_COOKIE); return; } this.updateSession(threadData); @@ -236,14 +235,14 @@ export class LivechatService { } get sessionCookie() { - return JSON.parse(this.cookie.current[this.SESSION_COOKIE] ?? "false"); + return JSON.parse(cookie.get(this.SESSION_COOKIE) ?? "false"); } get shouldRestoreSession() { if (this.state !== SESSION_STATE.NONE) { return false; } - return Boolean(this.cookie.current[this.SESSION_COOKIE]); + return Boolean(cookie.get(this.SESSION_COOKIE)); } /** @@ -274,7 +273,6 @@ export class LivechatService { export const livechatService = { dependencies: [ "bus_service", - "cookie", "mail.chat_window", "mail.store", "notification", diff --git a/addons/im_livechat/static/tests/embed/autopopup_tests.js b/addons/im_livechat/static/tests/embed/autopopup_tests.js index d1f17f0d108..60f31c9b5b0 100644 --- a/addons/im_livechat/static/tests/embed/autopopup_tests.js +++ b/addons/im_livechat/static/tests/embed/autopopup_tests.js @@ -2,11 +2,12 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; -import { start, setCookie, loadDefaultConfig } from "@im_livechat/../tests/embed/helper/test_utils"; +import { start, loadDefaultConfig } from "@im_livechat/../tests/embed/helper/test_utils"; import { Command } from "@mail/../tests/helpers/command"; import { contains } from "@web/../tests/utils"; +import { cookie } from "@web/core/browser/cookie"; QUnit.module("autopopup"); @@ -25,7 +26,7 @@ QUnit.test("persisted session", async () => { livechat_operator_id: pyEnv.adminPartnerId, }); const [channelInfo] = pyEnv.mockServer._mockDiscussChannelChannelInfo([channelId]); - setCookie("im_livechat_session", JSON.stringify(channelInfo)); + cookie.set("im_livechat_session", JSON.stringify(channelInfo)); start(); await contains(".o-mail-ChatWindow"); }); diff --git a/addons/im_livechat/static/tests/embed/helper/test_utils.js b/addons/im_livechat/static/tests/embed/helper/test_utils.js index 09edd35fa92..db497ddde2d 100644 --- a/addons/im_livechat/static/tests/embed/helper/test_utils.js +++ b/addons/im_livechat/static/tests/embed/helper/test_utils.js @@ -13,27 +13,9 @@ import { registry } from "@web/core/registry"; import { patch } from "@web/core/utils/patch"; import { session } from "@web/session"; import { registerCleanup } from "@web/../tests/helpers/cleanup"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; import { patchWithCleanup, makeDeferred } from "@web/../tests/helpers/utils"; import { createWebClient } from "@web/../tests/webclient/helpers"; -// ============================================================================= -// HELPERS -// ============================================================================= - -let cookie = {}; -QUnit.testDone(() => (cookie = {})); - -/** - * Set a cookie to be used by the current test. - * - * @param {string} key - * @param {string} val - */ -export function setCookie(key, val) { - cookie[key] = val; -} - // ============================================================================= // SETUP // ============================================================================= @@ -84,24 +66,6 @@ patch(App.prototype, { */ export async function start({ mockRPC } = {}) { setupManager.setupServiceRegistries(); - registry.category("services").add( - "cookie", - { - start() { - const service = fakeCookieService.start(...arguments); - return { - ...service, - get current() { - return { - ...service.current, - ...cookie, - }; - }, - }; - }, - }, - { force: true } - ); const mainComponentRegistry = registry.category("main_components"); mainComponentRegistry.add("LivechatButton", { Component: LivechatButton }); mainComponentRegistry.add("ChatWindowContainer", { Component: ChatWindowContainer }); diff --git a/addons/im_livechat/static/tests/embed/livechat_service_tests.js b/addons/im_livechat/static/tests/embed/livechat_service_tests.js index 1dc30c58f8e..c69949a54a9 100644 --- a/addons/im_livechat/static/tests/embed/livechat_service_tests.js +++ b/addons/im_livechat/static/tests/embed/livechat_service_tests.js @@ -2,11 +2,12 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; -import { loadDefaultConfig, setCookie, start } from "@im_livechat/../tests/embed/helper/test_utils"; +import { loadDefaultConfig, start } from "@im_livechat/../tests/embed/helper/test_utils"; import { Command } from "@mail/../tests/helpers/command"; import { click, contains } from "@web/../tests/utils"; +import { cookie } from "@web/core/browser/cookie"; QUnit.module("livechat service"); @@ -25,7 +26,7 @@ QUnit.test("persisted session history", async () => { livechat_operator_id: pyEnv.adminPartnerId, }); const [channelInfo] = pyEnv.mockServer._mockDiscussChannelChannelInfo([channelId]); - setCookie("im_livechat_session", JSON.stringify(channelInfo)); + cookie.set("im_livechat_session", JSON.stringify(channelInfo)); pyEnv["mail.message"].create({ author_id: pyEnv.adminPartnerId, body: "Old message in history", @@ -43,7 +44,7 @@ QUnit.test("previous operator prioritized", async () => { const userId = pyEnv["res.users"].create({ name: "John Doe", im_status: "online" }); const previousOperatorId = pyEnv["res.partner"].create({ user_ids: [userId] }); pyEnv["im_livechat.channel"].write([livechatChannelId], { user_ids: [Command.link(userId)] }); - setCookie("im_livechat_previous_operator_pid", JSON.stringify(previousOperatorId)); + cookie.set("im_livechat_previous_operator_pid", JSON.stringify(previousOperatorId)); start(); click(".o-livechat-LivechatButton"); await contains(".o-mail-Message-author", { text: "John Doe" }); diff --git a/addons/im_livechat/static/tests/embed/unread_messages_tests.js b/addons/im_livechat/static/tests/embed/unread_messages_tests.js index 6aee6b156a8..ff198af1f35 100644 --- a/addons/im_livechat/static/tests/embed/unread_messages_tests.js +++ b/addons/im_livechat/static/tests/embed/unread_messages_tests.js @@ -2,11 +2,12 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; -import { loadDefaultConfig, setCookie, start } from "@im_livechat/../tests/embed/helper/test_utils"; +import { loadDefaultConfig, start } from "@im_livechat/../tests/embed/helper/test_utils"; import { Command } from "@mail/../tests/helpers/command"; import { contains, focus } from "@web/../tests/utils"; +import { cookie } from "@web/core/browser/cookie"; QUnit.module("thread service"); @@ -25,7 +26,7 @@ QUnit.test("new message from operator displays unread counter", async () => { livechat_operator_id: pyEnv.adminPartnerId, }); const [channelInfo] = pyEnv.mockServer._mockDiscussChannelChannelInfo([channelId]); - setCookie("im_livechat_session", JSON.stringify(channelInfo)); + cookie.set("im_livechat_session", JSON.stringify(channelInfo)); const env = await start(); $(".o-mail-Composer-input").blur(); pyEnv.withUser(pyEnv.adminUserId, () => @@ -53,7 +54,7 @@ QUnit.test("focus on unread livechat marks it as read", async () => { livechat_operator_id: pyEnv.adminPartnerId, }); const [channelInfo] = pyEnv.mockServer._mockDiscussChannelChannelInfo([channelId]); - setCookie("im_livechat_session", JSON.stringify(channelInfo)); + cookie.set("im_livechat_session", JSON.stringify(channelInfo)); const env = await start(); $(".o-mail-Composer-input").blur(); pyEnv.withUser(pyEnv.adminUserId, () => diff --git a/addons/mail/static/src/core/common/message.js b/addons/mail/static/src/core/common/message.js index 6b5771478df..b8f1458d7c8 100644 --- a/addons/mail/static/src/core/common/message.js +++ b/addons/mail/static/src/core/common/message.js @@ -34,6 +34,7 @@ import { usePopover } from "@web/core/popover/popover_hook"; import { useService } from "@web/core/utils/hooks"; import { url } from "@web/core/utils/urls"; import { useMessageActions } from "./message_actions"; +import { cookie } from "@web/core/browser/cookie"; /** * @typedef {Object} Props @@ -156,8 +157,7 @@ export class Message extends Component { const body = document.createElement("span"); body.innerHTML = this.message.body; this.insertReadMoreLess($(body)); - const color = - this.env.services.cookie?.current.color_scheme === "dark" ? "white" : "black"; + const color = cookie.get("color_scheme") === "dark" ? "white" : "black"; this.shadowStyle = document.createElement("style"); this.shadowStyle.innerHTML = ` * { diff --git a/addons/mrp_subcontracting/__manifest__.py b/addons/mrp_subcontracting/__manifest__.py index f0de6e4e258..e090edcc95e 100644 --- a/addons/mrp_subcontracting/__manifest__.py +++ b/addons/mrp_subcontracting/__manifest__.py @@ -62,7 +62,6 @@ 'web/static/src/legacy/js/promise_extension.js', 'web/static/src/module_loader.js', 'web/static/src/session.js', - 'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/lib/luxon/luxon.js', 'web/static/lib/owl/owl.js', diff --git a/addons/pos_self_order/static/src/app/components/language_popup/language_popup.js b/addons/pos_self_order/static/src/app/components/language_popup/language_popup.js index fd6bf0d6e13..1e8e840c3ef 100644 --- a/addons/pos_self_order/static/src/app/components/language_popup/language_popup.js +++ b/addons/pos_self_order/static/src/app/components/language_popup/language_popup.js @@ -2,14 +2,13 @@ import { Component } from "@odoo/owl"; import { useSelfOrder } from "@pos_self_order/app/self_order_service"; -import { useService } from "@web/core/utils/hooks"; +import { cookie } from "@web/core/browser/cookie"; export class LanguagePopup extends Component { static template = "pos_self_order.LanguagePopup"; setup() { this.selfOrder = useSelfOrder(); - this.cookie = useService("cookie"); } get languages() { @@ -21,7 +20,7 @@ export class LanguagePopup extends Component { } onClickLanguage(language) { - this.cookie.setCookie("frontend_lang", language.code); + cookie.set("frontend_lang", language.code); window.location.reload(); } } diff --git a/addons/pos_self_order/static/src/app/pages/payment_success_page/payment_success_page.js b/addons/pos_self_order/static/src/app/pages/payment_success_page/payment_success_page.js index a8899383a20..6f2bad420c9 100644 --- a/addons/pos_self_order/static/src/app/pages/payment_success_page/payment_success_page.js +++ b/addons/pos_self_order/static/src/app/pages/payment_success_page/payment_success_page.js @@ -2,6 +2,7 @@ import { Component, onMounted, useState } from "@odoo/owl"; import { useSelfOrder } from "@pos_self_order/app/self_order_service"; +import { cookie } from "@web/core/browser/cookie"; import { useService } from "@web/core/utils/hooks"; // This component is only use in Kiosk mode @@ -12,7 +13,6 @@ export class PaymentSuccessPage extends Component { this.selfOrder = useSelfOrder(); this.selfOrder.isOrder(); this.router = useService("router"); - this.cookie = useService("cookie"); this.state = useState({ onReload: false, }); @@ -33,7 +33,7 @@ export class PaymentSuccessPage extends Component { setDefautLanguage() { const defaultLanguage = this.selfOrder.config.self_ordering_default_language_id; if (this.selfOrder.currentLanguage.code !== defaultLanguage.code && !this.state.onReload) { - this.cookie.setCookie("frontend_lang", defaultLanguage.code); + cookie.set("frontend_lang", defaultLanguage.code); window.location.reload(); this.state.onReload = true; return true; diff --git a/addons/pos_self_order/static/src/app/self_order_service.js b/addons/pos_self_order/static/src/app/self_order_service.js index 0a4ad32dd1a..79d2f1704b5 100644 --- a/addons/pos_self_order/static/src/app/self_order_service.js +++ b/addons/pos_self_order/static/src/app/self_order_service.js @@ -13,6 +13,7 @@ import { batched } from "@web/core/utils/timing"; import { useState } from "@odoo/owl"; import { useService } from "@web/core/utils/hooks"; import { registry } from "@web/core/registry"; +import { cookie } from "@web/core/browser/cookie"; export class SelfOrder extends Reactive { constructor(...args) { @@ -20,11 +21,10 @@ export class SelfOrder extends Reactive { this.ready = this.setup(...args).then(() => this); } - async setup(env, { rpc, notification, router, cookie }) { + async setup(env, { rpc, notification, router }) { // services this.notification = notification; this.router = router; - this.cookie = cookie; this.env = env; this.rpc = rpc; @@ -80,14 +80,14 @@ export class SelfOrder extends Reactive { initData() { this.currentLanguage = this.config.self_ordering_available_language_ids.find( - (l) => l.code === this.cookie.current.frontend_lang + (l) => l.code === cookie.get("frontend_lang") ); if (this.config.self_ordering_default_language_id && !this.currentLanguage) { this.currentLanguage = this.config.self_ordering_default_language_id; } - this.cookie.setCookie("frontend_lang", this.currentLanguage.code); + cookie.set("frontend_lang", this.currentLanguage.code); this.products = this.products.map((p) => { const product = new Product(p, this.config.iface_tax_included); @@ -437,9 +437,9 @@ export class SelfOrder extends Reactive { } export const selfOrderService = { - dependencies: ["rpc", "notification", "router", "cookie"], - async start(env, { rpc, notification, router, cookie }) { - return new SelfOrder(env, { rpc, notification, router, cookie }).ready; + dependencies: ["rpc", "notification", "router"], + async start(env, { rpc, notification, router }) { + return new SelfOrder(env, { rpc, notification, router }).ready; }, }; diff --git a/addons/project/__manifest__.py b/addons/project/__manifest__.py index b142d671cd3..e2935f46823 100644 --- a/addons/project/__manifest__.py +++ b/addons/project/__manifest__.py @@ -112,7 +112,6 @@ 'web/static/src/legacy/js/promise_extension.js', 'web/static/src/module_loader.js', 'web/static/src/session.js', - 'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/lib/luxon/luxon.js', 'web/static/lib/owl/owl.js', diff --git a/addons/project/static/tests/burndown_chart_tests.js b/addons/project/static/tests/burndown_chart_tests.js index 1da286af8e0..64856a0e96a 100644 --- a/addons/project/static/tests/burndown_chart_tests.js +++ b/addons/project/static/tests/burndown_chart_tests.js @@ -5,10 +5,9 @@ import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils import { setupControlPanelServiceRegistry, toggleSearchBarMenu, toggleMenuItem, toggleMenuItemOption } from "@web/../tests/search/helpers"; import { makeView } from "@web/../tests/views/helpers"; import { registry } from "@web/core/registry"; -import { makeFakeNotificationService, fakeCookieService } from "@web/../tests/helpers/mock_services"; +import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services"; import { getFirstElementForXpath } from './project_test_utils'; -const serviceRegistry = registry.category("services"); QUnit.module("Project", {}, () => { QUnit.module("Views", (hooks) => { let makeViewParams; @@ -79,7 +78,6 @@ QUnit.module("Project", {}, () => { registry.category("services").add("notification", makeFakeNotificationService(notificationMock), { force: true, }); - serviceRegistry.add("cookie", fakeCookieService); }); QUnit.module("BurndownChart"); diff --git a/addons/project/static/tests/views/project_task_graph/project_task_graph_view_tests.js b/addons/project/static/tests/views/project_task_graph/project_task_graph_view_tests.js index 598a3cb7d5f..f0223d6d035 100644 --- a/addons/project/static/tests/views/project_task_graph/project_task_graph_view_tests.js +++ b/addons/project/static/tests/views/project_task_graph/project_task_graph_view_tests.js @@ -1,8 +1,5 @@ /** @odoo-module **/ -import { registry } from "@web/core/registry"; - -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; import { getFixture } from "@web/../tests/helpers/utils"; import { checkLabels, checkLegend, selectMode } from "@web/../tests/views/graph_view_tests"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; @@ -61,7 +58,6 @@ QUnit.module("Project", (hooks) => { setupViewRegistries(); target = getFixture(); - registry.category("services").add("cookie", fakeCookieService); }); QUnit.module("ProjectTaskGraphView"); diff --git a/addons/survey/static/src/js/survey_form.js b/addons/survey/static/src/js/survey_form.js index 89d596949ed..d195e93d068 100644 --- a/addons/survey/static/src/js/survey_form.js +++ b/addons/survey/static/src/js/survey_form.js @@ -3,7 +3,7 @@ import publicWidget from "@web/legacy/js/public/public_widget"; import { _t } from "@web/core/l10n/translation"; import dom from "@web/legacy/js/core/dom"; -import {getCookie, setCookie, deleteCookie} from "@web/legacy/js/core/cookie_utils"; +import { cookie } from "@web/core/browser/cookie"; import { utils as uiUtils } from "@web/core/ui/ui_service"; import SurveyPreloadImageMixin from "@survey/js/survey_preload_image_mixin"; @@ -57,8 +57,8 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa self.imgZoomer = false; // Add Survey cookie to retrieve the survey if you quit the page and restart the survey. - if (!getCookie('survey_' + self.options.surveyToken)) { - setCookie('survey_' + self.options.surveyToken, self.options.answerToken, 60 * 60 * 24, 'optional'); + if (!cookie.get('survey_' + self.options.surveyToken)) { + cookie.set('survey_' + self.options.surveyToken, self.options.answerToken, 60 * 60 * 24, 'optional'); } // Init fields @@ -426,7 +426,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa var selectorsToFadeout = ['.o_survey_form_content']; if (options.isFinish && !this.nextScreenResult.has_skipped_questions) { selectorsToFadeout.push('.breadcrumb', '.o_survey_timer'); - deleteCookie('survey_' + self.options.surveyToken); + cookie.delete('survey_' + self.options.surveyToken); } self.$(selectorsToFadeout.join(',')).fadeOut(this.fadeInOutDelay, function () { resolveFadeOut(); diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index b9cf9fb81ae..2537e872a43 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -67,7 +67,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/scss/name_and_signature.scss', 'web/static/src/legacy/js/promise_extension.js', - 'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/lib/jquery/jquery.js', 'web/static/lib/jquery.ui/jquery-ui.js', @@ -159,7 +158,7 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/promise_extension.js', 'web/static/src/module_loader.js', 'web/static/src/session.js', - 'web/static/src/legacy/js/core/cookie_utils.js', + 'web/static/src/core/browser/cookie.js', 'web/static/src/legacy/js/public/lazyloader.js', ], 'web.assets_frontend': [ @@ -274,7 +273,7 @@ This module provides the core of the Odoo Web Client. ('remove', 'web/static/src/legacy/js/promise_extension.js'), ('remove', 'web/static/src/module_loader.js'), ('remove', 'web/static/src/session.js'), - ('remove', 'web/static/src/legacy/js/core/cookie_utils.js'), + ('remove', 'web/static/src/core/browser/cookie.js'), ('remove', 'web/static/src/legacy/js/public/lazyloader.js'), ], # Optional Bundle for PDFJS lib diff --git a/addons/web/static/src/core/browser/cookie.js b/addons/web/static/src/core/browser/cookie.js new file mode 100644 index 00000000000..98c86fd4237 --- /dev/null +++ b/addons/web/static/src/core/browser/cookie.js @@ -0,0 +1,39 @@ +/** @odoo-module **/ + +/** + * Utils to make use of document.cookie + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies + * As recommended, storage should not be done by the cookie + * but with localStorage/sessionStorage + */ + +const COOKIE_TTL = 24 * 60 * 60 * 365; + +export const cookie = { + get _cookieMonster() { + return document.cookie; + }, + set _cookieMonster(value) { + document.cookie = value; + }, + get(str) { + const parts = this._cookieMonster.split("; "); + for (const part of parts) { + const [key, value] = part.split(/=(.*)/); + if (key === str) { + return value || ""; + } + } + }, + set(key, value, ttl = COOKIE_TTL) { + let fullCookie = []; + if (value !== undefined) { + fullCookie.push(`${key}=${value}`); + } + fullCookie = fullCookie.concat(["path=/", `max-age=${ttl}`]); + this._cookieMonster = fullCookie.join("; "); + }, + delete(key) { + this.set(key, "kill", 0); + }, +}; diff --git a/addons/web/static/src/core/browser/cookie_service.js b/addons/web/static/src/core/browser/cookie_service.js deleted file mode 100644 index 2ce1204442e..00000000000 --- a/addons/web/static/src/core/browser/cookie_service.js +++ /dev/null @@ -1,61 +0,0 @@ -/** @odoo-module **/ - -import { registry } from "../registry"; - -/** - * Service to make use of document.cookie - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies - * As recommended, storage should not be done by the cookie - * but with localStorage/sessionStorage - */ - -const COOKIE_TTL = 24 * 60 * 60 * 365; - -function parseCookieString(str) { - const cookie = {}; - const parts = str.split("; "); - for (const part of parts) { - const [key, value] = part.split(/=(.*)/); - cookie[key] = value || ""; - } - return cookie; -} - -function cookieToString(key, value, ttl = COOKIE_TTL) { - let fullCookie = []; - if (value !== undefined) { - fullCookie.push(`${key}=${value}`); - } - fullCookie = fullCookie.concat(["path=/", `max-age=${ttl}`]); - return fullCookie.join(";"); -} - -function makeCookieService() { - function getCurrent() { - return parseCookieString(document.cookie); - } - let cookie = getCurrent(); - function setCookie(key, value, ttl) { - // TODO When this will be used from website pages, recover the - // optional cookie mechanism. - document.cookie = cookieToString(key, value, ttl); - cookie = getCurrent(); - } - return { - get current() { - return cookie; - }, - setCookie, - deleteCookie(key) { - setCookie(key, "kill", 0); - }, - }; -} - -export const cookieService = { - start() { - return makeCookieService(); - }, -}; - -registry.category("services").add("cookie", cookieService); diff --git a/addons/web/static/src/legacy/js/core/cookie_utils.js b/addons/web/static/src/legacy/js/core/cookie_utils.js deleted file mode 100644 index 1a79c466f20..00000000000 --- a/addons/web/static/src/legacy/js/core/cookie_utils.js +++ /dev/null @@ -1,76 +0,0 @@ -/** @odoo-module **/ - -/** - * Reads the cookie described by the given name. - * - * @param {string} cookieName - * @returns {string} - */ -export function getCookie(cookieName) { - var cookies = document.cookie ? document.cookie.split('; ') : []; - for (var i = 0, l = cookies.length; i < l; i++) { - var parts = cookies[i].split('='); - var name = parts.shift(); - var cookie = parts.join('='); - - if (cookieName && cookieName === name) { - if (cookie.startsWith('"')) { - if (cookie.includes('\\')){ - // see werkzeug _cookie_quote - throw new Error( - `Cookie value contains unknown characters ${cookie}` - ) - } - cookie = cookie.slice(1, -1); - } - return cookie; - } - } - return ""; -} -/** - * Check if cookie can be written. - * - * @param {String} type the type of the cookie - * @returns {boolean} - */ -export function isAllowedCookie(type) { - return true; -} -/** - * Creates a cookie. - * - * @param {string} name the name of the cookie - * @param {string} value the value stored in the cookie - * @param {integer} ttl time to live of the cookie in millis. -1 to erase the cookie. - * @param {string} type the type of the cookies ('required' as default value) - */ -export function setCookie(name, value, ttl = 31536000, type = 'required') { - ttl = isAllowedCookie(type) ? ttl || 24 * 60 * 60 * 365 : -1; - document.cookie = [ - `${name}=${value}`, - 'path=/', - `max-age=${ttl}`, - `expires=${new Date(new Date().getTime() + ttl * 1000).toGMTString()}`, - ].join(';'); -} -/** - * Deletes a cookie. - * - * @param {string} name the name of the cookie - */ -export function deleteCookie(name) { - document.cookie = [ - `${name}=`, - 'path=/', - `max-age=-1`, - `expires=${new Date(new Date().getTime() - 1000).toGMTString()}`, - ].join(';'); -} - -export default { - deleteCookie, - setCookie, - getCookie, - isAllowedCookie -}; diff --git a/addons/web/static/src/legacy/js/public/public_root.js b/addons/web/static/src/legacy/js/public/public_root.js index ced9f746fbb..131b61d625b 100644 --- a/addons/web/static/src/legacy/js/public/public_root.js +++ b/addons/web/static/src/legacy/js/public/public_root.js @@ -2,7 +2,7 @@ import dom from '@web/legacy/js/core/dom'; import legacyEnv from '@web/legacy/js/public/public_env'; -import {getCookie} from '@web/legacy/js/core/cookie_utils'; +import { cookie } from "@web/core/browser/cookie"; import publicWidget from '@web/legacy/js/public/public_widget'; import { registry } from '@web/core/registry'; @@ -32,7 +32,7 @@ function getLang() { var html = document.documentElement; return (html.getAttribute('lang') || 'en_US').replace('-', '_'); } -const lang = getCookie('frontend_lang') || getLang(); // FIXME the cookie value should maybe be in the ctx? +const lang = cookie.get('frontend_lang') || getLang(); // FIXME the cookie value should maybe be in the ctx? // momentjs don't have config for en_US, so avoid useless RPC var localeDef = lang !== 'en_US' ? loadJS('/web/webclient/locale/' + lang.replace('-', '_')) : Promise.resolve(); diff --git a/addons/web/static/src/views/fields/ace/ace_field.js b/addons/web/static/src/views/fields/ace/ace_field.js index 17bba273681..0113fda56b0 100644 --- a/addons/web/static/src/views/fields/ace/ace_field.js +++ b/addons/web/static/src/views/fields/ace/ace_field.js @@ -2,13 +2,14 @@ import { _t } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; -import { useBus, useService } from "@web/core/utils/hooks"; +import { useBus } from "@web/core/utils/hooks"; import { standardFieldProps } from "../standard_field_props"; import { CodeEditor } from "@web/core/code_editor/code_editor"; import { Component, useState } from "@odoo/owl"; import { useRecordObserver } from "@web/model/relational_model/utils"; import { formatText } from "@web/views/fields/formatters"; +import { cookie } from "@web/core/browser/cookie"; export class AceField extends Component { static template = "web.AceField"; @@ -22,8 +23,6 @@ export class AceField extends Component { static components = { CodeEditor }; setup() { - this.cookies = useService("cookie"); - this.state = useState({}); useRecordObserver((record) => { this.state.initialValue = formatText(record.data[this.props.name]); @@ -42,7 +41,7 @@ export class AceField extends Component { return this.props.mode === "xml" ? "qweb" : this.props.mode; } get theme() { - return this.cookies.current.color_scheme === "dark" ? "monokai" : ""; + return cookie.get("color_scheme") === "dark" ? "monokai" : ""; } handleChange(editedValue) { diff --git a/addons/web/static/src/views/fields/journal_dashboard_graph/journal_dashboard_graph_field.js b/addons/web/static/src/views/fields/journal_dashboard_graph/journal_dashboard_graph_field.js index 80013161b69..eeec2237fc4 100644 --- a/addons/web/static/src/views/fields/journal_dashboard_graph/journal_dashboard_graph_field.js +++ b/addons/web/static/src/views/fields/journal_dashboard_graph/journal_dashboard_graph_field.js @@ -4,9 +4,9 @@ import { loadJS } from "@web/core/assets"; import { registry } from "@web/core/registry"; import { getColor, hexToRGBA } from "@web/core/colors/colors"; import { standardFieldProps } from "../standard_field_props"; -import { useService } from "@web/core/utils/hooks"; import { Component, onWillStart, useEffect, useRef } from "@odoo/owl"; +import { cookie } from "@web/core/browser/cookie"; export class JournalDashboardGraphField extends Component { static template = "web.JournalDashboardGraphField"; @@ -17,7 +17,6 @@ export class JournalDashboardGraphField extends Component { setup() { this.chart = null; - this.cookies = useService("cookie"); this.canvasRef = useRef("canvas"); this.data = JSON.parse(this.props.record.data[this.props.name]); @@ -53,7 +52,7 @@ export class JournalDashboardGraphField extends Component { const labels = this.data[0].values.map(function (pt) { return pt.x; }); - const color10 = getColor(10, this.cookies.current.color_scheme); + const color10 = getColor(10, cookie.get("color_scheme")); const borderColor = this.data[0].is_sample_data ? hexToRGBA(color10, 0.1) : color10; const backgroundColor = this.data[0].is_sample_data ? hexToRGBA(color10, 0.05) @@ -105,8 +104,8 @@ export class JournalDashboardGraphField extends Component { const labels = []; const backgroundColor = []; - const color13 = getColor(13, this.cookies.current.color_scheme); - const color19 = getColor(19, this.cookies.current.color_scheme); + const color13 = getColor(13, cookie.get("color_scheme")); + const color19 = getColor(19, cookie.get("color_scheme")); this.data[0].values.forEach((pt) => { data.push(pt.value); labels.push(pt.label); diff --git a/addons/web/static/src/views/graph/graph_renderer.js b/addons/web/static/src/views/graph/graph_renderer.js index ea9fa6afd2a..2a83db22b98 100644 --- a/addons/web/static/src/views/graph/graph_renderer.js +++ b/addons/web/static/src/views/graph/graph_renderer.js @@ -12,6 +12,7 @@ import { useService } from "@web/core/utils/hooks"; import { Component, onWillUnmount, useEffect, useRef, onWillStart } from "@odoo/owl"; import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; +import { cookie } from "@web/core/browser/cookie"; const NO_DATA = _t("No data"); @@ -50,7 +51,6 @@ export class GraphRenderer extends Component { this.rootRef = useRef("root"); this.canvasRef = useRef("canvas"); this.containerRef = useRef("container"); - this.cookies = useService("cookie"); this.actionService = useService("action"); this.chart = null; @@ -220,11 +220,11 @@ export class GraphRenderer extends Component { dataset.stack = domains[dataset.originIndex].description || ""; } // set dataset color - dataset.backgroundColor = getColor(index, this.cookies.current.color_scheme); + dataset.backgroundColor = getColor(index, cookie.get("color_scheme")); } if (lineOverlayDataset) { // Mutate the lineOverlayDataset to include the config on how it will be displayed. - const color = this.cookies.current.color_scheme === "dark" ? "ffffff" : "000000"; + const color = cookie.get("color_scheme") === "dark" ? "ffffff" : "000000"; Object.assign(lineOverlayDataset, { type: "line", order: -1, @@ -316,7 +316,7 @@ export class GraphRenderer extends Component { const fillStyle = label === NO_DATA ? DEFAULT_BG - : getColor(index, this.cookies.current.color_scheme); + : getColor(index, cookie.get("color_scheme")); return { text, fullText, fillStyle, hidden, index }; }); return labels; @@ -357,8 +357,8 @@ export class GraphRenderer extends Component { getLineChartData() { const { groupBy, domains, stacked, cumulated } = this.model.metaData; const data = this.model.data; - const color0 = getColor(0, this.cookies.current.color_scheme); - const color1 = getColor(1, this.cookies.current.color_scheme); + const color0 = getColor(0, cookie.get("color_scheme")); + const color1 = getColor(1, cookie.get("color_scheme")); for (let index = 0; index < data.datasets.length; ++index) { const dataset = data.datasets[index]; if (groupBy.length <= 1 && domains.length > 1) { @@ -369,10 +369,10 @@ export class GraphRenderer extends Component { } else if (dataset.originIndex === 1) { dataset.borderColor = color1; } else { - dataset.borderColor = getColor(index, this.cookies.current.color_scheme); + dataset.borderColor = getColor(index, cookie.get("color_scheme")); } } else { - dataset.borderColor = getColor(index, this.cookies.current.color_scheme); + dataset.borderColor = getColor(index, cookie.get("color_scheme")); } if (data.labels.length === 1) { // shift of the real value to right. This is done to @@ -416,10 +416,8 @@ export class GraphRenderer extends Component { const data = this.model.data; // style/complete data // give same color to same groups from different origins - const colors = data.labels.map((_, index) => - getColor(index, this.cookies.current.color_scheme) - ); - const borderColor = getBorderWhite(this.cookies.current.color_scheme); + const colors = data.labels.map((_, index) => getColor(index, cookie.get("color_scheme"))); + const borderColor = getBorderWhite(cookie.get("color_scheme")); for (const dataset of data.datasets) { dataset.backgroundColor = colors; dataset.borderColor = borderColor; diff --git a/addons/web/static/src/webclient/company_service.js b/addons/web/static/src/webclient/company_service.js index ceabade1fc3..2669c1004a3 100644 --- a/addons/web/static/src/webclient/company_service.js +++ b/addons/web/static/src/webclient/company_service.js @@ -4,6 +4,7 @@ import { browser } from "@web/core/browser/browser"; import { registry } from "@web/core/registry"; import { session } from "@web/session"; import { UPDATE_METHODS } from "@web/core/orm_service"; +import { cookie } from "@web/core/browser/cookie"; const CIDS_HASH_SEPARATOR = "-"; @@ -35,8 +36,8 @@ function computeAllowedCompanyIds(cids) { } export const companyService = { - dependencies: ["user", "router", "cookie", "action"], - start(env, { user, router, cookie, action }) { + dependencies: ["user", "router", "action"], + start(env, { user, router, action }) { let cids; const hash = router.current.hash; if ("cids" in hash) { @@ -47,8 +48,8 @@ export const companyService = { separator = ","; } cids = parseCompanyIds(hash.cids, separator); - } else if ("cids" in cookie.current) { - cids = parseCompanyIds(cookie.current.cids); + } else if (cookie.get("cids")) { + cids = parseCompanyIds(cookie.get("cids")); } const availableCompanies = session.user_companies.allowed_companies; @@ -69,7 +70,7 @@ export const companyService = { const cidsHash = formatCompanyIds(allowedCompanyIds, CIDS_HASH_SEPARATOR); router.replaceState({ cids: cidsHash }, { lock: true }); - cookie.setCookie("cids", formatCompanyIds(allowedCompanyIds)); + cookie.set("cids", formatCompanyIds(allowedCompanyIds)); user.updateContext({ allowed_company_ids: allowedCompanyIds }); // reload the page if changes are being done to `res.company` @@ -115,7 +116,7 @@ export const companyService = { { cids: formatCompanyIds(next, CIDS_HASH_SEPARATOR) }, { lock: true } ); - cookie.setCookie("cids", formatCompanyIds(next)); + cookie.set("cids", formatCompanyIds(next)); browser.setTimeout(() => browser.location.reload()); // history.pushState is a little async }, }; diff --git a/addons/web/static/tests/helpers/mock_services.js b/addons/web/static/tests/helpers/mock_services.js index fb7a95c0c35..32ef1577019 100644 --- a/addons/web/static/tests/helpers/mock_services.js +++ b/addons/web/static/tests/helpers/mock_services.js @@ -203,25 +203,6 @@ export const fakeCommandService = { }, }; -export const fakeCookieService = { - start() { - const cookie = {}; - return { - get current() { - return cookie; - }, - setCookie(key, value) { - if (value !== undefined) { - cookie[key] = value; - } - }, - deleteCookie(key) { - delete cookie[key]; - }, - }; - }, -}; - export const fakeTitleService = { start() { let current = {}; @@ -333,7 +314,6 @@ export const mocks = { color_scheme: () => fakeColorSchemeService, company: () => fakeCompanyService, command: () => fakeCommandService, - cookie: () => fakeCookieService, effect: () => effectService, // BOI The real service ? Is this what we want ? localization: makeFakeLocalizationService, notification: makeFakeNotificationService, diff --git a/addons/web/static/tests/legacy/helpers/test_env.js b/addons/web/static/tests/legacy/helpers/test_env.js index 83455ea95fd..763374af9d3 100644 --- a/addons/web/static/tests/legacy/helpers/test_env.js +++ b/addons/web/static/tests/legacy/helpers/test_env.js @@ -33,7 +33,6 @@ bus: env.bus || new Bus(), debug: env.debug || false, services: { - getCookie() {}, httpRequest(/* route, params = {}, readMethod = 'json' */) { return Promise.resolve(''); }, diff --git a/addons/web/static/tests/setup.js b/addons/web/static/tests/setup.js index e9087884a27..f0c07fd4986 100644 --- a/addons/web/static/tests/setup.js +++ b/addons/web/static/tests/setup.js @@ -16,6 +16,7 @@ transitionConfig.disabled = true; import { patch } from "@web/core/utils/patch"; import { App, EventBus, whenReady } from "@odoo/owl"; import { currencies } from "@web/core/currency"; +import { cookie } from "@web/core/browser/cookie"; function forceLocaleAndTimezoneWithCleanup() { const originalLocale = luxon.Settings.defaultLocale; @@ -71,6 +72,28 @@ function patchOwlApp() { }); } +function patchCookie() { + const cookieJar = {}; + + patchWithCleanup(cookie, { + get _cookieMonster() { + return Object.entries(cookieJar) + .filter(([, value]) => value !== "kill") + .map((cookie) => cookie.join("=")) + .join("; "); + }, + set _cookieMonster(value) { + const cookies = value.split("; "); + for (const cookie of cookies) { + const [key, value] = cookie.split(/=(.*)/); + if (!["path", "max-age"].includes(key)) { + cookieJar[key] = value; + } + } + }, + }); +} + function patchBrowserWithCleanup() { const originalAddEventListener = browser.addEventListener; const originalRemoveEventListener = browser.removeEventListener; @@ -338,6 +361,7 @@ export async function setupTests() { forceLocaleAndTimezoneWithCleanup(); cleanLoadedLanguages(); patchBrowserWithCleanup(); + patchCookie(); patchBodyAddEventListener(); patchEventBus(); patchLegacyBus(); diff --git a/addons/web/static/tests/views/fields/ace_editor_field_tests.js b/addons/web/static/tests/views/fields/ace_editor_field_tests.js index 4ea665b7aa8..5857c0ec7c7 100644 --- a/addons/web/static/tests/views/fields/ace_editor_field_tests.js +++ b/addons/web/static/tests/views/fields/ace_editor_field_tests.js @@ -1,7 +1,6 @@ /** @odoo-module **/ /* global ace */ -import { registry } from "@web/core/registry"; import { click, clickSave, @@ -13,7 +12,6 @@ import { } from "@web/../tests/helpers/utils"; import { pagerNext } from "@web/../tests/search/helpers"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; let serverData; let target; @@ -42,7 +40,6 @@ QUnit.module("Fields", (hooks) => { }; setupViewRegistries(); - registry.category("services").add("cookie", fakeCookieService); }); QUnit.module("AceEditorField"); diff --git a/addons/web/static/tests/views/fields/journal_dashboard_graph_field_tests.js b/addons/web/static/tests/views/fields/journal_dashboard_graph_field_tests.js index e85e7ea2e5e..264fa5c3ebc 100644 --- a/addons/web/static/tests/views/fields/journal_dashboard_graph_field_tests.js +++ b/addons/web/static/tests/views/fields/journal_dashboard_graph_field_tests.js @@ -1,7 +1,5 @@ /** @odoo-module **/ -import { registry } from "@web/core/registry"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; import { click, getFixture, nextTick, triggerEvent } from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; @@ -85,7 +83,6 @@ QUnit.module("Fields", (hooks) => { }; setupViewRegistries(); - registry.category("services").add("cookie", fakeCookieService); }); async function reloadKanbanView(target) { diff --git a/addons/web/static/tests/views/graph_view_tests.js b/addons/web/static/tests/views/graph_view_tests.js index 001e7d895bf..7660416eaee 100644 --- a/addons/web/static/tests/views/graph_view_tests.js +++ b/addons/web/static/tests/views/graph_view_tests.js @@ -29,7 +29,6 @@ import { GraphArchParser } from "@web/views/graph/graph_arch_parser"; import { GraphRenderer } from "@web/views/graph/graph_renderer"; import { onRendered } from "@odoo/owl"; import { patchWithCleanup } from "../helpers/utils"; -import { fakeCookieService } from "@web/../tests/helpers/mock_services"; import { Domain } from "@web/core/domain"; import { SampleServer } from "@web/model/sample_server"; @@ -315,7 +314,6 @@ QUnit.module("Views", (hooks) => { patchWithCleanup(browser, { setTimeout: (fn) => fn() }); target = getFixture(); - registry.category("services").add("cookie", fakeCookieService); }); QUnit.module("GraphView"); diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js index ab4f7cde175..ce39db16878 100644 --- a/addons/web/static/tests/webclient/actions/window_action_tests.js +++ b/addons/web/static/tests/webclient/actions/window_action_tests.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { makeServerError } from "@web/../tests/helpers/mock_server"; -import { fakeCookieService, makeFakeUserService } from "@web/../tests/helpers/mock_services"; +import { makeFakeUserService } from "@web/../tests/helpers/mock_services"; import * as cpHelpers from "@web/../tests/search/helpers"; import { browser } from "@web/core/browser/browser"; import { WarningDialog } from "@web/core/errors/error_dialogs"; @@ -1042,7 +1042,6 @@ QUnit.module("ActionManager", (hooks) => { }); QUnit.test("restore previous view state when switching back", async function (assert) { - registry.category("services").add("cookie", fakeCookieService); serverData.actions[3].views.unshift([false, "graph"]); serverData.views["partner,false,graph"] = ""; const webClient = await createWebClient({ serverData }); @@ -1083,7 +1082,6 @@ QUnit.module("ActionManager", (hooks) => { QUnit.test("view switcher is properly highlighted in graph view", async function (assert) { assert.expect(4); - registry.category("services").add("cookie", fakeCookieService); serverData.actions[3].views.splice(1, 1, [false, "graph"]); serverData.views["partner,false,graph"] = ""; const webClient = await createWebClient({ serverData }); diff --git a/addons/web/tooling/types/services.d.ts b/addons/web/tooling/types/services.d.ts index bbf4c2a99b3..68cbb5dde4f 100644 --- a/addons/web/tooling/types/services.d.ts +++ b/addons/web/tooling/types/services.d.ts @@ -2,7 +2,6 @@ declare module "services" { import { actionService } from "@web/webclient/actions/action_service"; import { commandService } from "@web/core/commands/command_service"; import { companyService } from "@web/webclient/company_service"; - import { cookieService } from "@web/core/browser/cookie_service"; import { dialogService } from "@web/core/dialog/dialog_service"; import { effectService } from "@web/core/effects/effect_service"; import { fieldService } from "@web/core/field_service"; @@ -24,7 +23,6 @@ declare module "services" { action: ReturnType; command: ReturnType; company: ReturnType; - cookie: ReturnType; dialog: ReturnType; effect: ReturnType; field: ReturnType; diff --git a/addons/web_editor/__manifest__.py b/addons/web_editor/__manifest__.py index 99e39272df5..8c2f3a99c28 100644 --- a/addons/web_editor/__manifest__.py +++ b/addons/web_editor/__manifest__.py @@ -51,7 +51,6 @@ Odoo Web Editor widget. 'web/static/src/legacy/js/promise_extension.js', 'web/static/src/module_loader.js', 'web/static/src/session.js', - 'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/lib/luxon/luxon.js', 'web/static/lib/owl/owl.js', diff --git a/addons/website/static/src/js/content/inject_dom.js b/addons/website/static/src/js/content/inject_dom.js index 1768ed4fd32..19dc4dcdfea 100644 --- a/addons/website/static/src/js/content/inject_dom.js +++ b/addons/website/static/src/js/content/inject_dom.js @@ -1,7 +1,7 @@ /** @odoo-module */ -import {getCookie} from '@web/legacy/js/core/cookie_utils'; -import { session } from '@web/session'; +import { cookie as cookieManager } from "@web/core/browser/cookie"; +import { session } from "@web/session"; /** * Unhide elements that are hidden by default and that should be visible @@ -35,7 +35,7 @@ document.addEventListener('DOMContentLoaded', () => { 'utm_campaign': 'utmCampaign', }; for (const [name, dsName] of Object.entries(cookieNamesToDataNames)) { - const cookie = getCookie(`odoo_${name}`); + const cookie = cookieManager.get(`odoo_${name}`); if (cookie) { // Remove leading and trailing " and ' htmlEl.dataset[dsName] = cookie.replace(/(^["']|["']$)/g, ''); diff --git a/addons/website/static/src/js/http_cookie.js b/addons/website/static/src/js/http_cookie.js index 525bfbe6e85..d52d952255d 100644 --- a/addons/website/static/src/js/http_cookie.js +++ b/addons/website/static/src/js/http_cookie.js @@ -1,30 +1,32 @@ /** @odoo-module **/ -import cookieUtils from '@web/legacy/js/core/cookie_utils'; +import { cookie } from "@web/core/browser/cookie"; +import { patch } from "@web/core/utils/patch"; -const originFunc = cookieUtils.isAllowedCookie; -cookieUtils.isAllowedCookie = (type) => { - const result = originFunc.apply(cookieUtils, [type]); - if (result && type === 'optional') { - if (!document.getElementById('cookies-consent-essential')) { - // Cookies bar is disabled on this website. - return true; - } - const consents = JSON.parse(cookieUtils.getCookie('website_cookies_bar') || '{}'); +patch(cookie, { + isAllowedCookie(type) { + if (type === "optional") { + if (!document.getElementById("cookies-consent-essential")) { + // Cookies bar is disabled on this website. + return true; + } + const consents = JSON.parse(cookie.get("website_cookies_bar") || "{}"); - // pre-16.0 compatibility, `website_cookies_bar` was `"true"`. - // In that case we delete that cookie and let the user choose again. - if (typeof consents !== 'object') { - cookieUtils.deleteCookie('website_cookies_bar'); + // pre-16.0 compatibility, `website_cookies_bar` was `"true"`. + // In that case we delete that cookie and let the user choose again. + if (typeof consents !== "object") { + cookie.delete("website_cookies_bar"); + return false; + } + + if ("optional" in consents) { + return consents["optional"]; + } return false; } - - if ('optional' in consents) { - return consents['optional']; - } - return false; - } - // Pass-through if already forbidden for another reason or a type that is - // not restricted by the website module. - return result; -}; + return true; + }, + set(key, value, ttl, type = "required") { + super.set(key, value, this.isAllowedCookie(type) ? ttl : 0); + }, +}); diff --git a/addons/website/static/src/snippets/s_popup/000.js b/addons/website/static/src/snippets/s_popup/000.js index a43753f9439..27b3cb38fbf 100644 --- a/addons/website/static/src/snippets/s_popup/000.js +++ b/addons/website/static/src/snippets/s_popup/000.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import publicWidget from "@web/legacy/js/public/public_widget"; -import {getCookie, setCookie} from "@web/legacy/js/core/cookie_utils"; +import { cookie } from "@web/core/browser/cookie"; import dom from "@web/legacy/js/core/dom"; import {throttleForAnimation} from "@web/core/utils/timing"; import { utils as uiUtils } from "@web/core/ui/ui_service"; @@ -93,7 +93,7 @@ const PopupWidget = publicWidget.Widget.extend({ // "Contact us" page to open a popup on the homepage). this._showPopupOnClick(); } else { - this._popupAlreadyShown = !!getCookie(this.$el.attr('id')); + this._popupAlreadyShown = !!cookie.get(this.$el.attr('id')); if (!this._popupAlreadyShown) { this._bindPopup(); } @@ -212,7 +212,7 @@ const PopupWidget = publicWidget.Widget.extend({ */ _onHideModal: function () { const nbDays = this.$el.find('.modal').data('consentsDuration'); - setCookie(this.el.id, this.cookieValue, nbDays * 24 * 60 * 60, 'required'); + cookie.set(this.el.id, this.cookieValue, nbDays * 24 * 60 * 60, 'required'); this._popupAlreadyShown = true && !this.modalShownOnClickEl; this.$el.find('.media_iframe_video iframe').each((i, iframe) => { diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index 60f0085fea7..922dfbed185 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -3,7 +3,7 @@ import { markup } from "@odoo/owl"; import { FlagMarkAsOffensiveDialog } from "../components/flag_mark_as_offensive/flag_mark_as_offensive"; import dom from "@web/legacy/js/core/dom"; -import {setCookie} from "@web/legacy/js/core/cookie_utils"; +import { cookie } from "@web/core/browser/cookie";; import { loadWysiwygFromTextarea } from "@web_editor/js/frontend/loadWysiwygFromTextarea"; import publicWidget from "@web/legacy/js/public/public_widget"; import { session } from "@web/session"; @@ -538,7 +538,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ */ _onCloseIntroClick: function (ev) { ev.preventDefault(); - setCookie('forum_welcome_message', false, 24 * 60 * 60 * 365, 'optional'); + cookie.set('forum_welcome_message', false, 24 * 60 * 60 * 365, 'optional'); $('.forum_intro').slideUp(); return true; }, diff --git a/addons/website_sale/static/src/js/website_sale_recently_viewed.js b/addons/website_sale/static/src/js/website_sale_recently_viewed.js index 9a034c2659a..c26695d5557 100644 --- a/addons/website_sale/static/src/js/website_sale_recently_viewed.js +++ b/addons/website_sale/static/src/js/website_sale_recently_viewed.js @@ -2,7 +2,7 @@ import { debounce } from "@web/core/utils/timing"; import publicWidget from "@web/legacy/js/public/public_widget"; -import {getCookie, setCookie} from "@web/legacy/js/core/cookie_utils"; +import { cookie } from "@web/core/browser/cookie";; publicWidget.registry.productsRecentlyViewedUpdate = publicWidget.Widget.extend({ selector: '#product_detail', @@ -35,7 +35,7 @@ publicWidget.registry.productsRecentlyViewedUpdate = publicWidget.Widget.extend( if (! parseInt(this.el.dataset.viewTrack, 10)) { return; // Is not tracked } - if (getCookie(cookieName)) { + if (cookie.get(cookieName)) { return; // Already tracked in the last 30min } if ($(this.el).find('.js_product.css_not_available').length) { @@ -44,7 +44,7 @@ publicWidget.registry.productsRecentlyViewedUpdate = publicWidget.Widget.extend( this.rpc('/shop/products/recently_viewed_update', { product_id: productId, }).then(function (res) { - setCookie(cookieName, productId, 30 * 60, 'optional'); + cookie.set(cookieName, productId, 30 * 60, 'optional'); }); }, diff --git a/addons/website_sale_comparison/static/src/js/website_sale_comparison.js b/addons/website_sale_comparison/static/src/js/website_sale_comparison.js index 15b9c0a8fc4..9f72970e770 100644 --- a/addons/website_sale_comparison/static/src/js/website_sale_comparison.js +++ b/addons/website_sale_comparison/static/src/js/website_sale_comparison.js @@ -2,7 +2,7 @@ import { Mutex } from "@web/core/utils/concurrency"; import publicWidget from "@web/legacy/js/public/public_widget"; -import {getCookie, setCookie} from "@web/legacy/js/core/cookie_utils"; +import { cookie } from "@web/core/browser/cookie";; import VariantMixin from "@website_sale/js/sale_variant_mixin"; import website_sale_utils from "@website_sale/js/website_sale_utils"; import { _t } from "@web/core/l10n/translation"; @@ -26,7 +26,7 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, { this._super.apply(this, arguments); this.product_data = {}; - this.comparelist_product_ids = JSON.parse(getCookie('comparelist_product_ids') || '[]'); + this.comparelist_product_ids = JSON.parse(cookie.get('comparelist_product_ids') || '[]'); this.product_compare_limit = 4; this.guard = new Mutex(); this.rpc = this.bindService("rpc"); @@ -138,7 +138,7 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, { var self = this; return this.rpc('/shop/get_product_data', { product_ids: product_ids, - cookies: JSON.parse(getCookie('comparelist_product_ids') || '[]'), + cookies: JSON.parse(cookie.get('comparelist_product_ids') || '[]'), }).then(function (data) { self.comparelist_product_ids = JSON.parse(data.cookies); delete data.cookies; @@ -223,7 +223,7 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, { * @private */ _updateCookie: function () { - setCookie('comparelist_product_ids', JSON.stringify(this.comparelist_product_ids), 24 * 60 * 60 * 365, 'required'); + cookie.set('comparelist_product_ids', JSON.stringify(this.comparelist_product_ids), 24 * 60 * 60 * 365, 'required'); this._updateComparelistView(); }, /** diff --git a/addons/website_slides/__manifest__.py b/addons/website_slides/__manifest__.py index 9163ddbb87c..d9026a5493b 100644 --- a/addons/website_slides/__manifest__.py +++ b/addons/website_slides/__manifest__.py @@ -151,7 +151,6 @@ Featuring 'web/static/src/legacy/js/promise_extension.js', 'web/static/src/module_loader.js', 'web/static/src/session.js', - 'web/static/src/legacy/js/core/cookie_utils.js', 'web/static/lib/luxon/luxon.js', 'web/static/lib/owl/owl.js',