Closed Bug 101995 Opened 23 years ago Closed 9 years ago

Need a generic way to guess at charset (layout depends on cache/etc)

Categories

(Core :: Internationalization, defect)

defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: alecf, Assigned: smontagu)

References

Details

Attachments

(2 files, 3 obsolete files)

Right now in http://lxr.mozilla.org/seamonkey/source/content/html/document/src/nsHTMLDocument.cpp#425 We use a whole bunch of methods to guess at the character set: - default/fallback of ISO-8850-1 - http header - user default - requested by the document - user forced - cache - bookmarks (this also brings in rdf) - parent frame - autodetect The problem is that some of these (http header, cache, bookmarks) bring in modules that are totally irrelevant, and that embeddors may not want.. we need a mechanism so that a component may register as a "charset guesser" or something.. My initial plan is to have a category that each component will register themselves in, and in nsHTMLDocument, we'll go through each member of the category until we find a match.
reassigning to me, I just wanted to get the default owner.. putting the original author of some of this, jbetak, in as well.
Assignee: yokoyama → alecf
Priority: -- → P2
Target Milestone: --- → mozilla0.9.5
Adding this to the dependency tracker, because if we fix this, we can eliminate the following dependencies in content: - necko - nkcache - bookmarks and possibly more (we won't know until we try :)) *** This bug has been marked as a duplicate of 100107 ***
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → DUPLICATE
cc'ing ftang and shanjian
argh, reopening.. I did NOT mean to mark this a dupe
Status: RESOLVED → REOPENED
Depends on: 100107
Resolution: DUPLICATE → ---
There are a few issues that I've thought about since posting this: - How often is this routine called, i.e. how performant should this be? I'm thinking that this affects document loading and that we should probably enumerate the cateogry just once (the first time), and then cache the results. - How will we handle ordering? I'm thinking I'll just sort the keys in the category, and when components register as members of this category, they'll just prefix themselves appropriately. (i.e. maybe "100 bookmarks" for bookmarks, "200 cache" for cache, etc, so we have room for expansion) - The "charset guesser" interface will have to have some way to provide context to the guesser - for now I'll probably just provide enough context such that we can handle the two most important cases (bookmarks and cache) and then figure out how to do harder ones (like http headers, which will need to know what channel it came in on, etc)
No longer depends on: 100107
Blocks: 100107
Status: REOPENED → ASSIGNED
I have an alternative approach for your consideration. Instead of using out-of-band channel to transfer charset info, we can simply use http data stream to perform such task. The idea is to add a internal tag before real html data, just like the invention of meta tag. It is something like: <MOZ-META Charset="Shift-JIS" CharsetSource="HTTP-Header"> Such tags are soly internal and must appear before real html data, and they should be optional to parser. When charset is found in http header, network module can just send such a string before any real data. Parser will be notified when it is parsing the data. Similar stories for cache, bookmark. (We still need to leave user default, user forced, meta charset, parent frame, and autodetect there.) Those tags will be stored in cache, and that will give parser more information about how the charset is achieved. Besides charset information, we can probably put more things there, or even extend it to be a general out-of-band information exchange method. That might help break other inter-module dependency.
An interesting idea.. but personally I think that places an unnecessary burden on the HTTP protocol to insert HTML-specific code into the stream. For example, what if I retrieve a text file over HTTP? We can't insert the tag into that stream because we won't be creating an html document. That means that the HTTP protocol has to have special knowledge of the "text/html" type so that it knows that it is appropriate to insert this tag. And besides, that doesn't even solve the problem of getting the information from bookmarks or the cache. Personally, I think that we need to create such a mechanism anyway for bookmarks/cache, we might as well make it accomadate http. However, HTTP is a lower priority, because there are other dependencies on necko/http as it is.
Keywords: intl
QA Contact: andreasb → ylong
"Content-Type" is available in http header. That's not a problem. Cache is the easiest to handle. We need to just include those internal tags. Bookmark is something I have less knowledge. I hope there is an available mechanism for it to send such hints to network and let network module do the work.
I don't understand your objection to the category idea.. you've provided another suggestion, which is fine, but I don't see why it's better than using categories. The HTML-specific idea is ok, but it doesn't address all cases, and (as I said earlier) it makes such modules have unnecessary dependencies on html, not to mention adding an extra burden on the parser to be aware of data that might be in the stream before the actual file... Also, what would we do in the case of a text file which is encoded in some particular character set? I also object to it from an architectural perspective because instead of clearly seperating the stream and its encoding, we are inserting the encoding into the stream. I think an out-of-band solution is actually more architecturally sound. Also, cache and bookmarks can't get involved in the stream: - cache isn't always involved - sometimes the data is coming over the net, but the code (as it stands today) will look to the cache in case the newer version of the file does not have an associated encoding. - there's no way for bookmarks to get involved in the stream without adding extra hooks into necko, and it seems wierd to rearchitect necko to add this functionality. Again, what is the objection to the category method? I'm the one who will be implementing this, so its not extra work for you :)
Sorry for the misunderstanding. I have no objection to your category idea. I just want to mention an alternative approach for your consideration. It is all up to you to analysis the pro and con of each approach and use the one that you believe is better.
Priority: P2 → P1
Target Milestone: mozilla0.9.5 → mozilla0.9.6
Priority: P1 → P2
Target Milestone: mozilla0.9.6 → mozilla0.9.7
Summary: Need a generic way to guess at charset → Need a generic way to guess at charset (layout depends on bookmarks)
*sigh* pushing out to 0.9.8, I just have too many little bugs that are more important.
Target Milestone: mozilla0.9.7 → mozilla0.9.8
*** Bug 111336 has been marked as a duplicate of this bug. ***
bad news: gotta move these bugs to 0.9.9, I have too much on my plate right now.
Target Milestone: mozilla0.9.8 → mozilla0.9.9
Priority: P2 → P3
Target Milestone: mozilla0.9.9 → mozilla1.1
Keywords: topembed
topembed-, embed keep working this. take for later releases -triage team (chofmann, cathleen, marcia)
Keywords: topembedembed, topembed-
Priority: P3 → P2
woah, 1.1 came up quick. Throwing these bugs over to 1.2.. little or no work has been done and there is no way that these bugs can be fixed in 1.1.
Target Milestone: mozilla1.1alpha → mozilla1.2alpha
Target Milestone: mozilla1.2alpha → mozilla1.2beta
many embeddors don't use our bookmarks impl.
Keywords: topembed-topembed+
ok, here's the investigation I've done: Functions called to guess the charset, and data they need (in parentheses) TryUserForcedCharset (muCV, dcInfo) muCV <- docshell <- aContainer dcInfo <- docshell <- aContainer TryHintCharset (muCV) muCV <- docshell <- aContainer TryParentCharset (dcInfo) dcInfo <- docshell <- aContainer TryChannelCharset (channel) aChannel TryBookmarkCharset (urlspec) urlSpec <- url <- aChannel ** url is needed later for NS_NewHTMLContentSink ** TryCacheCharset (cacheDescriptor) cacheDescriptor <- cacheToken <- cachingChan <- httpChannel <- aChannel ** cacheDescriptor is later used to set the charset ** TryDefaultCharset (muCV) muCV <- docshell <- aContainer UseWeakDocType (none) later, if it is a post, GetPrevDocCharset (muCV) muCV <- docshell <- aContainer all data eventually comes from aContainer, aChannel: docshell used by 5 consumers (2x by one) - almost all muCV used by 4 consumers, can also come from parent, can be used later to set the previous doc's charset dcInfo used by 2 consumers url/urlspec used by 1 consumer httpChannel used by 1 consumer so here's the thought: a new interface nsICharsetDetector : nsISupports { // @returns true if the handler will handle it later. If so, then the // resulting closure object should be passed to postCharset() with the // detected charset boolean detectCharset(in nsIDocShell aDocShell, in nsIChannel aChannel, out nsISupports aClosure); void postCharset(in nsAString aCharset, nsISupports *aClosure); }; so in the case of the cache and the bookmarks method, postCharset() will go back and set the charset of the cache entry or the bookmark entry. The URL might also come out of that. Each charset detector will implement the above interface via a service object of some kind. Initially, I'll just have a static, ordered list of contractIDs to try but eventually I'd like to get to the point where we're using categories. the trick there is to make sure we order the categories correctly.
Attached patch prep work, new interface (obsolete) — Splinter Review
ok, this patch: - cleans up nsHTMLDocument to move all the charset guessing code into a function GuessCharset() - adds the new interface - makes the bookmark service implement the new interface, which prompted me to make some string changes to the bookmark service Reviews?
Attached patch prep work, new interface (obsolete) — Splinter Review
oops, lets try that again... here's the actual patch.
Attachment #103815 - Attachment is obsolete: true
These bugs missed the 1.2 train. Moving these out to 1.3alpha
Target Milestone: mozilla1.2beta → mozilla1.3alpha
alec, I went through the code. Most of the code is just reorganization. Your new interface is not used anywhere. I understood that this is a preparation work only. I didn't have much to say about the code, I didn't spot any problem there. I have some suggestion towards naming and your interface design. 1, charset detector is a name we heavily used for "real" charset detection. Ie, given a binary stream, we detecting the encoding of this stream. So you might want to use a different word for this purpose. I suggest CharsetResolver in this context. 2, I would suggest you to use "AString" to replace "ACString" in your intereface design. We are using UTF-16 for charset representation in most of the places, so there is no need to do this conversion. This might be critical when non-ascii character get into character set name, though very unlikely. 3, In detectCharset function (as I mentioned in 1, I suggest to rename it as resolveCharset or queryCharset), I would suggest you to add a additional aurgument so that charset source can be returned. When I was fine tuning charset resolution, I found sometimes it is necessary to discriminate charset even they came from the same source. For example, charset from parent was later categorized as kCharsetFromParentForced and kCharsetFromParentFrame. This may happen on other category as well. Using bookmark as another example, a user manually set a page to certain character set (forced charset) and a charset being detected by computer might need to be treated different if user has such request. When such information need to be recorded by bookmark, your interface should be able to transfer this information back to caller. 4, I didn't quite understand how "postDetection" is supposed to be used. Our charset auto detection will set notification to webshell/parser if it detected a new charset in late stage, Is this function aimed for that purpose as well?
shanjian, Thanks for your review... from what I understand, charset NAMES are always ASCII, at least the way we use them in mozilla. In fact, there are many places where we do raw ASCII/UCS2 conversion of charset names so I doubt that non-ASCII charset names would even work in our product as it stands today. But that is the subject beyond the scope of this bug. (In fact one of my other footprint tasks is to convert the charset conversion APIs over to using ASCII (or at least UTF8) charset names (using nsACString&) - I'll need to talk with you a little about that later, but in the meantime I think this is the right thing to do.) and so, addressing the rest of your review: 1) I like Resolver, I'll switch to that. 2) (covered above) - I'd like to leave it as it is and assume ASCII 3) I'll add the "source" output, as you describe. 4) oh yeah I didn't explain that well. postDetection is going to be used by some of the other resolvers - it basically lets the resolver clean up after the detection. So after the initial detection happens, certain resolvers will want to be notified of the charset that they were just asked about. For example, the cache might fail to detect a charset, but it is interested in the charset of the URL so that it has it for next time. basically, it is needed to maintain the current behavior when we switch to this new mechanism.
Target Milestone: mozilla1.3alpha → mozilla1.4alpha
mass moving lower risk 1.4alpha stuff to 1.4beta
Target Milestone: mozilla1.4alpha → mozilla1.4beta
Missed the 1.4b train, will this be targetted for final 1.4 or 1.5 alpha? Please re-set the milestone accordingly.
Target Milestone: mozilla1.4beta → ---
ok, I've finally gotten to this. This is the minimal work necessary. What this does now is add a new interface (nsICharsetResolver) as described above, and does the absolute minimum to make nsHTMLDocument::TryBookmarks() call through this interface rather than nsIBookmarks service. this remove dependencies on appcomps but of course introduces a common dependency on chardet. it also adds a dependency on htmlparser (for nsIParser.h, for kCharsetFromBookmarks) This will get us out of our current predicament, and lays the groundwork for making this way more generic. Someone care to review?
Attachment #103816 - Attachment is obsolete: true
I should add that obviously the kCharsetFromBookmarks dependency is temporary for now. I haven't decided if these constants belong as a part of the nsICharsetResolver interface (Which would suck, because that would mean nsICharsetResolver would have implicit knowledge of all possible resolvers) for now we'll just continue to depend on the C++ #defines.
oh, and that kQuote/kSpace thing is because nsIParser.h defines two global variables that conflict in name (they are 'const PRUnichar' in nsIParser.h and 'const char[]' in nsBookmarksService.cpp)
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies requesting r / sr - brendan/shanjian please see my previous comments (starting with comment 25) - they explain some of the oddities of this patch.
Attachment #123328 - Flags: superreview?(brendan)
Attachment #123328 - Flags: review?(shanjian)
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies >+++ intl/chardet/public/Makefile.in 14 May 2003 21:36:24 -0000 >@@ -31,6 +31,7 @@ MODULE = chardet > XPIDLSRCS = \ > nsIDocumentCharsetInfo.idl \ > nsIDocCharset.idl \ >+ nsICharsetResolver.idl \ Wrong tabstops -- use 8-space equivalent tabs, no spaces. >+ /** >+ * requestCharset >+ * called to resolve the charset of an existing docshell. >+ * If the charset cannot be resolved, but the implementation is >+ * still curious what the final charset turned out to be, it can >+ * set wantCharset to true. >+ * If so, notifyResovedCharset will be called with the resulting >+ * closure >+ * >+ * @param docShell the docshell the document is being loaded in >+ * @param channel the channel the document is coming in from >+ * @param charsetSource a unique number which can be stored by the >+ * caller to remember which resolver actually >+ * resolved the charset. >+ * @param wantCharset gets set to true if notifyResolvedCharset should be >+ * called with the given closure object Is the wantCharset machinery really necessary? Seems unused, and when in doubt, leave it out applies. Where's the mozilla/browser patch? /be
Yes, its needed for the cache.... I wouldn't have written it if it wasn't going to be used. :) Its actually the mechanism that the cache uses to store the charset of the page so a page doesn't need to be re-detected when loaded from the cache. Note that this fix only fixes up bookmarks - the goal is to remove all these dependencies (Such as the cache) from this charset detection code - this one hunk of code is responsible for a number of ugly dependencies.
oops, brendan please see my previous comments - I loaded another page before the bugmail went out.
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies I talked with Jan on IRC and he says that nsIBookmarksService is forked from mozilla to phoenix. The difference will be that the QI will fail, and TryBookmarksCharset() will return early.
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies sr=brendan@mozilla.org with the makefile tab fix. I didn't realize there was more coming, including cache-related changes. In this bug, or a new one? /be
Attachment #123328 - Flags: superreview?(brendan) → superreview+
well, I was originally planning on doing the global architecture changes for this bug - there are bunch of unnecessary dependencies (seem comment 0 and comment 2) - that's why this patch is just a quick hack to get rid of the bookmarks dependency...but it lays the groundwork for future work short answer: yes, in this bug.
*** Bug 201821 has been marked as a duplicate of this bug. ***
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies trying a new reviewer.. jshin can you give me a review here? there is no functionality loss here, just a architecture change to reduce dependencies.
Attachment #123328 - Flags: review?(shanjian) → review?(jshin)
Comment on attachment 123328 [details] [diff] [review] new patch - does minimal work to remove dependencies r=jshin. sorry for the delay. Because shanjian did a thorough review regarding the interface and this is the minimal patch, I don't have any to add. A _brief_ test with the patch didn't show a sign of the regression, either.
Attachment #123328 - Flags: review?(jshin) → review+
Summary: Need a generic way to guess at charset (layout depends on bookmarks) → Need a generic way to guess at charset (layout depends on cache/etc)
Alec, this looks done, are there any barriers to checking it in?
oh, sorry. the bookmarks stuff already landed. cache and http come next.
So I'm looking at the api this bug introduced, and I don't see how callees could possibly set charsetSource in general. That number needs to fit into our hierarchy of nsIParser charset sources, and that's a private interface. So an embeddor who wants to set charsets from bookmarks cannot use it. Also, given that HTMLdocument has to instantiate the resolver to call it, it at least knows what contract it's instantiating and therefore can decide for itself what the charset source should be. Other than that, this patch leaves us depending on the fact that bookmarks are RDF, which may not be true in an embedding app....
ccing vlad too, since bookmarks are involved.
so my original plan (which I never followed through on, sorry) was to make a category of charset resolvers, which would be iterated in some order, asking each one to resolve the charset. What you see here was the first step. obviously right now we're just instantiating the interface the sourceCharset was definitely something I hadn't quite worked out. I'm not even sure its used anywhere, I think it might just be recorded for posterity. Other options include just keeping a pointer to the charset resolver rather than some magic number which indicates the source.
The charset source is heavily used in HTML document, parser, etc. That's how we ensure that higher-priority sources (eg user override, HTTP header, etc) don't get clobbered by lower-priority sources (eg bookmarks). There is no way to use a pointer to the resolver for this purpose. If we had a category, we would need to somehow order the things within the category and somehow interleave them with the internal charset sources we have. In any case, we wouldn't want to have the charset source in the API itself.
Attached patch Possible change for discussion (obsolete) — Splinter Review
The goal here is to allow embeddors to make use of this. This means no nsIParser dependency, no RDF dependency....
Blocks: 284660
Comment on attachment 176175 [details] [diff] [review] Possible change for discussion I like it.. simple and to the point :)
Attachment #176175 - Attachment is obsolete: true
Attachment #176181 - Flags: superreview?(alecf)
Attachment #176181 - Flags: review?(benjamin)
Attachment #176181 - Flags: review?(benjamin) → review+
Comment on attachment 176181 [details] [diff] [review] Same but compiling [checked in] sr=alecf
Attachment #176181 - Flags: superreview?(alecf) → superreview+
Comment on attachment 176181 [details] [diff] [review] Same but compiling [checked in] Checked this in.
Attachment #176181 - Attachment description: Same but compiling → Same but compiling [checked in]
QA Contact: amyy → i18n
Bug 700490 is proposing backing out the patches that landed here.
Assignee: alecf → smontagu
Keywords: embed, intl, topembed+
OS: Windows 2000 → All
Priority: P2 → --
Hardware: x86 → All
Attachment #176181 - Flags: checkin+
Per bug 700490 and events since then.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago9 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: