зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1517703 - Part 2 - Use ReferrerInfo in loadURIOptions from js r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D17922 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
92cca5e26c
Коммит
85ce5ab061
|
@ -1041,9 +1041,8 @@ function _loadURI(browser, uri, params = {}) {
|
|||
|
||||
let {
|
||||
flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
|
||||
referrerURI,
|
||||
referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
triggeringPrincipal,
|
||||
referrerInfo,
|
||||
postData,
|
||||
userContextId,
|
||||
} = params || {};
|
||||
|
@ -1076,8 +1075,7 @@ function _loadURI(browser, uri, params = {}) {
|
|||
let loadURIOptions = {
|
||||
triggeringPrincipal,
|
||||
loadFlags: flags,
|
||||
referrerURI,
|
||||
referrerPolicy,
|
||||
referrerInfo,
|
||||
postData,
|
||||
};
|
||||
try {
|
||||
|
@ -1106,8 +1104,7 @@ function _loadURI(browser, uri, params = {}) {
|
|||
? gSerializationHelper.serializeToString(triggeringPrincipal)
|
||||
: null,
|
||||
flags,
|
||||
referrer: referrerURI ? referrerURI.spec : null,
|
||||
referrerPolicy,
|
||||
referrerInfo: E10SUtils.serializeReferrerInfo(referrerInfo),
|
||||
remoteType: requiredRemoteType,
|
||||
postData,
|
||||
newFrameloader,
|
||||
|
|
|
@ -2615,12 +2615,16 @@ window._gBrowser = {
|
|||
if (!allowInheritPrincipal) {
|
||||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
try {
|
||||
b.loadURI(aURI, {
|
||||
flags,
|
||||
triggeringPrincipal,
|
||||
referrerURI: noReferrer ? null : referrerURI,
|
||||
referrerPolicy,
|
||||
referrerInfo: new ReferrerInfo(
|
||||
referrerPolicy, !noReferrer, referrerURI),
|
||||
charset,
|
||||
postData,
|
||||
});
|
||||
|
|
|
@ -511,11 +511,14 @@ function openLinkIn(url, where, params) {
|
|||
{ recordExecution: "*", newFrameloader: true });
|
||||
}
|
||||
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
targetBrowser.loadURI(url, {
|
||||
triggeringPrincipal: aTriggeringPrincipal,
|
||||
referrerInfo: new ReferrerInfo(
|
||||
aReferrerPolicy, !aNoReferrer, aReferrerURI),
|
||||
flags,
|
||||
referrerURI: aNoReferrer ? null : aReferrerURI,
|
||||
referrerPolicy: aReferrerPolicy,
|
||||
postData: aPostData,
|
||||
userContextId: aUserContextId,
|
||||
});
|
||||
|
|
|
@ -12,7 +12,8 @@ ChromeUtils.defineModuleGetter(this, "SessionHistory",
|
|||
"resource://gre/modules/sessionstore/SessionHistory.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
/**
|
||||
* This module implements the content side of session restoration. The chrome
|
||||
* side is handled by SessionStore.jsm. The functions in this module are called
|
||||
|
@ -191,11 +192,24 @@ ContentRestoreInternal.prototype = {
|
|||
|
||||
// A load has been redirected to a new process so get history into the
|
||||
// same state it was before the load started then trigger the load.
|
||||
let referrer = loadArguments.referrer ?
|
||||
Services.io.newURI(loadArguments.referrer) : null;
|
||||
let referrerPolicy = ("referrerPolicy" in loadArguments
|
||||
// Referrer information is now stored as a referrerInfo property. We
|
||||
// should also cope with the old format of passing `referrer` and
|
||||
// `referrerPolicy` separately.
|
||||
let referrerInfo = loadArguments.referrerInfo;
|
||||
if (referrerInfo) {
|
||||
referrerInfo = E10SUtils.deserializeReferrerInfo(referrerInfo);
|
||||
} else {
|
||||
let referrer = loadArguments.referrer ?
|
||||
Services.io.newURI(loadArguments.referrer) : null;
|
||||
let referrerPolicy = ("referrerPolicy" in loadArguments
|
||||
? loadArguments.referrerPolicy
|
||||
: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
|
||||
let ReferrerInfo = Components.Constructor(
|
||||
"@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
referrerInfo = new ReferrerInfo(referrerPolicy, true, referrer);
|
||||
}
|
||||
let postData = loadArguments.postData ?
|
||||
Utils.makeInputStream(loadArguments.postData) : null;
|
||||
let triggeringPrincipal = loadArguments.triggeringPrincipal
|
||||
|
@ -208,8 +222,7 @@ ContentRestoreInternal.prototype = {
|
|||
let loadURIOptions = {
|
||||
triggeringPrincipal,
|
||||
loadFlags: loadArguments.flags,
|
||||
referrerURI: referrer,
|
||||
referrerPolicy,
|
||||
referrerInfo,
|
||||
postData,
|
||||
};
|
||||
webNavigation.loadURI(loadArguments.uri, loadURIOptions);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const REFERRER1 = "http://example.org/?" + Date.now();
|
||||
const REFERRER2 = "http://example.org/?" + Math.random();
|
||||
const REFERRER3 = "http://example.org/?" + Math.random();
|
||||
|
||||
add_task(async function() {
|
||||
async function checkDocumentReferrer(referrer, msg) {
|
||||
|
@ -10,29 +11,42 @@ add_task(async function() {
|
|||
});
|
||||
}
|
||||
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
// Add a new tab.
|
||||
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
|
||||
let browser = tab.linkedBrowser;
|
||||
await promiseBrowserLoaded(browser);
|
||||
|
||||
// Load a new URI with a specific referrer.
|
||||
let referrerURI = Services.io.newURI(REFERRER1);
|
||||
let referrerInfo1 = new ReferrerInfo(
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
true,
|
||||
Services.io.newURI(REFERRER1));
|
||||
browser.loadURI("http://example.org", {
|
||||
referrerURI,
|
||||
referrerInfo: referrerInfo1,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
|
||||
});
|
||||
await promiseBrowserLoaded(browser);
|
||||
|
||||
await TabStateFlusher.flush(browser);
|
||||
let tabState = JSON.parse(ss.getTabState(tab));
|
||||
is(tabState.entries[0].referrer, REFERRER1,
|
||||
let actualReferrerInfo = E10SUtils.
|
||||
deserializeReferrerInfo(tabState.entries[0].referrerInfo);
|
||||
is(actualReferrerInfo.originalReferrer.spec, REFERRER1,
|
||||
"Referrer retrieved via getTabState matches referrer set via loadURI.");
|
||||
|
||||
tabState.entries[0].referrer = REFERRER2;
|
||||
let referrerInfo2 = new ReferrerInfo(
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
true,
|
||||
Services.io.newURI(REFERRER2));
|
||||
|
||||
tabState.entries[0].referrerInfo = E10SUtils.serializeReferrerInfo(referrerInfo2);
|
||||
await promiseTabState(tab, tabState);
|
||||
|
||||
await checkDocumentReferrer(REFERRER2,
|
||||
"document.referrer matches referrer set via setTabState.");
|
||||
"document.referrer matches referrer set via setTabState using referrerInfo.");
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Restore the closed tab.
|
||||
|
@ -41,5 +55,20 @@ add_task(async function() {
|
|||
|
||||
await checkDocumentReferrer(REFERRER2,
|
||||
"document.referrer is still correct after closing and reopening the tab.");
|
||||
|
||||
tabState.entries[0].referrerInfo = null;
|
||||
tabState.entries[0].referrer = REFERRER3;
|
||||
await promiseTabState(tab, tabState);
|
||||
|
||||
await checkDocumentReferrer(REFERRER3,
|
||||
"document.referrer matches referrer set via setTabState using referrer.");
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Restore the closed tab.
|
||||
tab = ss.undoCloseTab(window, 0);
|
||||
await promiseTabRestored(tab);
|
||||
|
||||
await checkDocumentReferrer(REFERRER3,
|
||||
"document.referrer is still correct after closing and reopening the tab.");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { Ci, Cu, Cr } = require("chrome");
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const ChromeUtils = require("ChromeUtils");
|
||||
const Services = require("Services");
|
||||
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
const { Utils } = require("resource://gre/modules/sessionstore/Utils.jsm");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
const { E10SUtils } = require("resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
const telemetry = new Telemetry();
|
||||
|
||||
|
@ -71,11 +72,14 @@ BrowserElementWebNavigation.prototype = {
|
|||
loadURIWithOptions(uri, flags, referrer, referrerPolicy, postData, headers,
|
||||
baseURI, triggeringPrincipal) {
|
||||
// No equivalent in the current BrowserElement API
|
||||
let referrerInfo = Cc["@mozilla.org/referrer-info;1"]
|
||||
.createInstance(Ci.nsIReferrerInfo);
|
||||
referrerInfo.init(referrerPolicy, true, referrer);
|
||||
referrerInfo = E10SUtils.serializeReferrerInfo(referrerInfo);
|
||||
this._sendMessage("WebNavigation:LoadURI", {
|
||||
uri,
|
||||
flags,
|
||||
referrer: referrer ? referrer.spec : null,
|
||||
referrerPolicy: referrerPolicy,
|
||||
referrerInfo,
|
||||
postData: postData ? readInputStreamToString(postData) : null,
|
||||
headers: headers ? readInputStreamToString(headers) : null,
|
||||
baseURI: baseURI ? baseURI.spec : null,
|
||||
|
|
|
@ -14,6 +14,8 @@ ChromeUtils.defineModuleGetter(this, "AppConstants",
|
|||
"resource://gre/modules/AppConstants.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
|
||||
"@mozilla.org/xre/app-info;1",
|
||||
|
@ -41,7 +43,7 @@ class WebNavigationChild extends ActorChild {
|
|||
Services.telemetry.msSystemNow() - message.data.requestTime);
|
||||
|
||||
this.loadURI(message.data.uri, message.data.flags,
|
||||
message.data.referrer, message.data.referrerPolicy,
|
||||
message.data.referrerInfo,
|
||||
message.data.postData, message.data.headers,
|
||||
message.data.baseURI, message.data.triggeringPrincipal);
|
||||
break;
|
||||
|
@ -83,7 +85,7 @@ class WebNavigationChild extends ActorChild {
|
|||
this._wrapURIChangeCall(() => this.webNavigation.gotoIndex(index));
|
||||
}
|
||||
|
||||
loadURI(uri, flags, referrer, referrerPolicy, postData, headers, baseURI, triggeringPrincipal) {
|
||||
loadURI(uri, flags, referrerInfo, postData, headers, baseURI, triggeringPrincipal) {
|
||||
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
|
||||
let annotation = uri;
|
||||
try {
|
||||
|
@ -97,8 +99,6 @@ class WebNavigationChild extends ActorChild {
|
|||
on about: URIs. */ }
|
||||
CrashReporter.annotateCrashReport("URL", annotation);
|
||||
}
|
||||
if (referrer)
|
||||
referrer = Services.io.newURI(referrer);
|
||||
if (postData)
|
||||
postData = Utils.makeInputStream(postData);
|
||||
if (headers)
|
||||
|
@ -116,8 +116,7 @@ class WebNavigationChild extends ActorChild {
|
|||
let loadURIOptions = {
|
||||
triggeringPrincipal,
|
||||
loadFlags: flags,
|
||||
referrerURI: referrer,
|
||||
referrerPolicy,
|
||||
referrerInfo: E10SUtils.deserializeReferrerInfo(referrerInfo),
|
||||
postData,
|
||||
headers,
|
||||
baseURI,
|
||||
|
|
|
@ -100,10 +100,14 @@ var ReaderMode = {
|
|||
return;
|
||||
}
|
||||
let flags = webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
let loadURIOptions = {
|
||||
triggeringPrincipal: principal,
|
||||
loadFlags: flags,
|
||||
referrerURI,
|
||||
referrerInfo: new ReferrerInfo(
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, referrerURI),
|
||||
};
|
||||
webNav.loadURI(originalURL, loadURIOptions);
|
||||
},
|
||||
|
|
|
@ -13,6 +13,8 @@ ChromeUtils.defineModuleGetter(this, "Utils",
|
|||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
|
||||
function makeURI(url) {
|
||||
return Services.io.newURI(url);
|
||||
|
@ -94,8 +96,7 @@ RemoteWebNavigation.prototype = {
|
|||
this._sendMessage("WebNavigation:LoadURI", {
|
||||
uri: aURI,
|
||||
flags: aLoadURIOptions.loadFlags,
|
||||
referrer: aLoadURIOptions.referrerURI ? aLoadURIOptions.referrerURI.spec : null,
|
||||
referrerPolicy: aLoadURIOptions.referrerPolicy,
|
||||
referrerInfo: E10SUtils.serializeReferrerInfo(aLoadURIOptions.referrerInfo),
|
||||
postData: aLoadURIOptions.postData ? Utils.serializeInputStream(aLoadURIOptions.postData) : null,
|
||||
headers: aLoadURIOptions.headers ? Utils.serializeInputStream(aLoadURIOptions.headers) : null,
|
||||
baseURI: aLoadURIOptions.baseURI ? aLoadURIOptions.baseURI.spec : null,
|
||||
|
|
|
@ -15,9 +15,14 @@ function waitForPageShow(browser = gBrowser.selectedBrowser) {
|
|||
add_task(async function test_referrer() {
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
|
||||
let loadURIOptionsWithReferrer = {
|
||||
triggeringPrincipal: SYSTEMPRINCIPAL,
|
||||
referrerURI: Services.io.newURI(DUMMY2),
|
||||
referrerInfo: new ReferrerInfo(
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, Services.io.newURI(DUMMY2)),
|
||||
};
|
||||
browser.webNavigation.loadURI(DUMMY1, loadURIOptionsWithReferrer);
|
||||
await waitForLoad(DUMMY1);
|
||||
|
|
|
@ -599,12 +599,10 @@ var ViewSourceContent = {
|
|||
|
||||
// all our content is held by the data:URI and URIs are internally stored as utf-8 (see nsIURI.idl)
|
||||
let loadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let loadURIOptions = {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
loadFlags,
|
||||
referrerPolicy,
|
||||
baseURI: Services.io.newURI(baseURI),
|
||||
};
|
||||
webNav.loadURI(uri, loadURIOptions);
|
||||
|
|
|
@ -799,20 +799,17 @@ class MozBrowser extends MozElementMixin(XULFrameElement) {
|
|||
if (!aURI) {
|
||||
aURI = "about:blank";
|
||||
}
|
||||
|
||||
let {
|
||||
flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
|
||||
referrerURI,
|
||||
referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
referrerInfo,
|
||||
triggeringPrincipal,
|
||||
postData,
|
||||
headers,
|
||||
} = aParams || {};
|
||||
let loadURIOptions = {
|
||||
triggeringPrincipal,
|
||||
referrerURI,
|
||||
referrerInfo,
|
||||
loadFlags: flags,
|
||||
referrerPolicy,
|
||||
postData,
|
||||
headers,
|
||||
};
|
||||
|
|
|
@ -17,6 +17,9 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "useSeparatePrivilegedContentProcess
|
|||
"browser.tabs.remote.separatePrivilegedContentProcess", false);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, "useHttpResponseProcessSelection",
|
||||
"browser.tabs.remote.useHTTPResponseProcessSelection", false);
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "serializationHelper",
|
||||
"@mozilla.org/network/serialization-helper;1",
|
||||
"nsISerializationHelper");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
|
@ -403,4 +406,40 @@ var E10SUtils = {
|
|||
handlingUserInput.destruct();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Serialize referrerInfo.
|
||||
*
|
||||
* @param {nsIReferrerInfo} The referrerInfo to serialize.
|
||||
* @return {String} The base64 encoded referrerInfo.
|
||||
*/
|
||||
serializeReferrerInfo(referrerInfo) {
|
||||
let serialized = null;
|
||||
if (referrerInfo) {
|
||||
try {
|
||||
serialized = serializationHelper.serializeToString(referrerInfo);
|
||||
} catch (e) {
|
||||
debug(`Failed to serialize referrerInfo '${referrerInfo}' ${e}`);
|
||||
}
|
||||
}
|
||||
return serialized;
|
||||
},
|
||||
/**
|
||||
* Deserialize a base64 encoded referrerInfo
|
||||
*
|
||||
* @param {String} referrerInfo_b64 A base64 encoded serialized referrerInfo.
|
||||
* @return {nsIReferrerInfo} A deserialized referrerInfo.
|
||||
*/
|
||||
deserializeReferrerInfo(referrerInfo_b64) {
|
||||
let deserialized = null;
|
||||
if (referrerInfo_b64) {
|
||||
try {
|
||||
deserialized = serializationHelper.deserializeObject(referrerInfo_b64);
|
||||
deserialized.QueryInterface(Ci.nsIReferrerInfo);
|
||||
} catch (e) {
|
||||
debug(`Failed to deserialize referrerInfo_b64 '${referrerInfo_b64}' ${e}`);
|
||||
}
|
||||
}
|
||||
return deserialized;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -11,6 +11,8 @@ const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm")
|
|||
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidGenerator",
|
||||
"@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
|
||||
|
||||
|
@ -143,9 +145,8 @@ var SessionHistoryInternal = {
|
|||
|
||||
// We will include the property only if it's truthy to save a couple of
|
||||
// bytes when the resulting object is stringified and saved to disk.
|
||||
if (shEntry.referrerURI) {
|
||||
entry.referrer = shEntry.referrerURI.spec;
|
||||
entry.referrerPolicy = shEntry.referrerPolicy;
|
||||
if (shEntry.referrerInfo) {
|
||||
entry.referrerInfo = E10SUtils.serializeReferrerInfo(shEntry.referrerInfo);
|
||||
}
|
||||
|
||||
if (shEntry.originalURI) {
|
||||
|
@ -338,10 +339,19 @@ var SessionHistoryInternal = {
|
|||
shEntry.setLoadTypeAsHistory();
|
||||
if (entry.contentType)
|
||||
shEntry.contentType = entry.contentType;
|
||||
if (entry.referrer) {
|
||||
shEntry.referrerURI = Services.io.newURI(entry.referrer);
|
||||
shEntry.referrerPolicy = entry.referrerPolicy;
|
||||
// Referrer information is now stored as a referrerInfo property. We should
|
||||
// also cope with the old format of passing `referrer` and `referrerPolicy`
|
||||
// separately.
|
||||
if (entry.referrerInfo) {
|
||||
shEntry.referrerInfo = E10SUtils.deserializeReferrerInfo(entry.referrerInfo);
|
||||
} else if (entry.referrer) {
|
||||
let ReferrerInfo = Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init");
|
||||
shEntry.referrerInfo = new ReferrerInfo(
|
||||
entry.referrerPolicy, true, Services.io.newURI(entry.referrer));
|
||||
}
|
||||
|
||||
if (entry.originalURI) {
|
||||
shEntry.originalURI = Services.io.newURI(entry.originalURI);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче