зеркало из https://github.com/mozilla/gecko-dev.git
Merge from e10s clone. a=dougt
This commit is contained in:
Коммит
fc5141bdf6
|
@ -52,6 +52,11 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
|
@ -840,16 +845,18 @@ BrowserGlue.prototype = {
|
|||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var bookmarksFile = null;
|
||||
var bookmarksURI = null;
|
||||
if (restoreDefaultBookmarks) {
|
||||
// User wants to restore bookmarks.html file from default profile folder
|
||||
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
|
||||
bookmarksFile.append("bookmarks.html");
|
||||
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
|
||||
}
|
||||
else {
|
||||
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
if (bookmarksFile.exists())
|
||||
bookmarksURI = NetUtil.newURI(bookmarksFile);
|
||||
}
|
||||
else
|
||||
bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
|
||||
|
||||
if (bookmarksFile.exists()) {
|
||||
if (bookmarksURI) {
|
||||
// Add an import observer. It will ensure that smart bookmarks are
|
||||
// created once the operation is complete.
|
||||
Services.obs.addObserver(this, "bookmarks-restore-success", false);
|
||||
|
@ -859,7 +866,7 @@ BrowserGlue.prototype = {
|
|||
try {
|
||||
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
|
||||
getService(Ci.nsIPlacesImportExportService);
|
||||
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
|
||||
importer.importHTMLFromURI(bookmarksURI, true /* overwrite existing */);
|
||||
} catch (err) {
|
||||
// Report the error, but ignore it.
|
||||
Cu.reportError("Bookmarks.html file could be corrupt. " + err);
|
||||
|
|
|
@ -51,5 +51,9 @@ _TEST_FILES = test_bug423375.html \
|
|||
test_bug470804.html \
|
||||
$(NULL)
|
||||
|
||||
test_bug292789.html : % : %.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
||||
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
|
|
@ -38,7 +38,11 @@ function testScriptSrc(aCallback) {
|
|||
** moved the resource
|
||||
**/
|
||||
var resjs = document.createElement("script");
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#else
|
||||
resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#endif
|
||||
resjs.onload = scriptOnload;
|
||||
document.getElementById("content").appendChild(resjs);
|
||||
|
||||
|
@ -55,7 +59,11 @@ function testScriptSrc(aCallback) {
|
|||
/** <img src=""> tests **/
|
||||
var img_global = "chrome://global/skin/icons/Error.png";
|
||||
var img_mozapps = "chrome://mozapps/skin/passwordmgr/key.png";
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
var res_mozapps = "jar:resource://gre/chrome/toolkit.jar!/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#else
|
||||
var res_mozapps = "resource://gre/chrome/toolkit/skin/classic/mozapps/passwordmgr/key.png";
|
||||
#endif
|
||||
|
||||
var imgTests = [[img_global, "success"],
|
||||
[img_mozapps, "fail"],
|
|
@ -1036,4 +1036,7 @@ event.h
|
|||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
|
|
@ -106,6 +106,11 @@ nsHTMLDNSPrefetch::Initialize()
|
|||
rv = CallGetService(kDNSServiceCID, &sDNSService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (mozilla::net::IsNeckoChild())
|
||||
mozilla::net::NeckoChild::InitNeckoChild();
|
||||
#endif
|
||||
|
||||
sInitialized = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsChromeRegistryChrome.h"
|
||||
#include "nsExternalHelperAppService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
|
@ -470,6 +472,17 @@ ContentParent::RecvSetURITitle(const IPC::URI& uri,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadURIExternal(const IPC::URI& uri)
|
||||
{
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
if (!extProtService)
|
||||
return true;
|
||||
nsCOMPtr<nsIURI> ourURI(uri);
|
||||
extProtService->LoadURI(ourURI, nsnull);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* void onDispatchedEvent (in nsIThreadInternal thread); */
|
||||
NS_IMETHODIMP
|
||||
ContentParent::OnDispatchedEvent(nsIThreadInternal *thread)
|
||||
|
|
|
@ -162,6 +162,8 @@ private:
|
|||
;
|
||||
|
||||
|
||||
virtual bool RecvLoadURIExternal(const IPC::URI& uri);
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
|
|
@ -82,6 +82,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(srcdir)/../../toolkit/components/places/src \
|
||||
-I$(srcdir)/../src/geolocation \
|
||||
-I$(topsrcdir)/chrome/src \
|
||||
-I$(topsrcdir)/uriloader/exthandler \
|
||||
$(NULL)
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
|
|
|
@ -81,6 +81,8 @@ parent:
|
|||
async VisitURI(URI uri, URI referrer, PRUint32 flags);
|
||||
async SetURITitle(URI uri, nsString title);
|
||||
|
||||
async LoadURIExternal(URI uri);
|
||||
|
||||
// PrefService messages
|
||||
sync GetPrefType(nsCString prefName) returns (PRInt32 retValue, nsresult rv);
|
||||
sync GetBoolPref(nsCString prefName) returns (PRBool retValue, nsresult rv);
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:icon="@drawable/icon">
|
||||
android:icon="@drawable/icon"
|
||||
android:debuggable="true">
|
||||
<activity android:name="App"
|
||||
android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
|
||||
|
|
|
@ -157,7 +157,7 @@ class GeckoAppShell
|
|||
sGeckoRunning = true;
|
||||
|
||||
// First argument is the .apk path
|
||||
String combinedArgs = apkPath;
|
||||
String combinedArgs = apkPath + " -omnijar " + apkPath;
|
||||
if (args != null)
|
||||
combinedArgs += " " + args;
|
||||
if (url != null)
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
|
||||
// PSM2 includes
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
|
@ -790,6 +791,7 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(PRUint32 aId, PRUint32 aValue)
|
|||
NS_ENSURE_TRUE((aValue == PR_TRUE || aValue == PR_FALSE), NS_ERROR_INVALID_ARG);
|
||||
mDocShell->SetAllowDNSPrefetch(!!aValue);
|
||||
}
|
||||
break;
|
||||
case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY:
|
||||
{
|
||||
NS_ENSURE_STATE(mDocShell);
|
||||
|
@ -1231,9 +1233,11 @@ NS_IMETHODIMP nsWebBrowser::Create()
|
|||
}
|
||||
mDocShellAsNav->SetSessionHistory(mInitInfo->sessionHistory);
|
||||
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
// Hook up global history. Do not fail if we can't - just warn.
|
||||
rv = EnableGlobalHistory(mShouldEnableHistory);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed");
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE);
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
# include <locale.h>
|
||||
# include <stdlib.h>
|
||||
# include "nsIPosixLocale.h"
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
# include "nsIGConfService.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -174,8 +177,28 @@ nsLocaleService::nsLocaleService(void)
|
|||
if ( resultLocale == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get system configuration
|
||||
char* lang = getenv("LANG");
|
||||
#if (MOZ_PLATFORM_MAEMO >= 6)
|
||||
nsCAutoString gconfLocaleString;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIGConfService> gconf =
|
||||
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gconf->GetString(NS_LITERAL_CSTRING("/meegotouch/i18n/language"),
|
||||
gconfLocaleString);
|
||||
if (NS_SUCCEEDED(rv) && !gconfLocaleString.IsEmpty()) {
|
||||
lang = static_cast<const char*>(gconfLocaleString.get());
|
||||
// For setlocale() doing the right thing we need to export
|
||||
// this as LANG to the environment
|
||||
setenv("LANG", lang, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( i = 0; i < LocaleListLength; i++ ) {
|
||||
nsresult result;
|
||||
// setlocale( , "") evaluates LC_* and LANG
|
||||
char* lc_temp = setlocale(posix_locale_category[i], "");
|
||||
CopyASCIItoUTF16(LocaleList[i], category);
|
||||
category_platform = category;
|
||||
|
@ -184,7 +207,6 @@ nsLocaleService::nsLocaleService(void)
|
|||
result = posixConverter->GetXPLocale(lc_temp, xpLocale);
|
||||
CopyASCIItoUTF16(lc_temp, platformLocale);
|
||||
} else {
|
||||
char* lang = getenv("LANG");
|
||||
if ( lang == nsnull ) {
|
||||
platformLocale.AssignLiteral("en_US");
|
||||
result = posixConverter->GetXPLocale("en-US", xpLocale);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "base/singleton.h"
|
||||
#include "base/waitable_event.h"
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
|
||||
#else
|
||||
|
@ -121,6 +122,8 @@ bool ChildProcessHost::Send(IPC::Message* msg) {
|
|||
void ChildProcessHost::Notify(NotificationType type) {
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
|
||||
if (!loop)
|
||||
loop = mozilla::ipc::ProcessChild::message_loop();
|
||||
if (!loop)
|
||||
loop = MessageLoop::current();
|
||||
loop->PostTask(
|
||||
|
|
|
@ -253,14 +253,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
|||
newEnvVars["LD_LIBRARY_PATH"] = path.get();
|
||||
#elif OS_MACOSX
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
#endif
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See ScopedXPCOMStartup::Initialize in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath())
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
newEnvVars["OMNIJAR_PATH"] = omnijarPath.get();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@ -296,6 +288,17 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
|||
|
||||
childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsCAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetNativePath(omnijarPath);
|
||||
childArgv.push_back("-omnijar");
|
||||
childArgv.push_back(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
childArgv.push_back(pidstring);
|
||||
childArgv.push_back(childProcessType);
|
||||
|
||||
|
@ -346,6 +349,18 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
|||
}
|
||||
|
||||
cmdLine.AppendLooseValue(std::wstring(mGroupId.get()));
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsAutoString omnijarPath;
|
||||
if (mozilla::OmnijarPath()) {
|
||||
mozilla::OmnijarPath()->GetPath(omnijarPath);
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-omnijar"));
|
||||
cmdLine.AppendLooseValue(omnijarPath.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
|
|
|
@ -1215,6 +1215,9 @@ bool
|
|||
XPCShellEnvironment::EvaluateString(const nsString& aString,
|
||||
nsString* aResult)
|
||||
{
|
||||
XPCShellEnvironment* env = Environment(mCx);
|
||||
XPCShellEnvironment::AutoContextPusher pusher(env);
|
||||
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
JS_ClearPendingException(mCx);
|
||||
|
|
|
@ -1036,4 +1036,7 @@ event.h
|
|||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
#endif
|
||||
#if MOZ_PLATFORM_MAEMO==6
|
||||
contentaction/contentaction.h
|
||||
#endif
|
||||
|
||||
|
|
|
@ -67,13 +67,12 @@ function run_test() {
|
|||
|
||||
do_check_true(scope2.XPCOMUtils == scope.XPCOMUtils);
|
||||
|
||||
// try on a new object using a file URL
|
||||
// try on a new object using the resolved URL
|
||||
var res = Components.classes["@mozilla.org/network/protocol;1?name=resource"]
|
||||
.getService(Components.interfaces.nsIResProtocolHandler);
|
||||
var resURI = res.newURI("resource://gre/modules/XPCOMUtils.jsm", null, null);
|
||||
dump("resURI: " + resURI + "\n");
|
||||
var filePath = res.resolveURI(resURI);
|
||||
do_check_eq(filePath.indexOf("file://"), 0);
|
||||
var scope3 = {};
|
||||
Components.utils.import(filePath, scope3);
|
||||
do_check_eq(typeof(scope3.XPCOMUtils), "object");
|
||||
|
|
|
@ -49,15 +49,32 @@
|
|||
#include "nsMimeTypes.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
class Callback
|
||||
{
|
||||
public:
|
||||
virtual bool Run() = 0;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
// Ensures any incoming IPDL msgs are queued during its lifetime, and flushes
|
||||
// the queue when it goes out of scope.
|
||||
class AutoEventEnqueuer
|
||||
{
|
||||
public:
|
||||
AutoEventEnqueuer(HttpChannelChild* channel) : mChannel(channel)
|
||||
{
|
||||
mChannel->BeginEventQueueing();
|
||||
}
|
||||
~AutoEventEnqueuer()
|
||||
{
|
||||
mChannel->FlushEventQueue();
|
||||
}
|
||||
private:
|
||||
HttpChannelChild *mChannel;
|
||||
};
|
||||
|
||||
// C++ file contents
|
||||
HttpChannelChild::HttpChannelChild()
|
||||
: mIsFromCache(PR_FALSE)
|
||||
|
@ -65,7 +82,7 @@ HttpChannelChild::HttpChannelChild()
|
|||
, mCacheExpirationTime(nsICache::NO_EXPIRATION_TIME)
|
||||
, mState(HCC_NEW)
|
||||
, mIPCOpen(false)
|
||||
, mShouldBuffer(true)
|
||||
, mQueuePhase(PHASE_UNQUEUED)
|
||||
{
|
||||
LOG(("Creating HttpChannelChild @%x\n", this));
|
||||
}
|
||||
|
@ -118,6 +135,67 @@ HttpChannelChild::ReleaseIPDLReference()
|
|||
Release();
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::FlushEventQueue()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mQueuePhase != PHASE_UNQUEUED,
|
||||
"Queue flushing should not occur if PHASE_UNQUEUED");
|
||||
|
||||
// Queue already being flushed.
|
||||
if (mQueuePhase != PHASE_QUEUEING)
|
||||
return;
|
||||
|
||||
if (mEventQueue.Length() > 0) {
|
||||
// It is possible for new callbacks to be enqueued as we are
|
||||
// flushing the queue, so the queue must not be cleared until
|
||||
// all callbacks have run.
|
||||
mQueuePhase = PHASE_FLUSHING;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> kungFuDeathGrip(this);
|
||||
for (PRUint32 i = 0; i < mEventQueue.Length(); i++) {
|
||||
mEventQueue[i]->Run();
|
||||
}
|
||||
mEventQueue.Clear();
|
||||
}
|
||||
|
||||
mQueuePhase = PHASE_UNQUEUED;
|
||||
}
|
||||
|
||||
class StartRequestEvent : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
StartRequestEvent(HttpChannelChild* child,
|
||||
const nsHttpResponseHead& responseHead,
|
||||
const PRBool& useResponseHead,
|
||||
const PRBool& isFromCache,
|
||||
const PRBool& cacheEntryAvailable,
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset)
|
||||
: mChild(child)
|
||||
, mResponseHead(responseHead)
|
||||
, mUseResponseHead(useResponseHead)
|
||||
, mIsFromCache(isFromCache)
|
||||
, mCacheEntryAvailable(cacheEntryAvailable)
|
||||
, mCacheExpirationTime(cacheExpirationTime)
|
||||
, mCachedCharset(cachedCharset)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->OnStartRequest(mResponseHead, mUseResponseHead, mIsFromCache,
|
||||
mCacheEntryAvailable, mCacheExpirationTime,
|
||||
mCachedCharset);
|
||||
}
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsHttpResponseHead mResponseHead;
|
||||
PRBool mUseResponseHead;
|
||||
PRBool mIsFromCache;
|
||||
PRBool mCacheEntryAvailable;
|
||||
PRUint32 mCacheExpirationTime;
|
||||
nsCString mCachedCharset;
|
||||
};
|
||||
|
||||
bool
|
||||
HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
|
||||
const PRBool& useResponseHead,
|
||||
|
@ -125,6 +203,25 @@ HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
|
|||
const PRBool& cacheEntryAvailable,
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset)
|
||||
{
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new StartRequestEvent(this, responseHead, useResponseHead,
|
||||
isFromCache, cacheEntryAvailable,
|
||||
cacheExpirationTime, cachedCharset));
|
||||
} else {
|
||||
OnStartRequest(responseHead, useResponseHead, isFromCache,
|
||||
cacheEntryAvailable, cacheExpirationTime, cachedCharset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
|
||||
const PRBool& useResponseHead,
|
||||
const PRBool& isFromCache,
|
||||
const PRBool& cacheEntryAvailable,
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset)
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this));
|
||||
|
||||
|
@ -140,31 +237,21 @@ HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
|
|||
mCacheExpirationTime = cacheExpirationTime;
|
||||
mCachedCharset = cachedCharset;
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (mResponseHead)
|
||||
SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
|
||||
} else {
|
||||
// TODO: Cancel request: (bug 536317)
|
||||
// - Send Cancel msg to parent
|
||||
// - drop any in flight OnDataAvail msgs we receive
|
||||
// - make sure we do call OnStopRequest eventually
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mResponseHead)
|
||||
SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
|
||||
|
||||
bool ret = true;
|
||||
nsCOMPtr<nsIHttpChannel> kungFuDeathGrip(this);
|
||||
for (PRUint32 i = 0; i < mBufferedCallbacks.Length(); i++) {
|
||||
ret = mBufferedCallbacks[i]->Run();
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
mBufferedCallbacks.Clear();
|
||||
mShouldBuffer = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
class DataAvailableEvent : public Callback
|
||||
class DataAvailableEvent : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
DataAvailableEvent(HttpChannelChild* child,
|
||||
|
@ -176,11 +263,7 @@ class DataAvailableEvent : public Callback
|
|||
, mOffset(offset)
|
||||
, mCount(count) {}
|
||||
|
||||
bool Run()
|
||||
{
|
||||
return mChild->OnDataAvailable(mData, mOffset, mCount);
|
||||
}
|
||||
|
||||
void Run() { mChild->OnDataAvailable(mData, mOffset, mCount); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsCString mData;
|
||||
|
@ -193,11 +276,15 @@ HttpChannelChild::RecvOnDataAvailable(const nsCString& data,
|
|||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
{
|
||||
DataAvailableEvent* event = new DataAvailableEvent(this, data, offset, count);
|
||||
return BufferOrDispatch(event);
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new DataAvailableEvent(this, data, offset, count));
|
||||
} else {
|
||||
OnDataAvailable(data, offset, count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
HttpChannelChild::OnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count)
|
||||
|
@ -218,18 +305,20 @@ HttpChannelChild::OnDataAvailable(const nsCString& data,
|
|||
NS_ASSIGNMENT_DEPEND);
|
||||
if (NS_FAILED(rv)) {
|
||||
// TODO: what to do here? Cancel request? Very unlikely to fail.
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
rv = mListener->OnDataAvailable(this, mListenerContext,
|
||||
stringStream, offset, count);
|
||||
stringStream->Close();
|
||||
if (NS_FAILED(rv)) {
|
||||
// TODO: Cancel request: see OnStartRequest. Bug 536317
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class StopRequestEvent : public Callback
|
||||
class StopRequestEvent : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
StopRequestEvent(HttpChannelChild* child,
|
||||
|
@ -237,11 +326,7 @@ class StopRequestEvent : public Callback
|
|||
: mChild(child)
|
||||
, mStatusCode(statusCode) {}
|
||||
|
||||
bool Run()
|
||||
{
|
||||
return mChild->OnStopRequest(mStatusCode);
|
||||
}
|
||||
|
||||
void Run() { mChild->OnStopRequest(mStatusCode); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsresult mStatusCode;
|
||||
|
@ -250,11 +335,15 @@ class StopRequestEvent : public Callback
|
|||
bool
|
||||
HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
|
||||
{
|
||||
StopRequestEvent* event = new StopRequestEvent(this, statusCode);
|
||||
return BufferOrDispatch(event);
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new StopRequestEvent(this, statusCode));
|
||||
} else {
|
||||
OnStopRequest(statusCode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
HttpChannelChild::OnStopRequest(const nsresult& statusCode)
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvOnStopRequest [this=%x status=%u]\n",
|
||||
|
@ -264,21 +353,26 @@ HttpChannelChild::OnStopRequest(const nsresult& statusCode)
|
|||
|
||||
mIsPending = PR_FALSE;
|
||||
mStatus = statusCode;
|
||||
mListener->OnStopRequest(this, mListenerContext, statusCode);
|
||||
mListener = 0;
|
||||
mListenerContext = 0;
|
||||
mCacheEntryAvailable = PR_FALSE;
|
||||
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, statusCode);
|
||||
{ // We must flush the queue before we Send__delete__,
|
||||
// so make sure this goes out of scope before then.
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
mListener->OnStopRequest(this, mListenerContext, statusCode);
|
||||
mListener = 0;
|
||||
mListenerContext = 0;
|
||||
mCacheEntryAvailable = PR_FALSE;
|
||||
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, statusCode);
|
||||
}
|
||||
|
||||
// This calls NeckoChild::DeallocPHttpChannel(), which deletes |this| if IPDL
|
||||
// holds the last reference. Don't rely on |this| existing after here.
|
||||
PHttpChannelChild::Send__delete__(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
class ProgressEvent : public Callback
|
||||
class ProgressEvent : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
ProgressEvent(HttpChannelChild* child,
|
||||
|
@ -288,11 +382,7 @@ class ProgressEvent : public Callback
|
|||
, mProgress(progress)
|
||||
, mProgressMax(progressMax) {}
|
||||
|
||||
bool Run()
|
||||
{
|
||||
return mChild->OnProgress(mProgress, mProgressMax);
|
||||
}
|
||||
|
||||
void Run() { mChild->OnProgress(mProgress, mProgressMax); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
PRUint64 mProgress, mProgressMax;
|
||||
|
@ -302,11 +392,15 @@ bool
|
|||
HttpChannelChild::RecvOnProgress(const PRUint64& progress,
|
||||
const PRUint64& progressMax)
|
||||
{
|
||||
ProgressEvent* event = new ProgressEvent(this, progress, progressMax);
|
||||
return BufferOrDispatch(event);
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new ProgressEvent(this, progress, progressMax));
|
||||
} else {
|
||||
OnProgress(progress, progressMax);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
HttpChannelChild::OnProgress(const PRUint64& progress,
|
||||
const PRUint64& progressMax)
|
||||
{
|
||||
|
@ -317,6 +411,8 @@ HttpChannelChild::OnProgress(const PRUint64& progress,
|
|||
if (!mProgressSink)
|
||||
GetCallback(mProgressSink);
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
// block socket status event after Cancel or OnStopRequest has been called.
|
||||
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
|
||||
!(mLoadFlags & LOAD_BACKGROUND))
|
||||
|
@ -326,11 +422,9 @@ HttpChannelChild::OnProgress(const PRUint64& progress,
|
|||
mProgressSink->OnProgress(this, nsnull, progress, progressMax);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class StatusEvent : public Callback
|
||||
class StatusEvent : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
StatusEvent(HttpChannelChild* child,
|
||||
|
@ -340,11 +434,7 @@ class StatusEvent : public Callback
|
|||
, mStatus(status)
|
||||
, mStatusArg(statusArg) {}
|
||||
|
||||
bool Run()
|
||||
{
|
||||
return mChild->OnStatus(mStatus, mStatusArg);
|
||||
}
|
||||
|
||||
void Run() { mChild->OnStatus(mStatus, mStatusArg); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
nsresult mStatus;
|
||||
|
@ -355,11 +445,15 @@ bool
|
|||
HttpChannelChild::RecvOnStatus(const nsresult& status,
|
||||
const nsString& statusArg)
|
||||
{
|
||||
StatusEvent* event = new StatusEvent(this, status, statusArg);
|
||||
return BufferOrDispatch(event);
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new StatusEvent(this, status, statusArg));
|
||||
} else {
|
||||
OnStatus(status, statusArg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
HttpChannelChild::OnStatus(const nsresult& status,
|
||||
const nsString& statusArg)
|
||||
{
|
||||
|
@ -369,27 +463,14 @@ HttpChannelChild::OnStatus(const nsresult& status,
|
|||
if (!mProgressSink)
|
||||
GetCallback(mProgressSink);
|
||||
|
||||
AutoEventEnqueuer ensureSerialDispatch(this);
|
||||
|
||||
// block socket status event after Cancel or OnStopRequest has been called.
|
||||
if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
|
||||
!(mLoadFlags & LOAD_BACKGROUND))
|
||||
{
|
||||
mProgressSink->OnStatus(this, nsnull, status, statusArg.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpChannelChild::BufferOrDispatch(Callback* callback)
|
||||
{
|
||||
if (mShouldBuffer) {
|
||||
mBufferedCallbacks.AppendElement(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = callback->Run();
|
||||
delete callback;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -58,14 +58,12 @@
|
|||
#include "nsIResumableChannel.h"
|
||||
#include "nsIProxiedChannel.h"
|
||||
#include "nsITraceableChannel.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
class nsIRunnable;
|
||||
class Callback;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class ChildChannelEvent;
|
||||
|
||||
// TODO: replace with IPDL states: bug 536319
|
||||
enum HttpChannelChildState {
|
||||
HCC_NEW,
|
||||
|
@ -148,29 +146,70 @@ private:
|
|||
enum HttpChannelChildState mState;
|
||||
bool mIPCOpen;
|
||||
|
||||
// Workaround for Necko re-entrancy dangers. We buffer all messages
|
||||
// received until OnStartRequest completes.
|
||||
nsTArray<nsAutoPtr<Callback> > mBufferedCallbacks;
|
||||
bool mShouldBuffer;
|
||||
// Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a
|
||||
// queue if still dispatching previous one(s) to listeners/observers.
|
||||
// Otherwise synchronous XMLHttpRequests and/or other code that spins the
|
||||
// event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for
|
||||
// instance) to be called before mListener->OnStartRequest has completed.
|
||||
void BeginEventQueueing();
|
||||
void FlushEventQueue();
|
||||
void EnqueueEvent(ChildChannelEvent* callback);
|
||||
bool ShouldEnqueue();
|
||||
|
||||
bool BufferOrDispatch(Callback* callback);
|
||||
nsTArray<nsAutoPtr<ChildChannelEvent> > mEventQueue;
|
||||
enum {
|
||||
PHASE_UNQUEUED,
|
||||
PHASE_QUEUEING,
|
||||
PHASE_FLUSHING
|
||||
} mQueuePhase;
|
||||
|
||||
// This class does not actually implement the stream listener interface.
|
||||
// These functions actually perform the actions associated with the
|
||||
// corresponding IPDL receivers above.
|
||||
bool OnDataAvailable(const nsCString& data,
|
||||
void OnStartRequest(const nsHttpResponseHead& responseHead,
|
||||
const PRBool& useResponseHead,
|
||||
const PRBool& isFromCache,
|
||||
const PRBool& cacheEntryAvailable,
|
||||
const PRUint32& cacheExpirationTime,
|
||||
const nsCString& cachedCharset);
|
||||
void OnDataAvailable(const nsCString& data,
|
||||
const PRUint32& offset,
|
||||
const PRUint32& count);
|
||||
bool OnStopRequest(const nsresult& statusCode);
|
||||
bool OnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
bool OnStatus(const nsresult& status, const nsString& statusArg);
|
||||
void OnStopRequest(const nsresult& statusCode);
|
||||
void OnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
void OnStatus(const nsresult& status, const nsString& statusArg);
|
||||
|
||||
friend class AutoEventEnqueuer;
|
||||
friend class StartRequestEvent;
|
||||
friend class StopRequestEvent;
|
||||
friend class DataAvailableEvent;
|
||||
friend class ProgressEvent;
|
||||
friend class StatusEvent;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inline functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void
|
||||
HttpChannelChild::BeginEventQueueing()
|
||||
{
|
||||
if (mQueuePhase == PHASE_FLUSHING)
|
||||
return;
|
||||
// Store incoming IPDL messages for later.
|
||||
mQueuePhase = PHASE_QUEUEING;
|
||||
}
|
||||
|
||||
inline bool
|
||||
HttpChannelChild::ShouldEnqueue()
|
||||
{
|
||||
return mQueuePhase != PHASE_UNQUEUED;
|
||||
}
|
||||
|
||||
inline void
|
||||
HttpChannelChild::EnqueueEvent(ChildChannelEvent* callback)
|
||||
{
|
||||
mEventQueue.AppendElement(callback);
|
||||
}
|
||||
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -3249,6 +3249,9 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||
|
||||
nsresult rv;
|
||||
|
||||
if (mCanceled)
|
||||
return mStatus;
|
||||
|
||||
rv = NS_CheckPortSafety(mURI);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
|
|
@ -95,25 +95,20 @@ nsResURL::EnsureFile()
|
|||
|
||||
nsCAutoString spec;
|
||||
rv = gResHandler->ResolveURI(this, spec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#if defined(MOZ_CHROME_FILE_FORMAT_JAR) || defined(MOZ_OMNIJAR)
|
||||
nsCAutoString host;
|
||||
rv = GetHost(host);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
// Deal with the fact resource://gre-resouces/ urls do not resolve to files
|
||||
if (host.Equals(kGRE_RESOURCES))
|
||||
|
||||
nsCAutoString scheme;
|
||||
rv = net_ExtractURLScheme(spec, nsnull, nsnull, &scheme);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Bug 585869:
|
||||
// In most cases, the scheme is jar if it's not file.
|
||||
// Regardless, net_GetFileFromURLSpec should be avoided
|
||||
// when the scheme isn't file.
|
||||
if (!scheme.Equals(NS_LITERAL_CSTRING("file")))
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
#endif
|
||||
#ifdef MOZ_OMNIJAR
|
||||
if (mozilla::OmnijarPath()) {
|
||||
if (host.Equals(kGRE))
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
if (host.IsEmpty())
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = net_GetFileFromURLSpec(spec, getter_AddRefs(mFile));
|
||||
#ifdef DEBUG_bsmedberg
|
||||
|
|
|
@ -10,26 +10,81 @@ var last = 0, max = 0;
|
|||
const STATUS_RECEIVING_FROM = 0x804b0006;
|
||||
const LOOPS = 50000;
|
||||
|
||||
const TYPE_ONSTATUS = 1;
|
||||
const TYPE_ONPROGRESS = 2;
|
||||
const TYPE_ONSTARTREQUEST = 3;
|
||||
const TYPE_ONDATAAVAILABLE = 4;
|
||||
const TYPE_ONSTOPREQUEST = 5;
|
||||
|
||||
var progressCallback = {
|
||||
_listener: null,
|
||||
_got_onstartrequest: false,
|
||||
_got_onstatus_after_onstartrequest: false,
|
||||
_last_callback_handled: null,
|
||||
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIProgressEventSink))
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIProgressEventSink) ||
|
||||
iid.equals(Ci.nsIStreamListener) ||
|
||||
iid.equals(Ci.nsIRequestObserver))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
getInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsIProgressEventSink))
|
||||
if (iid.equals(Ci.nsIProgressEventSink) ||
|
||||
iid.equals(Ci.nsIStreamListener) ||
|
||||
iid.equals(Ci.nsIRequestObserver))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onStartRequest: function(request, context) {
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONSTATUS);
|
||||
this._got_onstartrequest = true;
|
||||
this._last_callback_handled = TYPE_ONSTARTREQUEST;
|
||||
|
||||
this._listener = new ChannelListener(checkRequest, request);
|
||||
this._listener.onStartRequest(request, context);
|
||||
},
|
||||
|
||||
onDataAvailable: function(request, context, data, offset, count) {
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONPROGRESS);
|
||||
this._last_callback_handled = TYPE_ONDATAAVAILABLE;
|
||||
|
||||
this._listener.onDataAvailable(request, context, data, offset, count);
|
||||
},
|
||||
|
||||
onStopRequest: function(request, context, status) {
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONDATAAVAILABLE);
|
||||
do_check_true(this._got_onstatus_after_onstartrequest);
|
||||
this._last_callback_handled = TYPE_ONSTOPREQUEST;
|
||||
|
||||
this._listener.onStopRequest(request, context, status);
|
||||
delete this._listener;
|
||||
},
|
||||
|
||||
onProgress: function (request, context, progress, progressMax) {
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONSTATUS);
|
||||
this._last_callback_handled = TYPE_ONPROGRESS;
|
||||
|
||||
do_check_eq(mStatus, STATUS_RECEIVING_FROM);
|
||||
last = progress;
|
||||
max = progressMax;
|
||||
},
|
||||
|
||||
onStatus: function (request, context, status, statusArg) {
|
||||
if (!this._got_onstartrequest) {
|
||||
// Ensure that all messages before onStartRequest are onStatus
|
||||
if (this._last_callback_handled)
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONSTATUS);
|
||||
} else if (this._last_callback_handled == TYPE_ONSTARTREQUEST) {
|
||||
this._got_onstatus_after_onstartrequest = true;
|
||||
} else {
|
||||
do_check_eq(this._last_callback_handled, TYPE_ONDATAAVAILABLE);
|
||||
}
|
||||
this._last_callback_handled = TYPE_ONSTATUS;
|
||||
|
||||
do_check_eq(statusArg, "localhost");
|
||||
mStatus = status;
|
||||
},
|
||||
|
@ -41,7 +96,7 @@ function run_test() {
|
|||
httpserver.registerPathHandler(testpath, serverHandler);
|
||||
httpserver.start(4444);
|
||||
var channel = setupChannel(testpath);
|
||||
channel.asyncOpen(new ChannelListener(checkRequest, channel), null);
|
||||
channel.asyncOpen(progressCallback, null);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,27 +5,44 @@ var httpserver = new nsHttpServer();
|
|||
var testpath = "/simple";
|
||||
var httpbody = "<?xml version='1.0' ?><root>0123456789</root>";
|
||||
|
||||
function createXHR(async)
|
||||
{
|
||||
var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", "http://localhost:4444" + testpath, async);
|
||||
return xhr;
|
||||
}
|
||||
|
||||
function checkResults(xhr)
|
||||
{
|
||||
if (xhr.readyState != 4)
|
||||
return false;
|
||||
|
||||
do_check_eq(xhr.status, 200);
|
||||
do_check_eq(xhr.responseText, httpbody);
|
||||
|
||||
var root_node = xhr.responseXML.getElementsByTagName('root').item(0);
|
||||
do_check_eq(root_node.firstChild.data, "0123456789");
|
||||
return true;
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
httpserver.registerPathHandler(testpath, serverHandler);
|
||||
httpserver.start(4444);
|
||||
|
||||
var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", "http://localhost:4444" + testpath, true);
|
||||
xhr.onreadystatechange = function(event) {
|
||||
if (xhr.readyState == 4) {
|
||||
do_check_eq(xhr.status, 200);
|
||||
do_check_eq(xhr.responseText, httpbody);
|
||||
|
||||
var root_node = xhr.responseXML.getElementsByTagName('root').item(0);
|
||||
do_check_eq(root_node.firstChild.data, "0123456789");
|
||||
// Test sync XHR sending
|
||||
var sync = createXHR(false);
|
||||
sync.send(null);
|
||||
checkResults(sync);
|
||||
|
||||
// Test async XHR sending
|
||||
let async = createXHR(true);
|
||||
async.onreadystatechange = function(event) {
|
||||
if (checkResults(async))
|
||||
httpserver.stop(do_test_finished);
|
||||
}
|
||||
}
|
||||
xhr.send(null);
|
||||
|
||||
};
|
||||
async.send(null);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
function run_test() {
|
||||
_dump('FIXME/bug 564351: temporarily disabled for perma-crash on e10s tinderbox');
|
||||
//run_test_in_child("../unit/test_xmlhttprequest.js");
|
||||
run_test_in_child("../unit/test_xmlhttprequest.js");
|
||||
}
|
||||
|
|
|
@ -39,13 +39,14 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILocalFile;
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* The PlacesImportExport interface provides methods for importing
|
||||
* and exporting Places data.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(21c00314-fa63-11db-8314-0800200c9a66)]
|
||||
[scriptable, uuid(47a4a09e-c708-4e68-b2f2-664d982ce026)]
|
||||
interface nsIPlacesImportExportService: nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -64,6 +65,11 @@ interface nsIPlacesImportExportService: nsISupports
|
|||
*/
|
||||
void importHTMLFromFile(in nsILocalFile aFile, in boolean aIsInitialImport);
|
||||
|
||||
/**
|
||||
* Same thing as importHTMLFromFile, but takes a URI instead
|
||||
*/
|
||||
void importHTMLFromURI(in nsIURI aURI, in boolean aIsInitialImport);
|
||||
|
||||
/**
|
||||
* Loads the given bookmarks.html file and puts it in the given folder
|
||||
*
|
||||
|
|
|
@ -2181,6 +2181,33 @@ nsPlacesImportExportService::ImportHTMLFromFile(nsILocalFile* aFile,
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlacesImportExportService::ImportHTMLFromURI(nsIURI* aURI,
|
||||
PRBool aIsInitialImport)
|
||||
{
|
||||
NotifyImportObservers(RESTORE_BEGIN_NSIOBSERVER_TOPIC, -1, aIsInitialImport);
|
||||
|
||||
// this version is exposed on the interface and disallows changing of roots
|
||||
nsresult rv = ImportHTMLFromURIInternal(aURI,
|
||||
PR_FALSE,
|
||||
0,
|
||||
aIsInitialImport);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NotifyImportObservers(RESTORE_FAILED_NSIOBSERVER_TOPIC,
|
||||
-1,
|
||||
aIsInitialImport);
|
||||
}
|
||||
else {
|
||||
NotifyImportObservers(RESTORE_SUCCESS_NSIOBSERVER_TOPIC,
|
||||
-1,
|
||||
aIsInitialImport);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlacesImportExportService::ImportHTMLFromFileToFolder(nsILocalFile* aFile,
|
||||
PRInt64 aFolderId,
|
||||
|
@ -2217,8 +2244,7 @@ nsPlacesImportExportService::ImportHTMLFromFileInternal(nsILocalFile* aFile,
|
|||
PRInt64 aFolder,
|
||||
PRBool aIsImportDefaults)
|
||||
{
|
||||
nsresult rv = EnsureServiceState();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(aFile);
|
||||
NS_ENSURE_STATE(file);
|
||||
|
@ -2237,6 +2263,24 @@ nsPlacesImportExportService::ImportHTMLFromFileInternal(nsILocalFile* aFile,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIOService> ioservice = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIURI> fileURI;
|
||||
rv = ioservice->NewFileURI(file, getter_AddRefs(fileURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return ImportHTMLFromURIInternal(fileURI, aAllowRootChanges, aFolder, aIsImportDefaults);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlacesImportExportService::ImportHTMLFromURIInternal(nsIURI* aURI,
|
||||
PRBool aAllowRootChanges,
|
||||
PRInt64 aFolder,
|
||||
PRBool aIsImportDefaults)
|
||||
{
|
||||
nsresult rv = EnsureServiceState();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID);
|
||||
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -2250,16 +2294,13 @@ nsPlacesImportExportService::ImportHTMLFromFileInternal(nsILocalFile* aFile,
|
|||
// will confuse the parser.
|
||||
nsCOMPtr<nsIIOService> ioservice = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIURI> fileURI;
|
||||
rv = ioservice->NewFileURI(file, getter_AddRefs(fileURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = ioservice->NewChannelFromURI(fileURI, getter_AddRefs(mImportChannel));
|
||||
rv = ioservice->NewChannelFromURI(aURI, getter_AddRefs(mImportChannel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mImportChannel->SetContentType(NS_LITERAL_CSTRING("text/html"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Init parser.
|
||||
rv = parser->Parse(fileURI, nsnull);
|
||||
rv = parser->Parse(aURI, nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Run the import in batch mode, so it will be executed in a transaction
|
||||
|
|
|
@ -50,6 +50,8 @@ class nsPlacesImportExportService : public nsIPlacesImportExportService,
|
|||
|
||||
nsresult ImportHTMLFromFileInternal(nsILocalFile* aFile, PRBool aAllowRootChanges,
|
||||
PRInt64 aFolder, PRBool aIsImportDefaults);
|
||||
nsresult ImportHTMLFromURIInternal(nsIURI* aURI, PRBool aAllowRootChanges,
|
||||
PRInt64 aFolder, PRBool aIsImportDefaults);
|
||||
nsresult WriteContainer(nsINavHistoryResultNode* aFolder, const nsACString& aIndent, nsIOutputStream* aOutput);
|
||||
nsresult WriteContainerHeader(nsINavHistoryResultNode* aFolder, const nsACString& aIndent, nsIOutputStream* aOutput);
|
||||
nsresult WriteTitle(nsINavHistoryResultNode* aItem, nsIOutputStream* aOutput);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
|
@ -12,15 +13,26 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Nokia.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nokia Corporation.
|
||||
* The Initial Developer of the Original Code is Nokia Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MOZMEEGOAPPSERVICE_H
|
||||
|
|
|
@ -1114,10 +1114,6 @@ ScopedXPCOMStartup::~ScopedXPCOMStartup()
|
|||
|
||||
NS_ShutdownXPCOM(mServiceManager);
|
||||
mServiceManager = nsnull;
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
mozilla::SetOmnijar(nsnull);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,16 +1171,6 @@ ScopedXPCOMStartup::Initialize()
|
|||
NS_ASSERTION(gDirServiceProvider, "Should not get here!");
|
||||
|
||||
nsresult rv;
|
||||
#ifdef MOZ_OMNIJAR
|
||||
nsCOMPtr<nsILocalFile> lf;
|
||||
char *omnijarPath = getenv("OMNIJAR_PATH");
|
||||
if (omnijarPath)
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(omnijarPath), PR_TRUE, getter_AddRefs(lf));
|
||||
else
|
||||
rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mozilla::SetOmnijar(lf);
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_ENABLE_LIBXUL
|
||||
#ifndef _BUILD_STATIC_BIN
|
||||
|
@ -3777,16 +3763,6 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
#if defined(OS_WIN)
|
||||
CommandLine::Init(aArgc, aArgv);
|
||||
#else
|
||||
#ifdef MOZ_OMNIJAR
|
||||
nsCOMPtr<nsILocalFile> lf;
|
||||
char *omnijarPath = getenv("OMNIJAR_PATH");
|
||||
if (omnijarPath)
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(omnijarPath), PR_TRUE, getter_AddRefs(lf));
|
||||
else
|
||||
rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mozilla::SetOmnijar(lf);
|
||||
#endif
|
||||
|
||||
// these leak on error, but that's OK: we'll just exit()
|
||||
char** canonArgs = new char*[aArgc];
|
||||
|
@ -3818,6 +3794,25 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
delete[] canonArgs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
const char *omnijarPath = nsnull;
|
||||
ArgResult ar = CheckArg("omnijar", PR_FALSE, &omnijarPath);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -omnijar requires an omnijar path\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!omnijarPath)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsILocalFile> omnijar;
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(omnijarPath), PR_TRUE,
|
||||
getter_AddRefs(omnijar));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mozilla::SetOmnijar(omnijar);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ EXTRA_COMPONENTS = \
|
|||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
SRCS_IN_OBJDIR = 1
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifneq (,$(filter qt gtk2, $(MOZ_WIDGET_TOOLKIT)))
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "nsStringEnumerator.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMIMEInfoAndroid, nsIMIMEInfo)
|
||||
NS_IMPL_ISUPPORTS2(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
|
||||
|
||||
nsMIMEInfoAndroid::~nsMIMEInfoAndroid()
|
||||
{
|
||||
|
@ -230,9 +230,7 @@ nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction)
|
|||
NS_IMETHODIMP
|
||||
nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(PRBool* aAlwaysAsk)
|
||||
{
|
||||
// the chooser dialog currently causes a crash on Android, avoid this by returning false here
|
||||
// but be sure to return mAlwaysAsk when that gets fixed (bug 584896)
|
||||
*aAlwaysAsk = PR_FALSE;
|
||||
*aAlwaysAsk = mAlwaysAsk;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,15 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
#define FORCE_PR_LOG
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#endif
|
||||
|
||||
#include "nsExternalHelperAppService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -861,6 +870,13 @@ nsExternalHelperAppService::LoadURI(nsIURI *aURI,
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
mozilla::dom::ContentChild::GetSingleton()->SendLoadURIExternal(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCAutoString spec;
|
||||
aURI->GetSpec(spec);
|
||||
|
||||
|
|
|
@ -2082,7 +2082,9 @@ nsWindow::createQWidget(MozQWidget *parent, nsWidgetInitData *aInitData)
|
|||
if (mIsTopLevel) {
|
||||
QGraphicsView* newView = nsnull;
|
||||
#ifdef MOZ_ENABLE_MEEGOTOUCH
|
||||
newView = new MozMGraphicsView(widget);
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
newView = new MozMGraphicsView(widget);
|
||||
} else
|
||||
#else
|
||||
newView = new MozQGraphicsView(widget);
|
||||
#endif
|
||||
|
|
|
@ -393,8 +393,10 @@ RealBreak()
|
|||
raise(SIGTRAP);
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
|
||||
asm("int $3");
|
||||
#elif defined(__arm__)
|
||||
asm("BKPT #0");
|
||||
#else
|
||||
// don't know how to break on this platform
|
||||
#warning don't know how to break on this platform
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -493,8 +495,10 @@ Break(const char *aMsg)
|
|||
RealBreak();
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
|
||||
RealBreak();
|
||||
#elif defined(__arm__)
|
||||
RealBreak();
|
||||
#else
|
||||
// don't know how to break on this platform
|
||||
#warning don't know how to break on this platform
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -45,15 +45,43 @@
|
|||
static nsILocalFile* sOmnijarPath = nsnull;
|
||||
static nsZipArchive* sOmnijarReader = nsnull;
|
||||
|
||||
static void
|
||||
SetupReader()
|
||||
{
|
||||
if (!sOmnijarPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsZipArchive* zipReader = new nsZipArchive();
|
||||
if (!zipReader) {
|
||||
NS_IF_RELEASE(sOmnijarPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(zipReader->OpenArchive(sOmnijarPath))) {
|
||||
delete zipReader;
|
||||
NS_IF_RELEASE(sOmnijarPath);
|
||||
return;
|
||||
}
|
||||
|
||||
sOmnijarReader = zipReader;
|
||||
}
|
||||
|
||||
nsILocalFile*
|
||||
mozilla::OmnijarPath()
|
||||
{
|
||||
if (!sOmnijarReader)
|
||||
SetupReader();
|
||||
|
||||
return sOmnijarPath;
|
||||
}
|
||||
|
||||
nsZipArchive*
|
||||
mozilla::OmnijarReader()
|
||||
{
|
||||
if (!sOmnijarReader)
|
||||
SetupReader();
|
||||
|
||||
return sOmnijarReader;
|
||||
}
|
||||
|
||||
|
@ -67,22 +95,7 @@ mozilla::SetOmnijar(nsILocalFile* aPath)
|
|||
sOmnijarReader = nsnull;
|
||||
}
|
||||
|
||||
if (!aPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsZipArchive* zipReader = new nsZipArchive();
|
||||
if (!zipReader) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_FAILED(zipReader->OpenArchive(aPath))) {
|
||||
delete zipReader;
|
||||
return;
|
||||
}
|
||||
|
||||
sOmnijarReader = zipReader;
|
||||
sOmnijarPath = aPath;
|
||||
NS_ADDREF(sOmnijarPath);
|
||||
NS_IF_ADDREF(sOmnijarPath);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ extern nsresult nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **)
|
|||
#include <locale.h>
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
#include "mozilla/Omnijar.h"
|
||||
|
||||
#include "nsChromeRegistry.h"
|
||||
#include "nsChromeProtocolHandler.h"
|
||||
|
@ -419,6 +420,7 @@ NS_InitXPCOM2(nsIServiceManager* *result,
|
|||
|
||||
NS_StartupNativeCharsetUtils();
|
||||
#endif
|
||||
|
||||
NS_TIME_FUNCTION_MARK("Next: startup local file");
|
||||
|
||||
NS_StartupLocalFile();
|
||||
|
@ -457,6 +459,26 @@ NS_InitXPCOM2(nsIServiceManager* *result,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
NS_TIME_FUNCTION_MARK("Next: Omnijar init");
|
||||
|
||||
if (!mozilla::OmnijarPath()) {
|
||||
nsCOMPtr<nsILocalFile> omnijar;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
||||
rv = NS_ERROR_FAILURE;
|
||||
nsDirectoryService::gService->Get(NS_GRE_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(file));
|
||||
if (file)
|
||||
rv = file->Append(NS_LITERAL_STRING("omni.jar"));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
omnijar = do_QueryInterface(file);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mozilla::SetOmnijar(omnijar);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
|
||||
NS_TIME_FUNCTION_MARK("Next: IPC command line init");
|
||||
|
@ -734,6 +756,10 @@ ShutdownXPCOM(nsIServiceManager* servMgr)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMNIJAR
|
||||
mozilla::SetOmnijar(nsnull);
|
||||
#endif
|
||||
|
||||
NS_LogTerm();
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -526,6 +526,9 @@ GetExtension(nsILocalFile* file)
|
|||
void
|
||||
nsComponentManagerImpl::RegisterOmnijar(const char* aPath, bool aChromeOnly)
|
||||
{
|
||||
if (!mozilla::OmnijarPath())
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIInputStream> is = mManifestLoader->LoadEntry(aPath);
|
||||
|
||||
PRUint32 flen;
|
||||
|
|
Загрузка…
Ссылка в новой задаче